Gradle 8.0 新功能
自 7.0 版以来 Gradle 8.0 的新功能。
目录
Gradle 8.0 标志着 Gradle 在革新构建自动化和提高开发者生产力这一持续使命中的下一个重要里程碑。继 2021 年 5 月发布 Gradle 7.0 之后,我们一直致力于简化可用性,使执行常见任务变得毫不费力,让您能够专注于最大化生产力。
自 Gradle 7.0 以来的主要改进分为以下几类:
立即升级,在您的构建中尝试这些功能,或使用 Gradle 开始一个新项目。
如果您想了解最新的 Gradle 功能和其他开发动态,请订阅我们的新闻通讯,并在 Twitter 或 Mastodon 上关注我们。
性能
缓慢的构建可能会产生不利影响,而更快、更频繁地交付产品非常重要,特别是对于像 Square 这样的大公司。Gradle 的每个版本都以提高性能为目标,确保每次迭代都超越前一个版本。
配置缓存
更快的配置时间
每个 Gradle 构建都有一个生命周期:初始化、配置和执行。许多性能特性都集中在执行阶段;然而,配置阶段也可能非常耗时。如果没有配置缓存,即使配置没有任何变化,配置阶段也需要重复执行。
为了改善这种情况,6.6 版引入了一个名为配置缓存的实验性功能。它通过缓存结果并在后续构建中重用,从而降低了配置阶段的成本。只有当项目配置方式发生变化时,配置阶段才需要运行。这是 Gradle 8.0 中的一个可选功能,它为人们节省了大量时间。在 Gradle 8.1 中,配置缓存将成为稳定功能。
通过并行化实现更快的执行
使用 –parallel 标志并行运行任务已经可以改善构建时间。但是,同一项目中的任务不允许并行执行,除非它们被专门编写成可以并行。启用配置缓存后,Gradle 可以实现更好的并行性。
当启用配置缓存时,即使没有 –parallel 标志,Gradle 也会并行运行任务。所有任务都可以并行运行,甚至包括同一项目内的任务,因为配置缓存可以防止任务之间相互干扰配置。与配置缓存兼容的任务无需更改即可实现并行安全。
更快的 Java 编译
更快的增量编译
默认情况下,Gradle 使用 Java 增量编译器,仅编译需要编译的 Java 源文件,从而加快构建速度。增量编译已经存在超过 5 年,但一些用户在使用大型源码集时开始遇到性能瓶颈。
增量编译通过分析类之间的关系来工作。以前,这种分析只保存在本地,这使得 Gradle 在从构建缓存中命中缓存后无法立即执行增量编译。在具有大型源码集的项目中,缓存命中后重新编译所有源文件的成本抵消了缓存命中节省的时间。
现在,增量分析结果会保存在构建缓存中。因此,在缓存命中后的编译将是增量的。
此外,与 Gradle 7.0 相比,增量编译分析变得更快,并且使用的内存更少。
这些变化的影响因项目而异,但可能非常巨大。在 Gradle 项目本身,这些变化使增量编译速度提高了两倍!
常量的更改不再触发完全重新编译
由于 Java 编译器的工作方式,以前的 Gradle 版本在某个上游依赖项中的*任何*常量发生变化时,都不得不执行完全重新编译。
Gradle 现在会跟踪常量的使用情况,并且只重新编译那些使用了已更改常量的类。
对于那些包含许多常量(例如模板引擎生成的代码)的类,这可以加速增量构建。
Java 编译在不同操作系统之间获得更多缓存命中
Gradle 通过查看任务的输入来计算其缓存键。在不同操作系统上检出源代码时,换行符的差异可能导致任务的输入看起来不同,即使任务产生的输出是相同的。
Gradle 现在在编译 Java 代码时会对源文件中的换行符进行规范化,以便在不同操作系统之间获得更好的缓存命中率。
响应更快的持续构建
当输入发生变化时,持续构建会自动重新执行带有指定任务的构建。这为开发过程提供了持续的反馈。
由于一些新版 JDK 的实现细节,持续构建在 Windows 和 macOS 上的 Java 9+ 环境中通常表现不佳。检测到更改并触发构建可能需要长达 10 秒的时间。
当使用新版 Java 运行 Gradle 时,持续构建在 Windows 和 macOS 上能对更改做出快速响应。Gradle 现在使用自己强大且原生实现的文件系统监视系统,而不是依赖于 JDK 中的通用 API。
可用性
Java 工具链
您可能熟悉因使用错误 Java 版本而导致构建失败的痛苦,但使用正确的供应商同样重要。Java 工具链支持是在 Gradle 6.7 中引入的,允许您为项目指定 JDK。自那以后,工具链已成为强制执行此规定的最佳方式,并在 7.x 系列和 8.0 中持续提供支持。
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
vendor.set(JvmVendorSpec.ADOPTIUM)
}
}
Gradle 仍然可以自动检测已安装的工具链,但我们通过工具链解析器插件提供了更高的配置灵活性。这使您在获取 JDK 的来源方面拥有了更大的灵活性和控制权,以便您可以使用符合您需求的特定 JDK。
Build Scan™ 现在会显示 Java 工具链的使用情况
测试套件
编写测试时的一个常见用例是将测试类分组,以便将它们组织成可管理的块,从而可以在构建管道的不同频率或不同时间点运行它们。例如,您可能想定义*单元测试*、*集成测试*和*功能测试*等组。要正确地做到这一点,需要深入了解如何在 Gradle 中修改和连接各种领域对象,如 SourceSet、配置和任务。
您会很高兴地知道,通过引入测试套件,这个过程已大大简化。JVM 测试套件插件简化了这类测试组(称为测试套件)的创建。请注意,这不应与测试框架的套件混淆,例如 JUnit4 的 Suite 或 JUnit Jupiter 的 Suite 引擎。
测试套件是一个高级的声明性概念,可以在构建脚本中直接引用。您可以配置依赖项、源代码以及测试所使用的测试框架,而无需担心底层细节。
例如,您可以通过向 Java 项目添加以下代码片段来创建一个*集成测试*套件:
testing {
suites {
// Add a new test suite
integrationTest(JvmTestSuite) {
// Use JUnit Jupiter as a testing framework
useJUnitJupiter('5.7.1')
// depend on the production code for tests
dependencies {
implementation project
}
}
}
}
// Run integration tests as part of check
tasks.named('check') {
dependsOn(testing.suites.integrationTest)
}
版本目录
Gradle 在 7.0 版本中引入了版本目录作为一项实验性功能。如果您还没有尝试过使用版本目录来管理您的依赖项,现在是时候切换了。它用于在一个中心位置,即 gradle/libs.versions.toml
文件中,声明您构建中使用的所有直接依赖项的版本。其优点包括类型安全的访问、跨依赖项的通用版本控制以及将依赖项捆绑在一起。
在 7.x 系列和 8.0 版本中,版本目录在许多方面都得到了改进。以下是一些具体示例。
声明插件版本
版本目录已经支持声明库的版本。然而,这些声明在 plugins
和 buildscript
块中无法访问。这个限制现在已经取消,可以在 TOML 文件中声明插件,例如:
像这样在 plugins 块中使用它们:
版本目录类型不安全 API 的变更
当使用类型不安全的 API 时,所有接受别名引用的方法现在都可以使用与别名定义相同的字符串。这意味着您可以声明和引用 groovy-json
,而无需在类型不安全的 API 中强制使用 groovy.json
。
请注意,对类型不安全 API 的访问方式已发生变化;详情请参阅升级指南。
Kotlin DSL
Gradle 的 Kotlin DSL 为传统的 Groovy DSL 提供了一种替代语法,在支持的 IDE 中提供了增强的编辑体验、卓越的内容辅助、重构、文档等功能。我们投入了大量精力来确保 Kotlin 的体验是卓越的。
改进的脚本编译性能
在许多情况下,Kotlin 脚本的编译传统上比 Groovy 脚本的编译慢。Gradle 8.0 通过为 .gradle.kts
脚本中的声明式 plugins {} 块引入解释器,可以将 Kotlin 脚本的编译速度提高多达 20%。默认情况下,避免了为声明式 plugins {}
块调用 Kotlin 编译器。
要从这一性能改进中受益,请在 plugins {}
块中使用支持的格式。有关插件语法的更多信息,请阅读关于受限语法的文档。
在 Kotlin DSL 中对 repositories {} 的扩展进行类型安全的访问
Kotlin DSL 为添加到 repositories {}
块的自定义扩展生成类型安全的模型访问器。自定义扩展在 IDE 中拥有完整的内容辅助功能。
例如,[asciidoctorj-gems-plugin](https://asciidoctor.github.io/asciidoctor-gradle-plugin/master/user-guide/#asciidoctorj-gems-plugin)
插件添加了一个自定义扩展。您不再需要使用 withGroovyBuilder
,而是可以使用这种简洁的语法:
构建配置
构建配置多年来经历了许多变化。当前的最佳实践有时是使用 buildSrc
,有时是使用包含的构建 (included builds)。在大规模项目中,有时包含的构建性能更好,有时 buildSrc
性能更好。性能取决于具体结构。然而,许多项目仍在使用 apply 脚本(缺乏 IDE 自动补全)甚至 allprojects/subprojects(这使得确定共享配置的来源变得困难,并且不够灵活,性能也不佳)。
为了统一 buildSrc
和包含的构建,buildSrc 正在改变,使其行为更像包含的构建。请注意,这意味着 buildSrc
的测试不会自动运行,您可以通过命令行像处理常规包含的构建任务一样来处理 buildSrc 任务。
如果您已经在使用 buildSrc,请继续使用并享受新功能。如果您已经在使用包含的构建,请继续使用它们。如果您的构建性能需要改进,请尝试两种解决方案,并为您的项目选择最佳组合。
生态系统支持升级
支持 Java 17 到 19
Gradle 支持在 Java 17、18 和 19 上进行编译、测试和运行。
支持 Groovy 4
Gradle 支持使用 Groovy 4.0 构建软件。请注意,Groovy DSL 构建脚本仍然使用 Groovy 3。
更新的 Scala 编译器
默认的 Scala Zinc 版本已更新至 1.6.1。
Zinc 是 Scala 的增量编译器,它允许 Gradle 始终只编译当前文件更改所需的最少文件集。它会考虑哪些方法被使用以及哪些发生了变化,这意味着它比文件间的依赖关系更具粒度。
Kotlin DSL 中的新 Kotlin 功能
使用 Kotlin DSL 编写的构建脚本使用 Kotlin API 级别 1.8。以前,构建脚本仅限于 Kotlin API 级别 1.4。这一变化带来了自 Kotlin 1.4.0 以来对 Kotlin 语言和标准库的所有改进。
有关此升级中破坏性和非破坏性更改的信息,请访问升级指南。
如何升级
我们提供了一份文档,以帮助您从 Gradle 7.x 升级到 Gradle 8.0。如果您使用的版本低于 Gradle 7.0,您可能需要先查看Gradle 7.0 的所有新功能。
在升级之前,您应该: