Gradle 支援多專案建立。

gradle basic 9

雖然有些小型專案和單體應用程式可能包含單一建立檔案和原始碼樹,但專案通常會分割成較小的相依模組。相依這個字很重要,因為您通常會想透過單一建立將多個模組連結在一起。

Gradle 透過多專案建立來支援這個場景。這有時稱為多模組專案。Gradle 將模組稱為子專案。

多專案建立包含一個根專案和一個或多個子專案。

多專案結構

以下表示包含兩個子專案的多專案建立結構

multi project structure

目錄結構應如下所示

├── .gradle
│   └── ⋮
├── gradle
│   ├── libs.version.toml
│   └── wrapper
├── gradlew
├── gradlew.bat
├── settings.gradle.kts  (1)
├── sub-project-1
│   └── build.gradle.kts (2)
├── sub-project-2
│   └── build.gradle.kts (2)
└── sub-project-3
    └── build.gradle.kts (2)
1 settings.gradle.kts 檔案應包含所有子專案。
2 每個子專案應有自己的 build.gradle.kts 檔案。

多專案標準

Gradle 社群有兩種多專案建立結構標準

  1. 使用 buildSrc 的多專案建立 - 其中 buildSrc 是 Gradle 專案根目錄中的類似子專案的目錄,包含所有建立邏輯。

  2. 複合建立 - 一種包含其他建立的建立,其中 build-logic 是 Gradle 專案根目錄中的建立目錄,包含可重複使用的建立邏輯。

multi project standards

1. 使用 buildSrc 的多專案建立

多專案建立讓您組織具有多個模組的專案,串連這些模組之間的相依性,並輕鬆地在它們之間共用常見的建立邏輯。

例如,一個具有多個模組的建立稱為 mobile-appweb-appapilibdocumentation,可以結構如下

.
├── gradle
├── gradlew
├── settings.gradle.kts
├── buildSrc
│   ├── build.gradle.kts
│   └── src/main/kotlin/shared-build-conventions.gradle.kts
├── mobile-app
│   └── build.gradle.kts
├── web-app
│   └── build.gradle.kts
├── api
│   └── build.gradle.kts
├── lib
│   └── build.gradle.kts
└── documentation
    └── build.gradle.kts

模組之間會有相依性,例如 web-appmobile-app 相依於 lib。這表示為了讓 Gradle 建立 web-appmobile-app,它必須先建立 lib

在此範例中,根設定檔將如下所示

settings.gradle.kts
include("mobile-app", "web-app", "api", "lib", "documentation")
包含子專案 (模組) 的順序並不重要。

buildSrc 目錄會自動由 Gradle 辨識。這是定義和維護共用設定或命令式建置邏輯(例如自訂任務或外掛)的好地方。

如果在 buildSrc 下找到 build.gradle(.kts) 檔案,buildSrc 會自動包含在您的建置中,作為一個特殊子專案。

如果將 java 外掛套用至 buildSrc 專案,則從 buildSrc/src/main/java 編譯的程式碼會放入根建置指令碼的類別路徑中,讓建置中的任何子專案 (web-appmobile-applib 等…) 都可以使用。

請參閱如何宣告 子專案之間的相依性 以深入了解。

2. 複合建置

複合建置(也稱為「包含建置」)最適合在建置之間共用邏輯(而非子專案)或隔離存取共用建置邏輯(例如慣例外掛)。

讓我們來看前一個範例。buildSrc 中的邏輯已轉換為一個包含外掛的專案,而且可以獨立於根專案建置來發布和處理。

外掛移至其自己的建置,稱為 build-logic,並附有建置指令碼和設定檔

.
├── gradle
├── gradlew
├── settings.gradle.kts
├── build-logic
│   ├── settings.gradle.kts
│   └── conventions
│       ├── build.gradle.kts
│       └── src/main/kotlin/shared-build-conventions.gradle.kts
├── mobile-app
│   └── build.gradle.kts
├── web-app
│   └── build.gradle.kts
├── api
│   └── build.gradle.kts
├── lib
│   └── build.gradle.kts
└── documentation
    └── build.gradle.kts
build-logic 位於根專案的子目錄中這項事實並無關緊要。如果需要,可以將資料夾放在根專案外部。

根設定檔包含整個 build-logic 建置

settings.gradle.kts
pluginManagement {
    includeBuild("build-logic")
}
include("mobile-app", "web-app", "api", "lib", "documentation")

請參閱如何使用 includeBuild 建立複合建置 以深入了解。

多專案路徑

專案路徑具有下列模式:它從一個可選的冒號開始,表示根專案。

根專案 : 是路徑中唯一未由其名稱指定的專案。

專案路徑的其餘部分是專案名稱的冒號分隔順序,其中下一個專案是前一個專案的子專案

:sub-project-1

執行 gradle projects 時,您可以看到專案路徑

------------------------------------------------------------
Root project 'project'
------------------------------------------------------------

Root project 'project'
+--- Project ':sub-project-1'
\--- Project ':sub-project-2'

專案路徑通常反映檔案系統佈局,但有例外。最顯著的是 複合建置

識別專案結構

您可以使用 `gradle projects` 指令識別專案結構。

舉例來說,我們使用具有下列結構的多專案建置

> gradle -q projects
------------------------------------------------------------
Root project 'multiproject'
------------------------------------------------------------

Root project 'multiproject'
+--- Project ':api'
+--- Project ':services'
|    +--- Project ':services:shared'
|    \--- Project ':services:webservice'
\--- Project ':shared'

To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :api:tasks

多專案建置是您可以執行的任務集合。不同之處在於您可能想要控制執行 哪些 專案的任務。

下列各節將介紹您在多專案建置中執行任務的兩個選項。

依名稱執行任務

指令 `gradle test` 將執行任何子專案中相對於具有該任務的目前工作目錄的 `test` 任務。

如果您從根專案目錄執行指令,您將在 apisharedservices:sharedservices:webservice 中執行 `test`。

如果您從 services 專案目錄執行指令,您將只在 services:sharedservices:webservice 中執行任務。

Gradle 行為背後的基本規則是 執行階層中所有具有 名稱的任務。而且 如果在遍歷的任何子專案中找不到 任何 該任務,則會抱怨

某些任務選擇器(例如 `help` 或 `dependencies`)將只在呼叫它們的專案上執行任務,而不會在所有子專案上執行,以減少顯示在螢幕上的資訊量。

依完全限定名稱執行任務

您可以使用任務的完全限定名稱在特定子專案中執行特定任務。例如:`gradle :services:webservice:build` 將執行 webservice 子專案的 `build` 任務。

任務的完全限定名稱是其 專案路徑 加上任務名稱。

此方法適用於任何任務,因此如果您想知道特定子專案中有哪些任務,請使用 `tasks` 任務,例如 `gradle :services:webservice:tasks`。

多專案建置和測試

build 任務通常用於編譯、測試和檢查單一專案。

在多專案建置中,您可能經常想要在各種專案中執行所有這些任務。buildNeededbuildDependents 任務可以協助執行此操作。

此範例 中,:services:person-service 專案依賴 :api:shared 專案。:api 專案也依賴 :shared 專案。

假設您正在處理單一專案 :api 專案,您已經進行變更,但自執行 clean 以來尚未建置整個專案。您想要建置任何必要的支援 JAR,但只針對已變更的專案部分執行程式碼品質和單元測試。

build 任務會執行此操作

$ gradle :api:build

> Task :shared:compileJava
> Task :shared:processResources
> Task :shared:classes
> Task :shared:jar
> Task :api:compileJava
> Task :api:processResources
> Task :api:classes
> Task :api:jar
> Task :api:assemble
> Task :api:compileTestJava
> Task :api:processTestResources
> Task :api:testClasses
> Task :api:test
> Task :api:check
> Task :api:build

BUILD SUCCESSFUL in 0s

如果您剛從版本控制系統取得最新版本的原始程式碼,其中包含 :api 所依賴的其他專案的變更,您可能想要建置所有您所依賴的專案,並對其執行測試。

buildNeeded 任務會建置並測試 testRuntime 設定中專案依賴關係的所有專案

$ gradle :api:buildNeeded

> Task :shared:compileJava
> Task :shared:processResources
> Task :shared:classes
> Task :shared:jar
> Task :api:compileJava
> Task :api:processResources
> Task :api:classes
> Task :api:jar
> Task :api:assemble
> Task :api:compileTestJava
> Task :api:processTestResources
> Task :api:testClasses
> Task :api:test
> Task :api:check
> Task :api:build
> Task :shared:assemble
> Task :shared:compileTestJava
> Task :shared:processTestResources
> Task :shared:testClasses
> Task :shared:test
> Task :shared:check
> Task :shared:build
> Task :shared:buildNeeded
> Task :api:buildNeeded

BUILD SUCCESSFUL in 0s

您可能想要重構其他專案中使用的 :api 專案的某些部分。如果您進行這些變更,只測試 :api 專案是不夠的。您必須測試所有依賴 :api 專案的專案。

buildDependents 任務會測試所有在 (testRuntime 設定中) 對指定專案有專案依賴關係的專案

$ gradle :api:buildDependents

> Task :shared:compileJava
> Task :shared:processResources
> Task :shared:classes
> Task :shared:jar
> Task :api:compileJava
> Task :api:processResources
> Task :api:classes
> Task :api:jar
> Task :api:assemble
> Task :api:compileTestJava
> Task :api:processTestResources
> Task :api:testClasses
> Task :api:test
> Task :api:check
> Task :api:build
> Task :services:person-service:compileJava
> Task :services:person-service:processResources
> Task :services:person-service:classes
> Task :services:person-service:jar
> Task :services:person-service:assemble
> Task :services:person-service:compileTestJava
> Task :services:person-service:processTestResources
> Task :services:person-service:testClasses
> Task :services:person-service:test
> Task :services:person-service:check
> Task :services:person-service:build
> Task :services:person-service:buildDependents
> Task :api:buildDependents

BUILD SUCCESSFUL in 0s

最後,您可以在所有專案中建置和測試所有內容。您在根專案資料夾中執行的任何任務都會導致在所有子項上執行同名的任務。

您可以執行 gradle build 來建置和測試所有專案。

請參閱 建置結構章節 以進一步了解。