執行任何 Gradle 組建的建議方式是透過 Gradle Wrapper(簡稱「Wrapper」)。

Wrapper 是一個會呼叫已宣告 Gradle 版本的指令碼,並在必要時先行下載。因此,開發人員可以快速啟動並執行 Gradle 專案。

wrapper workflow

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

  • 在特定 Gradle 版本上標準化專案,以獲得更可靠且穩健的組建。

  • 透過簡單變更 Wrapper 定義,即可為不同使用者提供 Gradle 版本。

  • 透過簡單變更 Wrapper 定義,即可為不同的執行環境(例如 IDE 或持續整合伺服器)提供 Gradle 版本。

有下列三種使用 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.7-bin.zip

在使用下列命令列選項產生 Wrapper 檔案時,所有這些面向都是可設定的

--gradle-version

用於下載和執行 Wrapper 的 Gradle 版本。在將結果發行版 URL 寫入屬性檔案前,會先驗證它。

允許使用下列標籤

--distribution-type

用於 Wrapper 的 Gradle 發行版類型。可用的選項為 `bin` 和 `all`。預設值為 `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` 架構的情況下傳送 HEAD 要求來驗證 URL,或在 `file` 架構的情況下檢查檔案是否存在。

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

下列命令列執行會擷取這些需求

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

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

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

distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-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 使用代理伺服器,需要放入 不同的檔案 中。

gradlewgradlew.bat

用於使用 Wrapper 執行建置的 shell 腳本和 Windows 批次檔。

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

使用 Gradle Wrapper

強烈建議使用 Wrapper 執行建置,以確保建置可靠、受控且標準化。使用 Wrapper 看起來就像使用 Gradle 安裝執行建置。根據作業系統,您可以在 gradle 指令中執行 gradlewgradlew.bat

下列主控台輸出示範在 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,但會讓 gradle-wrapper.jar 中的 wrapper 本身保持不變。這通常沒問題,因為即使使用較舊的 wrapper 檔案,也可以執行新版本的 Gradle。

如果您想要讓 所有 wrapper 檔案完全是最新的,您需要第二次執行 wrapper 任務。

下列指令會將 Wrapper 升級至 最新 版本

$ ./gradlew wrapper --gradle-version latest

BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed

下列指令會將 Wrapper 升級至特定版本

$ ./gradlew wrapper --gradle-version 8.7

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.7 就足以在 Wrapper 屬性檔中產生一個 distributionUrl 值,這個值會要求 -all 分配

distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-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任務會失敗。執行Wrapper任務會在 Gradle 版本未變更時保留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-8.7-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 團隊。