組織 Gradle 專案
每個軟體專案的原始碼和建置邏輯都應該以有意義的方式組織。本頁闡述可產生可讀、可維護專案的最佳實務。以下章節也將觸及常見問題以及如何避免這些問題。
分隔特定語言的原始碼檔案
Gradle 的語言外掛程式為探索和編譯原始碼建立慣例。例如,套用 Java 外掛程式 的專案將自動編譯 src/main/java
目錄中的程式碼。其他語言外掛程式也遵循相同的模式。目錄路徑的最後一部分通常指示原始碼檔案的預期語言。
某些編譯器能夠在同一個原始碼目錄中交叉編譯多種語言。Groovy 編譯器可以處理混合位於 src/main/groovy
中的 Java 和 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 發行版本的 URL 即可。
自訂 Gradle 發行版本也可能在發行版本的根目錄中包含 gradle.properties
檔案,該檔案提供組織範圍的一組控制建置環境的屬性。
以下步驟是用於建立自訂 Gradle 發行版本的典型步驟
-
實作下載和重新封裝 Gradle 發行版本的邏輯。
-
使用所需的邏輯定義一個或多個初始化腳本。
-
將初始化腳本與 Gradle 發行版本捆綁在一起。
-
將 Gradle 發行版本封存檔上傳到 HTTP 伺服器。
-
變更所有專案的 Wrapper 檔案,以指向自訂 Gradle 發行版本的 URL。
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"
}
}