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 的实现细节,持续构建在 Java 9+ 的 Windows 和 macOS 上通常无法很好地工作。可能需要长达 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 仍然可以自动检测已安装的工具链,但我们通过 Toolchain Resolver Plugin 提供了更高的配置灵活性。这为您提供了更大的灵活性和控制权,让您可以选择从哪里获取 JDK,以便您可以使用与您的需求相匹配的特定 JDK。
Build Scan™ 现在显示 Java 工具链的使用情况
测试套件
编写测试时的一个常见用例是对测试类进行分组,以便将它们组织成可管理的小块,这样您就可以在构建管道中的不同频率或不同点运行它们。例如,您可能想要定义 单元测试 、 集成测试 和 功能测试 组。正确地执行此操作需要深入了解如何在 Gradle 中修改和连接各种域对象,例如 SourceSets、配置和任务。
您会很高兴地知道,通过 引入测试套件,该过程已大大简化。JVM 测试套件插件 简化了创建此类称为测试套件的测试组的过程。请注意,这不应与测试框架套件混淆,例如 JUnit4 的 Suite 或 JUnit Jupiter 的 Suite Engine。
测试套件是一个高级声明性概念,可以直接在构建脚本中引用。您可以配置依赖项、源和测试使用的测试框架,而无需担心低级细节。
例如,您可以通过将以下代码片段添加到 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
,有时是 包含构建。在大规模情况下,有时包含构建性能更高,有时 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 中的所有新功能。
在升级之前,您应该