Gradle 7.0 的新增功能

自 6.0 版本以来 Gradle 7.0 中的新功能。

Gradle 7.0 banner

Gradle 7.0 是 Gradle 在构建自动化和开发者生产力方面演进的下一步。以下是 Gradle 6.0 到 7.0 之间一些有趣的变更。

Gradle 7.0…

立即升级,在您的构建中尝试这些功能,或者使用 Gradle 开始一个新项目

如果您有兴趣了解 Gradle 的新功能和其他发展动态,请订阅我们的博客并在 Twitter 上关注我们。

我们还发布了关于安卓构建热门问题、依赖管理技术和发布策略的过往网络研讨会视频

Gradle 入门

使用 gradle init 引导新项目

内置的 init 任务可用于快速创建新的 Gradle 构建或将 Maven 构建转换为 Gradle 构建。

Gradle 生成的项目采用了最新的推荐构建编写实践。生成的构建演示了使用 buildSrc 来共享通用构建逻辑,您还可以为 JVM 语言生成多项目构建。

对于从 Maven 转换为 Gradle 的项目,Gradle 支持生成 Groovy DSL 和 Kotlin DSL 脚本。

可下载的 Gradle 示例

Gradle 提供了一个示例索引,以演示可以用 Gradle 构建的不同类型的项目。

这些示例还展示了可以使用 Groovy 或 Kotlin DSL 解决的常见问题,例如向 Java 项目添加集成测试

性能改进

通过文件系统监视加快最新状态检查

对于本地增量构建而言,快速反馈对开发者生产力至关重要。当您的 IDE 使用 Gradle 来构建和运行项目测试时,这一点尤其明显。文件系统监视通过减少确定自上次构建以来发生了哪些变化所需的磁盘 I/O 量,从而加快了本地增量构建的速度。

File system watching improvements

自 Gradle 7.0 起,此优化在所有支持的操作系统上默认启用,包括最新版本的 Windows、Linux 和 MacOS。

请参阅文档了解更多详情。

更快的 Kotlin DSL 脚本编译

Gradle 编译 Kotlin DSL 构建脚本 (*.gradle.kts) 的速度更快,内存压力更小。

当更改共享的构建逻辑(例如 buildSrc 目录中的代码)时,Gradle 还可以完全跳过未受影响的构建脚本文件的编译

使用 Gradle 7.0 编辑 Kotlin DSL 构建逻辑时,大多数构建都可以期待明显缩短的反馈循环。

Kotlin script compilation

使用构建缓存时跳过更多工作,从而加快构建速度

Gradle 包含多项更改,通过有选择地忽略各种不影响系统行为的更改(例如空目录、属性文件中的注释或空格等),提高了构建缓存的命中率。

通过实验性的配置缓存加快构建速度

在运行任何任务之前,Gradle 需要运行配置阶段。目前,这在每次构建调用时都会执行,可能会导致明显的延迟,尤其是在大型项目中。

配置缓存通过缓存配置阶段的结果来提高构建性能。使用配置缓存,当没有任何影响构建配置的更改时,Gradle 可以完全跳过配置阶段,从而使后续构建速度更快。

此外,使用配置缓存时,更多的工作会并行执行,这也加速了构建的执行阶段。

请注意,此功能目前是实验性的,默认未启用,并且截至 Gradle 7.0,并非所有核心插件都支持它。

configuration caching demo

配置缓存文档中了解有关此新功能及其影响的更多信息。

通过增量分析加快 PMD 执行速度

PMD 插件默认使用增量分析。这可以显著减少后续构建中的分析时间。

对于依赖于 PMD 6.0.0 之前版本的构建,您需要明确禁用增量分析

更快的临时构建

临时构建机器在重新下载构建所使用的所有依赖项时会付出高昂的代价。Gradle 7.0 具有以下功能,通过在机器之间重用依赖缓存来限制对此类构建的影响。

重定位依赖缓存

$GRADLE_HOME/caches/modules-2下的 Gradle 依赖缓存可以重定位到另一个目录或主机,用于缓存依赖项。当移动到新位置或植入主机镜像时,如果依赖项已经下载,使用该依赖缓存的构建将无需访问网络来下载构件或元数据。

请注意,创建和使用缓存应使用兼容的 Gradle 版本完成。

请参阅文档了解更多详情。

共享只读依赖缓存

Gradle 提供了在多个 Gradle 实例之间共享依赖缓存的能力。

这使得可以拥有一个包含所有构建所需依赖项的单一共享目录。

  • 每个容器都将有权访问共享的只读依赖缓存,从而避免了构建之间的冗余下载。
  • 此缓存可以在容器之间安全共享,而无需创建其单独的副本。

请参阅用户手册了解如何设置共享依赖缓存。

可用性和新功能

对 JVM 项目的工具链支持

默认情况下,Gradle 使用相同的 Java 版本来运行 Gradle 本身和构建 JVM 项目,但这并不总是理想的。

在不同的开发人员机器和 CI 服务器上使用不同的 Java 版本构建项目可能会导致意外问题。此外,您可能希望使用 Gradle 不兼容的 Java 版本来构建项目。

Gradle 提供了一种方法,通过 java 扩展来设置用于构建和测试项目的工具链。

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(14)
    }
}

Gradle 将检测本地 Java 安装以及来自流行包管理器(如 asdf-vm、jabba 和 SDKMAN!)的其他常见安装位置。如果本地没有可用的与构建要求匹配的 Java 版本,Gradle 将从 AdoptOpenJDK 的网站下载匹配的 JDK。

Java toolchains demo

请参阅用户手册中的工具链文档

构建、测试和运行 Java 模块

Gradle 支持Java 模块系统,提供了编译和执行 Java 模块测试所需的一切。

请参阅附带的示例

处理用户提供凭据的约定

构建有时需要用户提供凭据。例如,可能需要凭据来向构件仓库进行身份验证以发布构件。将凭据放在构建脚本之外是一个好习惯。

Gradle 有一个 API,通过建立一个约定,使用 Gradle 属性来提供凭据,从而使处理凭据变得更容易。这些属性可以作为命令行参数、环境变量或 gradle.properties 文件中的值提供给构建。它还引入了快速失败行为,即当 Gradle 知道构建在某个时候需要凭据但凭据缺失时,会立即失败。

有关使用新 API 向构件仓库进行身份验证的更多详细信息,请参阅用户手册部分以及更新的示例

可以从命令行执行包含的构建的任务

Gradle 允许用户直接从命令行执行包含的构建中的任务。例如,如果您的构建包含 my-other-project 作为一个包含的构建,并且它有一个子项目 sub,其中有一个任务 foo,那么您可以使用以下命令执行 foo

gradle :my-other-project:sub:foo

请注意,与多项目构建不同,运行 gradle build 不会在所有包含的构建中运行 build 任务。如果您想为包含的构建重现此行为,可以向包含的构建中的生命周期任务引入任务依赖

单一依赖项锁定文件格式

依赖锁定是一种在使用动态依赖版本时确保可复现构建的机制。

Gradle 7.0 使用单个锁定文件将动态依赖项锁定到其解析的版本。

以前版本的 Gradle 为每个配置使用一个文件。Gradle 会自动迁移到单一锁定文件。

安全性改进

依赖项验证

典型的项目使用大量外部依赖,这使它们面临使用不受信任代码的风险。例如,有人可能会通过传递性依赖无意中引入恶意代码。同样,您的构建脚本本身也可能通过被攻破的插件而遭受恶意代码执行的风险。

为了减轻这些风险,Gradle 提供了依赖验证。依赖验证可以验证构建期间使用的依赖项和插件的校验和与签名。

通过启用依赖验证,Gradle 将

  • 确保依赖项未被篡改(通过验证其校验和
  • 确保您使用的依赖项和插件的来源(通过验证其签名

从而降低将恶意代码交付到生产环境的风险。

请参阅用户手册,了解如何设置依赖验证的完整说明。

声明独占的仓库内容

Gradle 允许您声明应在哪些仓库中搜索特定的依赖项

Gradle 还允许您声明只能在某个仓库中找到的独占内容,并且不应在任何其他仓库中搜索它。

有关详细信息,请参阅用户手册

验证 Gradle Wrapper 的完整性

Gradle Wrapper 是一个可执行代码的二进制 blob,被检入到数百万个 GitHub 仓库中。接受对 gradle-wrapper.jar 的更改存在安全隐患,这些隐患可能并不明显。

我们创建了一个官方 GitHub Action,允许 GitHub 上的项目自动验证其仓库中的 gradle-wrapper.jar 是由 Gradle 发布的。

Gradle wrapper verification

您仍然可以按照用户手册中的说明手动验证 gradle-wrapper.jar

依赖管理

一致的依赖项解析

不同配置之间的依赖解析是相互隔离的。这可能导致一个问题,即测试的运行时类路径可能使用与生产代码的运行时类路径不同的版本。

为了缓解这个问题,Gradle 允许您声明依赖配置之间的一致性,以便对齐一个类路径与另一个类路径之间公共依赖项的版本。

集中声明仓库

settings.gradle (.kts) 中为整个构建方便地定义仓库

dependencyResolutionManagement {
    repositories {
        mavenCentral ()
    }
}

这允许 Gradle 确保您在构建的所有项目中使用相同的仓库来解析依赖项。通过阅读如何为整个构建声明仓库来了解更多信息。

集中声明组件元数据规则

settings.gradle (.kts) 的中央位置声明组件元数据规则

dependencyResolutionManagement {
    components {
        withModule ('com.google.guava: guava', GuavaRule)
    }
}

您可以在用户手册中了解更多关于全局声明规则的信息。

用于集中声明依赖项版本的实验性版本目录

在多项目构建中,有多种方法可以共享依赖项版本。例如,用户可以直接在构建脚本(在 ext 块中)、外部文件(例如 dependencies.gradle)、buildSrc 中,甚至在专用插件中声明版本或依赖项坐标。然而,之前并没有一种能够结合各种方法优点的标准机制。

Gradle 引入了实验性的版本目录,使构建作者能够在一个常规的配置文件中集中管理其第三方依赖项的坐标(组、构件、版本),并以类型安全的方式声明实际的依赖项。

实验性的类型安全项目访问器

Gradle 有一个实验性功能,用于类型安全项目访问器,它可以在 IDE 中为声明对其他项目的依赖项提供代码补全功能。

构建编写

使用包含的构建进行本地插件开发

将插件作为复合构建的一部分进行开发,以便在约定插件中组织构建逻辑,到目前为止仅对项目插件(在 build.gradle(.kts) 文件中应用的插件)可行。设置插件(在 settings.gradle(.kts) 文件中应用的插件)总是必须独立开发并发布到二进制仓库。

Gradle 在设置文件中提供了一个 DSL 构造,用于包含插件构建

像这样包含的构建可以提供项目插件和设置插件。

pluginManagement {
    includeBuild("../my-settings-plugin")
}
plugins {
    id("my.settings-plugin") 
}

以上示例假定包含的构建定义了一个 ID 为 my.settings-plugin 的设置插件。

预编译的 Groovy DSL 脚本插件

脚本插件是拆分和组织长构建脚本的便捷方式,但它们有一些限制和怪癖。

预编译脚本插件看起来像常规的构建脚本,但具有二进制插件的所有优点。它们可以

  • 发布到私有仓库或插件门户,
  • 使用 TestKit 进行测试,
  • 使用 plugins {} 块应用,
  • 使用 plugins {} 块来应用其他插件。

预编译脚本插件可以使用 Groovy DSL 和 Kotlin DSL 编写。

预编译脚本插件在用户手册中有更深入的介绍。还有一个示例演示了该功能的实际应用。

包含的构建对 buildSrc 可见

我们建议构建使用特殊命名的 buildSrc 构建来组织命令式和通用的构建逻辑。

有时,您可能还需要在 buildSrc 本身和您的根构建之间共享构建逻辑。在以前的版本中,这是不可能的,因为 buildSrc 无法访问其他包含的构建中的构建逻辑。

Gradle 使得在 buildSrc 和根构建或任何其他包含的构建之间共享构建逻辑成为可能。这使得在 buildSrc 和其他构建之间共享通用仓库声明或约定变得更加容易,如此示例所示。

您可能错过的其他更改

Kotlin 1.4

在 Gradle 7.0 中编写的 Kotlin 构建脚本默认使用 Kotlin 1.4 兼容级别。

Groovy 3.0

为了支持 JDK 16 并与最新的 Groovy 版本保持同步,Gradle 已升级为在 Groovy DSL 构建脚本中使用 Groovy 3。Groovy 3 附带了新的解析器以及许多其他新特性和功能,使得与新 Java 特性的互操作性更加容易。

Groovy 2 和 3 之间存在一些不兼容之处,这可能会在升级到 Gradle 7.0 时导致问题。

如果出现以下情况,您可能会受到 Groovy 升级的影响:

  • 您正在为构建脚本使用 Groovy DSL(.gradle 文件)
  • 您正在使用一个用 Groovy 实现的 Gradle 插件
  • 您正在构建一个用 Groovy 实现的 Gradle 插件

如果出现以下情况,您应该不会受到升级的影响:

  • 您仅使用 Kotlin DSL(.gradle.kts 文件)
  • 您仅在生产代码中使用 Groovy(您可以选择所需的 Groovy 版本)

请参阅 Gradle 升级指南,了解更多关于升级您的构建和插件以使其与 Groovy 3 兼容的信息。

要了解有关 Groovy 3.0 中改进和新功能的更多信息,请参阅 Groovy 项目的发行说明


如何升级

我们提供了一份文档来帮助您从 Gradle 6.x 升级到 Gradle 7.0。如果您使用的版本比 Gradle 6.0 更旧,您可能需要先查看Gradle 6.0 中的所有新功能

在升级之前,我们建议您

  • 使用 Gradle Wrapper 升级到 Gradle 6.9。gradle wrapper --gradle-version=6.9
  • 运行 gradle help --scan 来列出所有已弃用的 Gradle API 及其位置。
  • 更新您的 Gradle 插件,尤其是那些在 Build Scan™ 的弃用报告中列出的插件。
  • 如果您遇到困难,请参阅故障排除指南或在社区论坛上寻求帮助。

您可以通过 Twitter 上的 @gradle 与 Gradle 团队分享反馈。去构建快乐吧!