多專案建置中的子專案通常共用一些常見的依賴關係。

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
│ │ └──groovy
│ │ └──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.gradle(.kts)
檔案
// Apply any other configurations specific to your project
// Use the build script defined in buildSrc
apply(from = rootProject.file("buildSrc/shared.gradle.kts"))
// 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.kts (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
│ │ └──groovy
│ │ └──myproject.java-conventions.gradle (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"
}
為了編譯慣例外掛程式,需要在 buildSrc
目錄的建置檔案中應用基本配置
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
plugins {
id 'groovy-gradle-plugin'
}
慣例外掛程式應用於 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 {} 。 |
透過跨專案配置,建置邏輯可以注入到子專案中,但從其建置腳本中看不出來。
從長遠來看,跨專案配置通常會變得越來越複雜,並成為一種負擔。跨專案配置也可能在專案之間引入配置時耦合,這可能會妨礙隨需配置等最佳化功能正常運作。
慣例外掛程式與跨專案配置比較
跨專案配置的兩個最常見用途可以使用慣例外掛程式更好地建模
-
將外掛程式或其他配置應用於特定類型的子專案。
通常,跨專案配置邏輯是如果子專案類型為 X,則配置 Y
。這相當於將X-conventions
外掛程式直接應用於子專案。 -
從特定類型的子專案中提取資訊。
此使用案例可以使用傳出配置變體建模。