执行任何 Gradle 构建的推荐方式是借助 Gradle Wrapper(简称“Wrapper”)。

Wrapper 是一个脚本(称为 gradlewgradlew.bat),它调用已声明的 Gradle 版本,并在必要时预先下载。您不是使用已安装的 Gradle 运行 gradle build,而是通过调用 ./gradlew build 来使用 Gradle Wrapper。

wrapper workflow

Gradle Wrapper 不是作为独立下载包分发的——它是使用 gradle wrapper 任务创建的。

使用 Wrapper 的三种方式

  1. 添加 Wrapper - 您设置一个新的 Gradle 项目,并将 Wrapper 添加到其中

  2. 使用 Wrapper - 您使用已提供 Wrapper 的项目运行构建。

  3. 升级 Wrapper - 您将 Wrapper 升级到新的 Gradle 版本。

使用 Wrapper 而不是已安装的 Gradle,您将获得以下好处

  • 将项目标准化到特定的 Gradle 版本,以实现更可靠、更健壮的构建。

  • 为不同的用户配置 Gradle 版本只需简单地修改 Wrapper 定义即可完成。

  • 为不同的执行环境(例如,IDE 或持续集成服务器)配置 Gradle 版本只需简单地修改 Wrapper 定义即可完成。

以下各节将更详细地解释这些用例。

1. 添加 Gradle Wrapper

Gradle Wrapper 不是您下载的东西。

生成 Wrapper 文件需要在您的机器上安装 Gradle 运行时,如安装中所述。幸运的是,生成初始 Wrapper 文件是一次性过程。

每个原生的 Gradle 构建都带有一个名为 wrapper 的内置任务。当列出任务时,该任务列在“Build Setup tasks”组下。

执行 wrapper 任务会在项目目录中生成必要的 Wrapper 文件

$ gradle wrapper
> Task :wrapper

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

为了使 Wrapper 文件对其他开发人员和执行环境可用,您需要将它们提交到版本控制。Wrapper 文件,包括 JAR 文件,很小。将 JAR 文件添加到版本控制是预期的。有些组织不允许项目将二进制文件提交到版本控制,目前没有可用的变通方法。

生成的 Wrapper 属性文件 gradle/wrapper/gradle-wrapper.properties 存储有关 Gradle 分发版的信息

  • 托管 Gradle 分发版的服务器

  • Gradle 分发版的类型。默认情况下,-bin 分发版只包含运行时,不包含示例代码和文档。

  • 用于执行构建的 Gradle 版本。默认情况下,wrapper 任务选择用于生成 Wrapper 文件的同一 Gradle 版本。

  • 可选地,下载 Gradle 分发版时使用的以毫秒为单位的超时

  • 可选地,一个布尔值用于设置分发 URL 的验证

以下是 gradle/wrapper/gradle-wrapper.properties 中生成的 distribution URL 的示例

distributionUrl=https\://services.gradle.org/distributions/gradle-{gradleVersion}-bin.zip

借助以下命令行选项,可以在生成 Wrapper 文件时配置所有这些方面

--gradle-version

用于下载和执行 Wrapper 的 Gradle 版本。生成的 distribution URL 在写入属性文件之前会进行验证。

允许使用以下标签

--distribution-type

用于 Wrapper 的 Gradle 分发版类型。可用选项包括 binall。默认值为 bin

--gradle-distribution-url

指向 Gradle 分发版 ZIP 文件的完整 URL。此选项使 --gradle-version--distribution-type 过时,因为 URL 已包含此信息。如果您想在公司网络内部托管 Gradle 分发版,此选项很有价值。URL 在写入属性文件之前会进行验证。

--gradle-distribution-sha256-sum

用于验证下载的 Gradle 分发版的 SHA256 哈希值。

--network-timeout

下载 Gradle 分发版时使用的网络超时,单位为毫秒。默认值为 10000

--no-validate-url

禁用对已配置的 distribution URL 的验证。

--validate-url

启用对已配置的 distribution URL 的验证。默认启用。

如果使用 --gradle-version--gradle-distribution-url 配置了 distribution URL,对于 https 方案,通过发送 HEAD 请求进行验证;对于 file 方案,通过检查文件是否存在进行验证。

让我们假设以下用例来演示命令行选项的使用。您想使用 8.14 版本生成 Wrapper,并使用 -all 分发版,以便您的 IDE 能够启用代码补全并能够导航到 Gradle 源代码。

以下命令行执行满足了这些要求

$ gradle wrapper --gradle-version {gradleVersion} --distribution-type all
> Task :wrapper

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

结果是,您可以在 Wrapper 属性文件中找到所需信息(生成的 distribution URL)

distributionUrl=https\://services.gradle.org/distributions/gradle-{gradleVersion}-all.zip

让我们看看以下项目布局,以说明预期的 Wrapper 文件

.
├── a-subproject
│   └── build.gradle.kts
├── settings.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
.
├── a-subproject
│   └── build.gradle
├── settings.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat

Gradle 项目通常为每个子项目提供一个 settings.gradle(.kts) 文件和一个 build.gradle(.kts) 文件。Wrapper 文件位于项目根目录和 gradle 目录中。

以下列表解释了它们的作用

gradle-wrapper.jar

包含用于下载 Gradle 分发版的代码的 Wrapper JAR 文件。

gradle-wrapper.properties

负责配置 Wrapper 运行时行为的属性文件,例如与此版本兼容的 Gradle 版本。请注意,更通用的设置,例如配置 Wrapper 使用代理,需要写入不同的文件中。

gradlew, gradlew.bat

一个 shell 脚本和一个 Windows 批处理脚本,用于使用 Wrapper 执行构建。

您可以直接使用 Wrapper 执行构建,而无需安装 Gradle 运行时。如果您正在处理的项目不包含这些 Wrapper 文件,则需要生成它们

2. 使用 Gradle Wrapper

始终建议使用 Wrapper 执行构建,以确保构建的可靠、受控和标准化执行。使用 Wrapper 看起来像使用 Gradle 安装来运行构建。根据操作系统,您运行的是 gradlewgradlew.bat,而不是 gradle 命令。

以下控制台输出演示了在 Windows 机器上对基于 Java 的项目使用 Wrapper

$ gradlew.bat build
Downloading https://services.gradle.org/distributions/gradle-5.0-all.zip
.....................................................................................
Unzipping C:\Documents and Settings\Claudia\.gradle\wrapper\dists\gradle-5.0-all\ac27o8rbd0ic8ih41or9l32mv\gradle-5.0-all.zip to C:\Documents and Settings\Claudia\.gradle\wrapper\dists\gradle-5.0-al\ac27o8rbd0ic8ih41or9l32mv
Set executable permissions for: C:\Documents and Settings\Claudia\.gradle\wrapper\dists\gradle-5.0-all\ac27o8rbd0ic8ih41or9l32mv\gradle-5.0\bin\gradle

BUILD SUCCESSFUL in 12s
1 actionable task: 1 executed

如果 Gradle 分发版在机器上不可用,Wrapper 将下载它并将其存储在本地文件系统中。只要 Gradle 属性中的 distribution URL 不改变,任何后续构建调用都将重用现有的本地分发版。

Wrapper shell 脚本和批处理文件位于单项目或多项目 Gradle 构建的根目录中。如果您想从子项目目录(例如 ../../gradlew tasks)执行构建,则需要引用这些文件的正确路径。

3. 升级 Gradle Wrapper

项目通常希望与时俱进,升级其 Gradle 版本以从新特性和改进中获益。

升级 Gradle 版本的一种方法是手动更改 Wrapper 的 gradle-wrapper.properties 文件中的 distributionUrl 属性。

更好且推荐的选项是运行 wrapper 任务并提供目标 Gradle 版本,如添加 Gradle Wrapper 中所述。使用 wrapper 任务可确保针对特定 Gradle 版本对 Wrapper shell 脚本或批处理文件进行的任何优化都应用于项目。

像往常一样,您应该将 Wrapper 文件的更改提交到版本控制。

请注意,运行 wrapper 任务一次只会更新 gradle-wrapper.properties,而 Wrapper 本身在 gradle-wrapper.jar 中保持不变。这通常没有问题,因为即使使用旧的 Wrapper 文件,新版本的 Gradle 也能运行。

如果您希望所有 Wrapper 文件都完全更新,则需要第二次运行 wrapper 任务。

以下命令将 Wrapper 升级到 latest 版本

$ ./gradlew wrapper --gradle-version latest   // MacOs, Linux
$ gradlew.bat wrapper --gradle-version latest // Windows
BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed

以下命令将 Wrapper 升级到特定版本

$ ./gradlew wrapper --gradle-version {gradleVersion} // MacOs, Linux
$ gradlew.bat wrapper --gradle-version {gradleVersion} // Windows
BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed

升级 Wrapper 后,您可以通过执行 ./gradlew --version 来检查它是否是您预期的版本。

不要忘记再次运行 wrapper 任务以下载 Gradle 分发版二进制文件(如果需要)并更新 gradlewgradlew.bat 文件。

自定义 Gradle Wrapper

大多数 Gradle 用户对 Wrapper 的默认运行时行为感到满意。但是,组织策略、安全约束或个人偏好可能要求您更深入地自定义 Wrapper。

幸运的是,内置的 wrapper 任务提供了许多选项,可以根据您的需要调整运行时行为。大多数配置选项由底层任务类型 Wrapper 公开。

假设您每次升级 Wrapper 时都厌倦了在命令行上定义 -all 分发版类型。您可以通过重新配置 wrapper 任务来节省一些键盘输入。

build.gradle.kts
tasks.wrapper {
    distributionType = Wrapper.DistributionType.ALL
}
build.gradle
tasks.named('wrapper') {
    distributionType = Wrapper.DistributionType.ALL
}

配置到位后,运行 ./gradlew wrapper --gradle-version 8.14 足以在 Wrapper 属性文件中生成 distributionUrl 值,该值将请求 -all 分发版

distributionUrl=https\://services.gradle.org/distributions/gradle-{gradleVersion}-all.zip

查阅API 文档以获取可用配置选项的更详细说明。您还可以在 Gradle 分发版中找到各种配置 Wrapper 的示例。

认证的 Gradle 分发版下载

Gradle Wrapper 可以使用 HTTP 基本认证从服务器下载 Gradle 分发版。这使您可以在私有受保护的服务器上托管 Gradle 分发版。

您可以根据您的用例以两种不同的方式指定用户名和密码:作为系统属性或直接嵌入在 distributionUrl 中。系统属性中的凭据优先于嵌入在 distributionUrl 中的凭据。

HTTP 基本认证只能与 HTTPS URL 一起使用,不能与纯 HTTP URL 一起使用。使用基本认证时,用户凭据会以明文形式发送。

可以在用户主目录中的 .gradle/gradle.properties 文件中或通过其他方式指定系统属性。

要指定 HTTP 基本认证凭据,请将以下行添加到系统属性文件中

systemProp.gradle.wrapperUser=username
systemProp.gradle.wrapperPassword=password

将凭据嵌入到 gradle/wrapper/gradle-wrapper.properties 文件中的 distributionUrl 中也有效。请注意,此文件应提交到您的源代码控制系统。

嵌入在 distributionUrl 中的共享凭据只能在受控环境中使用。

要在 distributionUrl 中指定 HTTP 基本认证凭据,请添加以下行

distributionUrl=https://username:password@somehost/path/to/gradle-distribution.zip

这可以与代理(无论是否经过认证)结合使用。有关如何配置 Wrapper 以使用代理的更多信息,请参阅通过代理访问 Web

验证下载的 Gradle 分发版

Gradle Wrapper 允许通过 SHA-256 哈希值比较来验证下载的 Gradle 分发版。这通过阻止中间人攻击者篡改下载的 Gradle 分发版来增强针对定向攻击的安全性。

要启用此功能,请下载与您要验证的 Gradle 分发版关联的 .sha256 文件。

下载 SHA-256 文件

您可以从稳定版发布候选版和每夜构建版下载 .sha256 文件。该文件的格式是包含相应 zip 文件的 SHA-256 哈希值的单行文本。

您还可以参考Gradle 分发版校验和列表

配置校验和验证

使用 distributionSha256Sum 属性将下载的(SHA-256 校验和)哈希值添加到 gradle-wrapper.properties 中,或在命令行上使用 --gradle-distribution-sha256-sum

distributionSha256Sum=371cb9fbebbe9880d147f59bab36d61eee122854ef8c9ee1ecf12b82368bcf10

如果配置的校验和与托管分发版的服务器上的校验和不匹配,Gradle 将报告构建失败。校验和验证仅在尚未下载配置的 Wrapper 分发版时执行。

如果 gradle-wrapper.properties 包含 distributionSha256Sum 但任务配置未定义哈希值,则 Wrapper 任务将失败。当 Gradle 版本不变时,执行 Wrapper 任务会保留 distributionSha256Sum 配置。

验证 Gradle Wrapper JAR 的完整性

Wrapper JAR 是一个二进制文件,将在开发人员和构建服务器的计算机上执行。与所有此类文件一样,在执行之前应确保其可信。

由于 Wrapper JAR 通常会提交到项目的版本控制系统,因此存在恶意行为者通过提交仅升级 Gradle 版本的拉取请求来将原始 JAR 替换为修改过的 JAR 的可能性。

为了验证 Wrapper JAR 的完整性,Gradle 创建了一个 GitHub Action,它会在拉取请求中自动检查 Wrapper JAR 与已知良好校验和列表的匹配情况。

Gradle 还发布了所有版本的校验和(版本 3.3 到 4.0.2 除外,这些版本未生成可重现的 JAR),因此您可以手动验证 Wrapper JAR 的完整性。

在 GitHub 上自动验证 Gradle Wrapper JAR

GitHub Action 是独立于 Gradle 发布的,因此请查阅其文档了解如何将其应用于您的项目。

手动验证 Gradle Wrapper JAR

您可以在主要操作系统之一上运行以下命令,手动验证 Wrapper JAR 的校验和,以确保其未被篡改。

在 Linux 上手动验证 Wrapper JAR 的校验和

$ cd gradle/wrapper
$ curl --location --output gradle-wrapper.jar.sha256 \
       https://services.gradle.org/distributions/gradle-{gradleVersion}-wrapper.jar.sha256
$ echo " gradle-wrapper.jar" >> gradle-wrapper.jar.sha256
$ sha256sum --check gradle-wrapper.jar.sha256
gradle-wrapper.jar: OK

在 macOS 上手动验证 Wrapper JAR 的校验和

$ cd gradle/wrapper
$ curl --location --output gradle-wrapper.jar.sha256 \
       https://services.gradle.org/distributions/gradle-{gradleVersion}-wrapper.jar.sha256
$ echo " gradle-wrapper.jar" >> gradle-wrapper.jar.sha256
$ shasum --check gradle-wrapper.jar.sha256
gradle-wrapper.jar: OK

在 Windows 上手动验证 Wrapper JAR 的校验和(使用 PowerShell)

> $expected = Invoke-RestMethod -Uri https://services.gradle.org/distributions/gradle-{gradleVersion}-wrapper.jar.sha256
> $actual = (Get-FileHash gradle\wrapper\gradle-wrapper.jar -Algorithm SHA256).Hash.ToLower()
> @{$true = 'OK: Checksum match'; $false = "ERROR: Checksum mismatch!`nExpected: $expected`nActual:   $actual"}[$actual -eq $expected]
OK: Checksum match

排查校验和不匹配问题

如果校验和与您预期的不匹配,很可能是因为 wrapper 任务没有使用升级后的 Gradle 分发版执行。

您应该首先检查实际校验和是否与不同的 Gradle 版本匹配。

以下是在主要操作系统上运行以生成 Wrapper JAR 实际校验和的命令。

在 Linux 上生成 Wrapper JAR 的校验和

$ sha256sum gradle/wrapper/gradle-wrapper.jar
d81e0f23ade952b35e55333dd5f1821585e887c6d24305aeea2fbc8dad564b95 gradle/wrapper/gradle-wrapper.jar

在 macOS 上生成 Wrapper JAR 的实际校验和

$ shasum --algorithm=256 gradle/wrapper/gradle-wrapper.jar
d81e0f23ade952b35e55333dd5f1821585e887c6d24305aeea2fbc8dad564b95 gradle/wrapper/gradle-wrapper.jar

在 Windows 上生成 Wrapper JAR 的实际校验和(使用 PowerShell)

> (Get-FileHash gradle\wrapper\gradle-wrapper.jar -Algorithm SHA256).Hash.ToLower()
d81e0f23ade952b35e55333dd5f1821585e887c6d24305aeea2fbc8dad564b95

一旦您知道实际校验和,请检查是否在 https://gradle.org.cn/release-checksums/ 上列出。如果列出,则您已验证 Wrapper JAR 的完整性。如果生成 Wrapper JAR 的 Gradle 版本与 gradle/wrapper/gradle-wrapper.properties 中的版本不匹配,可以安全地再次运行 wrapper 任务来更新 Wrapper JAR。

如果校验和未在此页面上列出,则 Wrapper JAR 可能来自里程碑版本、发布候选版本或每夜构建版本,或者可能由 Gradle 3.3 至 4.0.2 生成。尝试查明其生成方式,但在证明其可信之前,请将其视为不可信。如果您认为 Wrapper JAR 已被泄露,请通过发送电子邮件至 security@gradle.com 告知 Gradle 团队。