組織 Gradle 專案
每個軟體專案的原始碼和組建邏輯都應該以有意義的方式組織。此頁面列出導致可讀、可維護專案的最佳實務。下列各節也探討常見問題以及如何避免這些問題。
分開特定語言的原始碼檔案
Gradle 的語言外掛程式建立慣例來偵測和編譯原始碼。例如,套用 Java 外掛程式 的專案會自動編譯 src/main/java
目錄中的程式碼。其他語言外掛程式遵循相同的模式。目錄路徑的最後一部分通常表示原始碼檔案預期的語言。
有些編譯器能夠在同一個原始碼目錄中交叉編譯多種語言。Groovy 編譯器可以處理將 Java 和 Groovy 原始碼檔案混合放在 src/main/groovy
中的情況。Gradle 建議您根據語言將原始碼放在目錄中,因為組建效能較高,而且使用者和組建都可以做出更強的假設。
下列原始碼樹包含 Java 和 Kotlin 原始碼檔案。Java 原始碼檔案位於 src/main/java
中,而 Kotlin 原始碼檔案位於 src/main/kotlin
中。
.
├── build.gradle.kts
└── src
└── main
├── java
│ └── HelloWorld.java
└── kotlin
└── Utils.kt
.
├── build.gradle
└── src
└── main
├── java
│ └── HelloWorld.java
└── kotlin
└── Utils.kt
每個測試類型分開原始碼檔案
專案定義並執行不同類型的測試非常常見,例如單元測試、整合測試、功能測試或煙霧測試。最佳做法是將每種類型測試的測試原始碼儲存在專用的原始碼目錄中。分開的測試原始碼對可維護性和關注點分離有正面的影響,因為您可以獨立執行各種類型的測試。
查看範例,了解如何將獨立的整合測試組態新增到基於 Java 的專案。
務必定義設定檔
每次呼叫建置時,Gradle 都會嘗試找出 settings.gradle
(Groovy DSL) 或 settings.gradle.kts
(Kotlin DSL) 檔案。為此,執行時期會沿著目錄樹狀結構向上走到根目錄。演算法會在找到設定檔後停止搜尋。
務必將 settings.gradle
新增到建置的根目錄,以避免最初的效能影響。檔案可以是空的,也可以定義專案的所需名稱。
多專案建置必須在多專案層級的根專案中具備 settings.gradle(.kts)
檔案。這是因為設定檔定義了哪些專案會參與 多專案建置。除了定義包含的專案外,您可能需要它來 將函式庫新增至您的建置指令碼類別路徑。
下列範例顯示標準 Gradle 專案配置
.
├── settings.gradle.kts
├── subproject-one
│ └── build.gradle.kts
└── subproject-two
└── build.gradle.kts
.
├── settings.gradle
├── subproject-one
│ └── build.gradle
└── subproject-two
└── build.gradle
使用 buildSrc
來抽象命令式邏輯
複雜的建置邏輯通常很適合封裝為自訂工作或二進位外掛程式。自訂工作和外掛程式實作不應存在於建置指令碼中。只要程式碼不需要在多個獨立專案中分享,使用 buildSrc
來達到此目的非常方便。
目錄 buildSrc
被視為 包含的建置。在發現目錄後,Gradle 會自動編譯並測試此程式碼,並將其置於您的建置指令碼的類別路徑中。對於多專案建置,只能有一個 buildSrc
目錄,它必須位於根專案目錄中。buildSrc
應優先於 指令碼外掛程式,因為維護、重構和測試程式碼比較容易。
buildSrc
使用適用於 Java 和 Groovy 專案的 相同原始程式碼慣例。它也提供對 Gradle API 的直接存取。可以在 buildSrc
下的專用 build.gradle
中宣告其他相依性。
repositories {
mavenCentral()
}
dependencies {
testImplementation("junit:junit:4.13")
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'junit:junit:4.13'
}
包含 buildSrc
的典型專案具有下列配置。buildSrc
下的任何程式碼都應使用類似應用程式程式碼的套件。buildSrc
目錄可以選擇性地主控建置指令碼,如果需要其他設定(例如套用外掛程式或宣告相依性)。
.
├── buildSrc
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ └── java
│ │ └── com
│ │ └── enterprise
│ │ ├── Deploy.java
│ │ └── DeploymentPlugin.java
│ └── test
│ └── java
│ └── com
│ └── enterprise
│ └── DeploymentPluginTest.java
├── settings.gradle.kts
├── subproject-one
│ └── build.gradle.kts
└── subproject-two
└── build.gradle.kts
.
├── buildSrc
│ ├── build.gradle
│ └── src
│ ├── main
│ │ └── java
│ │ └── com
│ │ └── enterprise
│ │ ├── Deploy.java
│ │ └── DeploymentPlugin.java
│ └── test
│ └── java
│ └── com
│ └── enterprise
│ └── DeploymentPluginTest.java
├── settings.gradle
├── subproject-one
│ └── build.gradle
└── subproject-two
└── build.gradle
因此,在進行小幅增量變更時, |
在 gradle.properties
檔案中宣告屬性
在 Gradle 中,屬性可以在建置指令碼、gradle.properties
檔案中定義,或作為命令列上的參數。
在臨時場景中,在命令列上宣告屬性是很常見的。例如,您可能想要傳入特定的屬性值,以控制執行時間行為,僅針對此建置呼叫。建置腳本中的屬性很容易變成維護的頭痛,並混淆建置腳本邏輯。gradle.properties
有助於將屬性與建置腳本分開,並應探索為可行的選項。這是放置 控制建置環境的屬性 的好位置。
典型的專案設定會將 gradle.properties
檔案放置在建置的根目錄中。或者,如果要將檔案套用至機器上的所有建置,檔案也可以存在於 GRADLE_USER_HOME
目錄中。
.
├── gradle.properties
└── settings.gradle.kts
├── subproject-a
│ └── build.gradle.kts
└── subproject-b
└── build.gradle.kts
.
├── gradle.properties
└── settings.gradle
├── subproject-a
│ └── build.gradle
└── subproject-b
└── build.gradle
使用自訂 Gradle 發行版標準化建置
企業通常希望透過定義常見慣例或規則,為組織中的所有專案標準化建置平台。您可以借助初始化腳本來達成此目的。 初始化腳本 使得在單一機器上的所有專案中套用建置邏輯變得非常容易。例如,宣告內部存放庫及其憑證。
這種方法有一些缺點。首先,您必須向公司中的所有開發人員傳達設定流程。此外,統一更新初始化腳本邏輯可能會具有挑戰性。
自訂 Gradle 發行版是解決此問題的實用方案。自訂 Gradle 發行版由標準 Gradle 發行版加上一個或多個自訂初始化指令碼組成。初始化指令碼與發行版綑綁在一起,並在每次執行建置時套用。開發人員只需將其簽入的 Wrapper 檔案指向自訂 Gradle 發行版的網址即可。
自訂 Gradle 發行版也可能在發行版的根目錄中包含一個 gradle.properties
檔案,提供組織範圍的 屬性集,用以控制建置環境。
以下是建立自訂 Gradle 發行版的典型步驟
-
實作下載和重新封裝 Gradle 發行版的邏輯。
-
定義一個或多個具有所需邏輯的初始化指令碼。
-
將初始化指令碼與 Gradle 發行版綑綁在一起。
-
將 Gradle 發行版封存檔上傳到 HTTP 伺服器。
-
變更所有專案的 Wrapper 檔案,使其指向自訂 Gradle 發行版的網址。
plugins {
id 'base'
}
// This is defined in buildSrc
import org.gradle.distribution.DownloadGradle
version = '0.1'
tasks.register('downloadGradle', DownloadGradle) {
description = 'Downloads the Gradle distribution with a given version.'
gradleVersion = '4.6'
}
tasks.register('createCustomGradleDistribution', Zip) {
description = 'Builds custom Gradle distribution and bundles initialization scripts.'
dependsOn downloadGradle
def projectVersion = project.version
archiveFileName = downloadGradle.gradleVersion.map { gradleVersion ->
"mycompany-gradle-${gradleVersion}-${projectVersion}-bin.zip"
}
from zipTree(downloadGradle.destinationFile)
from('src/init.d') {
into "${downloadGradle.distributionNameBase.get()}/init.d"
}
}