使用子專案和複合建置,了解建構 Gradle 專案的基礎知識。
步驟 1. 關於多專案建置
通常,建置包含多個專案,例如共享程式庫或將部署在您的生態系統中的獨立應用程式。
在 Gradle 中,多專案建置包含
-
settings.gradle(.kts)
檔案,代表您的 Gradle 建置,包括必要的子專案,例如 include("app", "model", "service") -
build.gradle(.kts)
和對應子目錄中每個子專案的原始碼
我們的建置目前包含一個名為 authoring-tutorial
的根專案,它有一個單一的 app
子專案
. (1)
├── app (2)
│ ... (3)
│ └── build.gradle.kts (4)
└── settings.gradle.kts (5)
1 | authoring-tutorial 根專案 |
2 | app 子專案 |
3 | app 原始碼 |
4 | app 建置指令碼 |
5 | 選用的設定檔 |
. (1)
├── app (2)
│ ... (3)
│ └── build.gradle (4)
└── settings.gradle (5)
1 | authoring-tutorial 根專案 |
2 | app 子專案 |
3 | app 原始碼 |
4 | app 建置指令碼 |
5 | 選用的設定檔 |
步驟 2. 將另一個子專案新增至建置
假設我們的專案正在成長,需要一個自訂函式庫才能運作。
讓我們建立這個虛擬的 lib
。首先,建立一個 lib
資料夾
mkdir lib
cd lib
建立一個名為 build.gradle(.kts)
的檔案,並新增下列程式碼
plugins {
id("java")
}
repositories {
mavenCentral()
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.9.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation("com.google.guava:guava:32.1.1-jre")
}
tasks.named<Test>("test") {
useJUnitPlatform()
}
tasks.register("task3"){
println("REGISTER TASK3: This is executed during the configuration phase")
}
tasks.named("task3"){
println("NAMED TASK3: This is executed during the configuration phase")
doFirst {
println("NAMED TASK3 - doFirst: This is executed during the execution phase")
}
doLast {
println("NAMED TASK3 - doLast: This is executed during the execution phase")
}
}
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'com.google.guava:guava:32.1.1-jre'
}
test {
useJUnitPlatform()
}
tasks.register('task3') {
println('REGISTER TASK3: This is executed during the configuration phase')
}
tasks.named('task3') {
println('NAMED TASK3: This is executed during the configuration phase')
doFirst {
println('NAMED TASK3 - doFirst: This is executed during the execution phase')
}
doLast {
println('NAMED TASK3 - doLast: This is executed during the execution phase')
}
}
你的專案應該長這樣
.
├── app
│ ...
│ └── build.gradle.kts
├── lib
│ └── build.gradle.kts
└── settings.gradle.kts
.
├── app
│ ...
│ └── build.gradle
├── lib
│ └── build.gradle
└── settings.gradle
讓我們在 lib
子專案中新增一些程式碼。建立一個新的目錄
mkdir -p lib/src/main/java/com/gradle
在一個名為 CustomLib.java
的檔案中建立一個名為 CustomLib
的 Java 類別,並使用下列原始碼
package com.gradle;
public class CustomLib {
public static String identifier = "I'm a String from a lib.";
}
專案現在應該有下列檔案和目錄結構
.
├── app
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── java
│ └── authoring
│ └── tutorial
│ └── App.java
├── lib
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── java
│ └── com
│ └── gradle
│ └── CustomLib.java
└── settings.gradle.kts
.
├── app
│ ├── build.gradle
│ └── src
│ └── main
│ └── java
│ └── authoring
│ └── tutorial
│ └── App.java
├── lib
│ ├── build.gradle
│ └── src
│ └── main
│ └── java
│ └── com
│ └── gradle
│ └── CustomLib.java
└── settings.gradle
不過,lib
子專案不屬於建置,而且你無法執行 task3
,直到它被新增至 settings.gradle(.kts)
檔案。
若要將 lib
新增至建置,請適當地更新根目錄中的 settings.gradle(.kts)
檔案
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
}
rootProject.name = "authoring-tutorial"
include("app")
include("lib") // Add lib to the build
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
rootProject.name = 'authoring-tutorial'
include('app')
include('lib') // Add lib to the build
讓我們在 app/build.gradle(.kts)
中將 lib
子專案新增為 app
相依性
dependencies {
implementation(project(":lib")) // Add lib as an app dependency
}
dependencies {
implementation(project(':lib')) // Add lib as an app dependency
}
更新 app
原始碼,讓它匯入 lib
package authoring.tutorial;
import com.gradle.CustomLib;
public class App {
public String getGreeting() {
return "CustomLib identifier is: " + CustomLib.identifier;
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}
最後,讓我們使用指令 ./gradlew run
執行 app
$ ./gradlew run
> Configure project :app
> Task :app:processResources NO-SOURCE
> Task :lib:compileJava
> Task :lib:processResources NO-SOURCE
> Task :lib:classes
> Task :lib:jar
> Task :app:compileJava
> Task :app:classes
> Task :app:run
CustomLib identifier is: I'm a String from a lib.
BUILD SUCCESSFUL in 11s
8 actionable tasks: 6 executed, 2 up-to-date
我們針對根專案 authoring-tutorial
的建置現在包含兩個子專案,app
和 lib
。app
相依於 lib
。你可以獨立於 app
建置 lib
。不過,若要建置 app
,Gradle 也會建置 lib
。
步驟 3. 了解複合建置
複合建置只是一個包含其他建置的建置。
複合建置允許你
-
從你的專案建置中萃取你的建置邏輯(並在子專案間重複使用它)
-
結合通常獨立開發的建置(例如外掛程式和應用程式)
-
將大型建置分解為較小、更獨立的區塊
步驟 4. 將建置新增至 Build
讓我們將外掛新增至我們的建置。首先,在 gradle
目錄中建立一個名為 license-plugin
的新目錄
cd gradle
mkdir license-plugin
cd license-plugin
進入 gradle/license-plugin
目錄後,執行 gradle init
。請務必選取 Gradle plugin
專案以及下方 init
工作的其他選項
$ gradle init --dsl kotlin --type kotlin-gradle-plugin --project-name license
$ gradle init --dsl groovy --type groovy-gradle-plugin --project-name license
對任何其他提示選取預設值。
你的專案應該長這樣
.
├── app
│ ...
│ └── build.gradle.kts
├── lib
│ ...
│ └── build.gradle.kts
├── gradle
│ ├── ...
│ └── license-plugin
│ ├── settings.gradle.kts
│ └── plugin
│ ├── gradle
│ │ └── ....
│ ├── src
│ │ ├── functionalTest
│ │ │ └── ....
│ │ ├── main
│ │ │ └── kotlin
│ │ │ └── license
│ │ │ └── LicensePlugin.kt
│ │ └── test
│ │ └── ...
│ └── build.gradle.kts
│
└── settings.gradle.kts
.
├── app
│ ...
│ └── build.gradle
├── lib
│ ...
│ └── build.gradle
├── gradle
│ ├── ...
│ └── license-plugin
│ ├── settings.gradle
│ └── plugin
│ ├── gradle
│ │ └── ....
│ ├── src
│ │ ├── functionalTest
│ │ │ └── ....
│ │ ├── main
│ │ │ └── groovy
│ │ │ └── license
│ │ │ └── LicensePlugin.groovy
│ │ └── test
│ │ └── ...
│ └── build.gradle
│
└── settings.gradle
花點時間查看 LicensePlugin.kt
或 LicensePlugin.groovy
程式碼以及 gradle/license-plugin/settings.gradle(.kts)
檔案。請務必注意,這是一個完全獨立的建置,擁有自己的設定檔和建置指令碼
rootProject.name = "license"
include("plugin")
rootProject.name = 'license'
include('plugin')
若要將我們的 license-plugin
建置新增至根專案,請適當地更新根目錄 settings.gradle(.kts)
檔案
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
}
rootProject.name = "authoring-tutorial"
include("app")
include("subproject")
includeBuild("gradle/license-plugin") // Add the new build
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
rootProject.name = 'running-tutorial-groovy'
include('app')
include('lib')
includeBuild('gradle/license-plugin')
您可以在根目錄 authoring-tutorial
中執行 ./gradlew projects
來檢視根專案的結構
$ ./gradlew projects
------------------------------------------------------------
Root project 'authoring-tutorial'
------------------------------------------------------------
Root project 'authoring-tutorial'
+--- Project ':app'
\--- Project ':lib'
Included builds
\--- Included build ':license-plugin'
我們針對根專案 authoring-tutorial
的建置現在包含兩個子專案,app
和 lib
,以及另一個建置 license-plugin
。
在專案根目錄中執行時
-
./gradlew build
- 建置app
和lib
-
./gradlew :app:build
- 建置app
和lib
-
./gradlew :lib:build
- 僅建置lib
-
./gradlew :license-plugin:plugin:build
- 僅建置license-plugin
使用 Gradle 設計專案架構的方式有很多種。
多專案建置非常適合組織具有許多模組的專案,例如 mobile-app
、web-app
、api
、lib
和 documentation
,這些模組之間有依賴關係。
複合式 (include) 建置非常適合分離建置邏輯 (例如慣例外掛) 或測試系統 (例如修補程式庫)
下一步: 設定檔 >>