執行任何 Gradle 建置的建議方式是藉助 Gradle Wrapper(簡稱 "Wrapper")。

Wrapper 是一個腳本,它會調用已宣告的 Gradle 版本,並在必要時預先下載。因此,開發人員可以快速啟動並執行 Gradle 專案。

wrapper workflow

簡而言之,您可以獲得以下好處

  • 將專案標準化在給定的 Gradle 版本上,以實現更可靠和穩健的建置。

  • 為不同使用者配置 Gradle 版本,只需簡單地變更 Wrapper 定義即可完成。

  • 為不同執行環境(例如,IDE 或持續整合伺服器)配置 Gradle 版本,只需簡單地變更 Wrapper 定義即可完成。

有三種方式可以使用 Wrapper

  1. 您設定一個新的 Gradle 專案,並 將 Wrapper 新增至其中

  2. 使用 Wrapper 執行專案,該專案已提供 Wrapper。

  3. 將 Wrapper 升級 至新的 Gradle 版本。

以下章節將更詳細地說明這些使用案例。

新增 Gradle Wrapper

產生 Wrapper 檔案需要您的機器上安裝 Gradle 執行環境,如 安裝 中所述。 幸好,產生初始 Wrapper 檔案是一次性的過程。

每個原始 Gradle 建置都帶有一個內建的任務,稱為 wrapper。當 列出任務 時,該任務會列在「建置設定任務」群組下。

執行 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 中產生的發行版本 URL 範例

distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip

所有這些方面都可以在產生 Wrapper 檔案時配置,藉助以下命令列選項

--gradle-version

用於下載和執行 Wrapper 的 Gradle 版本。 結果發行版本 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

停用已配置發行版本 URL 的驗證。

--validate-url

啟用已配置發行版本 URL 的驗證。 預設為啟用。

如果發行版本 URL 是使用 --gradle-version--gradle-distribution-url 配置的,則在 https 方案的情況下,URL 會透過發送 HEAD 請求進行驗證,或者在 file 方案的情況下,透過檢查檔案是否存在進行驗證。

讓我們假設以下使用案例來說明命令列選項的使用。 您想要使用版本 8.13 產生 Wrapper,並使用 -all 發行版本,以便您的 IDE 能夠啟用程式碼完成並能夠導航到 Gradle 原始碼。

以下命令列執行捕獲了這些需求

$ gradle wrapper --gradle-version 8.13 --distribution-type all
> Task :wrapper

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

因此,您可以在 Wrapper 屬性檔案中找到所需的資訊(產生的發行版本 URL)

distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-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

Wrapper JAR 檔案,包含用於下載 Gradle 發行版本的程式碼。

gradle-wrapper.properties

一個屬性檔案,負責配置 Wrapper 執行環境行為,例如與此版本相容的 Gradle 版本。 請注意,更通用的設定,例如 配置 Wrapper 以使用代理伺服器,需要放入 不同的檔案 中。

gradlew, gradlew.bat

一個 shell 腳本和一個 Windows 批次腳本,用於使用 Wrapper 執行建置。

您可以繼續 使用 Wrapper 執行建置,而無需安裝 Gradle 執行環境。 如果您正在處理的專案不包含這些 Wrapper 檔案,您將需要 產生它們

使用 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 屬性中的發行版本 URL 沒有變更,任何後續的建置調用都將重複使用現有的本機發行版本。

Wrapper shell 腳本和批次檔案位於單一或多專案 Gradle 建置的根目錄中。 如果您想從子專案目錄執行建置,例如 ../../gradlew tasks,您將需要參考這些檔案的正確路徑。

升級 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

BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed

以下命令將 Wrapper 升級到特定版本

$ ./gradlew wrapper --gradle-version 8.13

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.13 就足以在 Wrapper 屬性檔案中產生一個 distributionUrl 值,該值將請求 -all 發行版本

distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-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 以使用代理伺服器的更多資訊,請參閱 透過代理伺服器存取網路

驗證下載的 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,該 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-8.13-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/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 團隊。