多專案建置中的子專案通常會分享一些常見的相依性。

Gradle 提供了一個特殊目錄來儲存共用建置邏輯,可以自動套用至子專案,無需在每個子專案建置指令碼中複製並貼上相同的 Java 版本和函式庫。
在 buildSrc
中分享邏輯
buildSrc
是 Gradle 識別且受保護的目錄,具有一些好處
-
可重複使用的建置邏輯:
buildSrc
讓您可以以結構化的方式組織和集中自訂建置邏輯、工作和外掛。在 buildSrc 中撰寫的程式碼可以在專案中重複使用,讓維護和分享常見建置功能更為容易。 -
與主建置隔離:
放置在
buildSrc
中的程式碼會與專案的其他建置指令碼隔離。這有助於讓主建置指令碼更簡潔,並更專注於專案特定的設定。 -
自動編譯和類別路徑:
buildSrc
目錄的內容會自動編譯,並包含在主建置的類別路徑中。這表示在 buildSrc 中定義的類別和外掛可以直接在專案的建置指令碼中使用,無需任何其他設定。 -
測試容易:
由於
buildSrc
是獨立的建置,因此可以輕鬆測試自訂建置邏輯。您可以為建置程式碼撰寫測試,確保其行為符合預期。 -
Gradle 外掛開發:
如果您正在為專案開發自訂 Gradle 外掛,
buildSrc
是存放外掛程式碼的便利位置。這使得外掛在專案中容易存取。
buildSrc
目錄被視為 包含的建置。
對於多專案建置,只能有一個 buildSrc
目錄,而且必須位於根目錄專案中。
使用 buildSrc 的缺點是,對其進行任何變更都會使專案中的每個工作無效,並需要重新執行。
|
buildSrc
使用適用於 Java、Groovy 和 Kotlin 專案的相同 原始碼慣例。它還提供對 Gradle API 的直接存取。
包含 buildSrc
的典型專案具有下列配置
.
├── buildSrc
│ ├── src
│ │ └──main
│ │ └──kotlin
│ │ └──MyCustomTask.kt (1)
│ ├── shared.gradle.kts (2)
│ └── build.gradle.kts
├── api
│ ├── src
│ │ └──...
│ └── build.gradle.kts (3)
├── services
│ └── person-service
│ ├── src
│ │ └──...
│ └── build.gradle.kts (3)
├── shared
│ ├── src
│ │ └──...
│ └── build.gradle.kts
└── settings.gradle.kts
1 | 建立 MyCustomTask 工作。 |
2 | 共用建置指令碼。 |
3 | 使用 MyCustomTask 工作和共用建置指令碼。 |
.
├── buildSrc
│ ├── src
│ │ └──main
│ │ └──kotlin
│ │ └──MyCustomTask.groovy (1)
│ ├── shared.gradle (2)
│ └── build.gradle
├── api
│ ├── src
│ │ └──...
│ └── build.gradle (3)
├── services
│ └── person-service
│ ├── src
│ │ └──...
│ └── build.gradle (3)
├── shared
│ ├── src
│ │ └──...
│ └── build.gradle
└── settings.gradle
1 | 建立 MyCustomTask 工作。 |
2 | 共用建置指令碼。 |
3 | 使用 MyCustomTask 工作和共用建置指令碼。 |
在 buildSrc
中,建立建置指令碼 shared.gradle(.kts)
。它包含相依關係和其他對多個子專案而言共用的建置資訊
repositories {
mavenCentral()
}
dependencies {
implementation("org.slf4j:slf4j-api:1.7.32")
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.slf4j:slf4j-api:1.7.32'
}
在 buildSrc
中,也建立 MyCustomTask
。它是用作多個子專案建置邏輯一部分的輔助工作。
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
open class MyCustomTask : DefaultTask() {
@TaskAction
fun calculateSum() {
// Custom logic to calculate the sum of two numbers
val num1 = 5
val num2 = 7
val sum = num1 + num2
// Print the result
println("Sum: $sum")
}
}
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
class MyCustomTask extends DefaultTask {
@TaskAction
void calculateSum() {
// Custom logic to calculate the sum of two numbers
int num1 = 5
int num2 = 7
int sum = num1 + num2
// Print the result
println "Sum: $sum"
}
}
MyCustomTask
工作用於 api
和 shared
專案的建置指令碼中。工作會自動提供,因為它是 buildSrc
的一部分。
也會套用 shared.build(.kts)
檔案
// Apply any other configurations specific to your project
// Use the build script defined in buildSrc
apply(from = rootProject.file("buildSrc/shared.gradle"))
// Use the custom task defined in buildSrc
tasks.register<MyCustomTask>("myCustomTask")
// Apply any other configurations specific to your project
// Use the build script defined in buildSrc
apply from: rootProject.file('buildSrc/shared.gradle')
// Use the custom task defined in buildSrc
tasks.register('myCustomTask', MyCustomTask)
使用慣例外掛共用邏輯
Gradle 建議的建置邏輯組織方式是使用其外掛系統。
我們可以撰寫一個外掛,將專案中多個子專案共用的建置邏輯封裝起來。這種外掛稱為慣例外掛。
儘管撰寫外掛不在本節的範疇內,但建議建立 Gradle 專案的方式是將共用建置邏輯放入位於 buildSrc
中的慣例外掛。
我們來看看一個範例專案
.
├── buildSrc
│ ├── src
│ │ └──main
│ │ └──kotlin
│ │ └──myproject.java-conventions.gradle (1)
│ └── build.gradle.kts
├── api
│ ├── src
│ │ └──...
│ └── build.gradle.kts (2)
├── services
│ └── person-service
│ ├── src
│ │ └──...
│ └── build.gradle.kts (2)
├── shared
│ ├── src
│ │ └──...
│ └── build.gradle.kts (2)
└── settings.gradle.kts
1 | 建立 myproject.java-conventions 慣例外掛。 |
2 | 套用 myproject.java-conventions 慣例外掛。 |
.
├── buildSrc
│ ├── src
│ │ └──main
│ │ └──kotlin
│ │ └──myproject.java-conventions.gradle.kts (1)
│ └── build.gradle
├── api
│ ├── src
│ │ └──...
│ └── build.gradle (2)
├── services
│ └── person-service
│ ├── src
│ │ └──...
│ └── build.gradle (2)
├── shared
│ ├── src
│ │ └──...
│ └── build.gradle (2)
└── settings.gradle
1 | 建立 myproject.java-conventions 慣例外掛。 |
2 | 套用 myproject.java-conventions 慣例外掛。 |
此建置包含三個子專案
rootProject.name = "dependencies-java"
include("api", "shared", "services:person-service")
rootProject.name = 'dependencies-java'
include 'api', 'shared', 'services:person-service'
在 buildSrc
目錄中建立的慣例外掛的原始碼如下
plugins {
id("java")
}
group = "com.example"
version = "1.0"
repositories {
mavenCentral()
}
dependencies {
testImplementation("junit:junit:4.13")
}
plugins {
id 'java'
}
group = 'com.example'
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
testImplementation "junit:junit:4.13"
}
慣例外掛套用至 api
、shared
和 person-service
子專案
plugins {
id("myproject.java-conventions")
}
dependencies {
implementation(project(":shared"))
}
plugins {
id("myproject.java-conventions")
}
plugins {
id("myproject.java-conventions")
}
dependencies {
implementation(project(":shared"))
implementation(project(":api"))
}
plugins {
id 'myproject.java-conventions'
}
dependencies {
implementation project(':shared')
}
plugins {
id 'myproject.java-conventions'
}
plugins {
id 'myproject.java-conventions'
}
dependencies {
implementation project(':shared')
implementation project(':api')
}
不要使用跨專案設定
在子專案之間共用建置邏輯的不當方式是透過 subprojects {}
和 allprojects {}
DSL 建構來進行跨專案設定。
避免使用 subprojects {} 和 allprojects {} 。
|
使用跨設定時,建置邏輯可以注入到子專案中,而從其建置指令碼中無法明顯看出。
從長遠來看,跨設定通常會變得更複雜,並成為負擔。跨設定也可能在專案之間引入設定時間的關聯,這可能會阻止按需設定等最佳化正常運作。