Gradle 5.0 正式版本发布,一大波新特性来袭

15,614 阅读7分钟

前言

在历经了一年多时间, 20 个 4.x 系列版本的迭代后,Gradle 官方终于在 11月26日 发布了 5.0 的正式版本,先放上一张官方各版本 Gradle 性能对比图

官方表示这是至今为止最快、最安全,最强大的版本。

  • 改进的增量编译
  • 更快的构建速度
  • 细粒度的传递依赖管理
  • 更高效的内存执行等等。
  • ......

让我们赶紧来看一下有哪些令人激动的新特性。

官方新特性一览

  • Kotlin DSL 1.0
  • Dependency version alignment
  • Gradle build initialization features
  • Searchable documentation
  • Task timeouts
  • HTTP retries during dependency resolution
  • Java 11 runtime support
  • Plugin authoring features
  • Gradle Native features
  • Promoted features

我擦,感觉一脸懵逼,没关系,下面我会针对这些特性做些简要的总结和说明,内容可能比较多,但是干货满满,建议耐心阅读下去。

Kotlin DSL 1.0

早在 Gradle 4.x 版本中就已经支持了通过使用 Koltin DSL 的方式去编写构建脚本,但是当时刚出来,很多地方支持的还不太好(需要踩坑),所以并不推荐大家迁移过去,而是尝鲜为主。现在 Kotlin DSL 1.0 release 版本出来后,意味着接下来你可以放心的迁移或者使用 Kotlin DSL 啦。新版本做了很多优化和改进的地方,比如:

  • Code Completion:代码自动完成

  • Error Highlighting:错误高亮

  • Quick Documentation:文档快速提示

  • Refactoring:代码重构

    图片来自官方

如何迁移你的构建语言到 Kotlin DSL 上,可以参考我的另一篇文章Gradle指南之从Groovy迁移到Kotlin

Dependency version alignment

Dependency version alignment allows different modules belonging to the same logical group (a platform) to have identical versions in a dependency graph.

根据官网的介绍,直译过来的意思是:依赖版本一致性允许属于相同的逻辑组(平台)的不同module 拥有相同的版本依赖图。

这个概念确实不好理解,我自己也是花了一些时间去理解和消化。还是通过一个示例来说明吧。如果有英文水平高或者理解能力比较强的同学,欢迎指教。

比如,我们 build.gradle 有以下依赖:

	dependencies {
	    // a dependency on Jackson Databind
	    implementation 'com.fasterxml.jackson.core:jackson-databind:2.8.9'

	    // and a dependency on vert.x
	    implementation 'io.vertx:vertx-core:3.5.3'
	}

因为 vertx-core 也间接依赖了 jackson-core,通过依赖传递,当解析依赖信息的时候,我们实际依赖的版本号是:

  • jackson-core 版本 2.9.5(依赖传递)
  • jackson-databind 版本 2.8.9 -> 2.9.5(低版本通过依赖仲裁变为高版本)
  • jackson-annotation 版本 2.9.0 (jackson-databind 2.8.9 版本间接依赖 jackson-annotation 2.9.0 版本,注意这里,因为上面的依赖仲裁,变成了被高版本 的 jackson-databind 2.9.5 所依赖)

这里建议有兴趣的同学实际在 intellij IDEA CE 里建个简单的 Gradle 工程,根据上面说的步骤实际操作一遍就很容易理解了。

再举个小例子,看下下面的依赖关系:

	+--- com.google:gson:1.0.0 -> 2.0.0
	|    \--- com.google:gson-test:1.0.0
	+--- commons-io:commons-io:2.0.0
	  \--- com.google:gson:2.0.0

gson 被仲裁到 2.0.0 高版本,而 gson-test 还是 1.0.0 版本,相当于原来是 gson:1.0.0 依赖的是的 gson-test:1.0.0 ,现在变成了高版本的 gson:2.0.0 依赖了低版本的 gson-test:1.0.0,这样就很有可能会出现一些未知问题。理想的依赖应该是 gson:2.0.0 依赖的 gson-test:2.0.0。

通过以上的分析,我们发现实际上解析出来的依赖库版本出现了和预期不一致的情况,而类似这种情况很容易会导致一些未知问题,尤其是在一些不兼容老版本接口的依赖库里就会直接导致 Crash。

通常,针对这种问题,之前的做法可能就是简单粗暴的强指定版本号,不过,现在有了更加优雅的方式去帮助我们去管理版本,即 Dependency version alignment,我们可以通过指定一个 platform 去管理某一组的 module

回到刚才的场景示例中,我们在 build.gradle 里可以定义 jackson 为一组的 module 版本的规则,如下所示:

	class JacksonAlignmentRule implements ComponentMetadataRule {
	    void execute(ComponentMetadataContext ctx) {
	        ctx.details.with {
	            if (id.group.startsWith("com.fasterxml.jackson")) {
	                // declare that Jackson modules all belong to the Jackson virtual platform
	                belongsTo("com.fasterxml.jackson:jackson-platform:${id.version}")
	            }
	        }
	    }
	}

然后应用该规则:

	dependencies {
	    components.all(JacksonAlignmentRule)
	}

最后,在执行完 ./gradlew app:dependencies 命令后,你会发现当匹配上 com.fasterxml.jackson 组的 module 的版本都保持了一致,也就是

  • jackson-core 版本 2.9.5
  • jackson-databind 版本 2.8.9 -> 2.9.5
  • jackson-annotation 版本 2.9.0 -> 2.9.5

另外,platform 同样也提供了强制为一组 module 指定某个版本号,比如:

	dependencies {
	    // Forcefully downgrade the Jackson platform to 2.8.9
	    implementation enforcedPlatform('com.fasterxml.jackson:jackson-platform:2.8.9')
	}

还有一个比较方便的地方,就是通过 platform,我们可以直接省略该 module 的版本号(从此告别通过定义版本变量去维护众多 module 的版本信息),如下所示:

	dependencies {
	    // import a BOM. The versions used in this file will override any other version found in the graph
	    implementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))

	     // define dependencies without versions
	    implementation("com.google.code.gson:gson")
	    implementation("dom4j:dom4j")

	     // this version will be overriden by the one found in the BOM
	    implementation("org.codehaus.groovy:groovy:1.8.6")
	}

Gradle build initialization features

新版本对 gradle init 方法进行了升级,通过更多的特性和交互,来帮助我们去快速初始化一个 Gradle 项目。简单来说的话,就是加强版的脚手架。

Interactive mode

当你在控制台执行 init task 后,Gradle 将会提供更多的构建信息提示,来帮助你生成 Gradle 模版项目。

Kotlin library and applications

init task 可以通过 kotlin-library 或者 kotlin-application 类型来设置生成一个 Kotlin 的类库或者应用。你只需要根据它的提示来操作即可。

Generated builds use recommended configurations

init task 生成的构建脚本将推荐使用新的 implementationtestImplementationtestRuntimeOnly 去代替 compiletestCompiletestRuntime

Configure project and source package names

  • --project-name 选项可以帮助你调整生成的项目名称
  • --package 选项可以帮助你调整生成的项目包名

Create resource directories

init task 会创建一个空的 resource 目录

Create a .gitignore file

init task 会生成一个简单的 .gitignore 文件来帮助你设置你的 Git repository 。

Searchable documentation

Gradle 的文档搜索功能回来了(虽然我一直不知道这个功能在哪里),总之,可以更加方便的搜索用户手册和 DSL 的描述。

当然,还有更方便查找类和方法的 Gradle API Javadocs

Task timeouts

这个超时设置简直太有用了有木有。特别是当你因为一些网络原因,导致你的 build task 一直卡在那里的时候,你的心里一定是万马奔腾的感觉,赶紧用起来吧,不要再浪费这些无用的时间了。示例:

	task hangingTask() {
	    doLast {
	        Thread.sleep(100000)
	    }
	    timeout = Duration.ofMillis(500)
	}

HTTP retries during dependency resolution

HTTP 访问重试功能,嗯。挺好

Performance features

Gradle can be started as a low-priority process

通过 --priority low 命令参数或者 org.gradle.priority=low 属性设置可以让你的 Gradle 以一个低优先级的进程启动,至于好处嘛,当然是你一边在 building 的时候,一边听音乐的时候,再也不会感觉一卡一卡的了 :)

JaCoCo plugin now works with the build cache and parallel test execution

简单看了下介绍,可以帮助你查看代码覆盖率的 JaCoCo 插件,感兴趣的同学可以点这里了解更多

Java 11 runtime support

Gradle 5.0 版本构建支持 Java 11 版本

Plugin authoring features

这个版本为插件和自定义 task 提供了创建 SourceDirectorySet 的 API、提高 Provider 的 API、和构建缓存的兼容性提高。

Gradle Native features

Gradle Native project 持续的改善和提升 native 生态系统, 更多细节:Changes included in Gradle 5.0

Promoted features

一些现有功能的提升,详细点击这里

其他

5.0 版本共计修复了 166 个 issues(惊人),当然,伴随而来的还有一些已知的 issues ,详细可以点击这里 5.0 release-notes

总结

Gradle 5.0 版本真的是干货满满,尤其是对于使用 Gradle 构建的 Android 或者 Java 开发者来说,像 Kotlin DSL(构建语言)、Dependency version alignment(依赖版本一致性)、Performance features(性能提升) 等等这些特性还是很让人期待的。有兴趣的小伙伴可以赶紧更新一波了。

如何升级到 Gradle 5.0 版本呢,很简单,以下两种方式任选其一

  • 执行 ./gradlew wrapper --gradle-version=5.0 命令

  • 或者直接修改你的 rootProject/gradle/wrapper/gradle-wrapper.properties

      distributionBase=GRADLE_USER_HOME
      distributionPath=wrapper/dists
      distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip
      zipStoreBase=GRADLE_USER_HOME
      zipStorePath=wrapper/dists
    
  • 附上官方升级说明: Upgrade Gradle 4.x to 5.0
  • 需要注意的是:目前 Android 的项目如果要升级到 5.0 版本的 Gradle ,需要配套的升级 Android Gradle Plugin 和 Android Studio 到 3.4 版本,由于 5.0 Gradle 版本刚出来,Android Studio 3.4 版本现在还是预览版,所以建议想升级的小伙伴,再耐心等待一段时间。