您可以在支援 Gradle 的 IDE 中開啟此範例。

為了讓您的軟體專案準備好成長,您可以將 Gradle 專案組織成多個子專案,以模組化您正在建置的軟體。在本指南中,您將以 Groovy 應用程式為例,學習如何建構此類專案。但是,一般概念適用於您使用 Gradle 建置的任何軟體。您可以逐步按照指南從頭開始建立新專案,或使用上面的連結下載完整的範例專案。

您將建置的內容

您將建置一個 Groovy 應用程式,其中包含一個應用程式和多個程式庫專案。

您需要的東西

建立專案資料夾

Gradle 隨附一個內建任務,稱為 init,可在空白資料夾中初始化新的 Gradle 專案。init 任務使用(也是內建的)wrapper 任務來建立 Gradle Wrapper 腳本 gradlew

第一步是為新專案建立資料夾,然後變更目錄進入該資料夾。

$ mkdir demo
$ cd demo

執行 init 任務

從新專案目錄內,在終端機中使用以下命令執行 init 任務:gradle init。出現提示時,選取 1: application 專案類型和 3: Groovy 作為實作語言。之後,選取 2: Application and library project。接下來,您可以選擇用於編寫建置腳本的 DSL - 1 : Kotlin2: Groovy。對於其他問題,按 Enter 鍵使用預設值。

輸出結果如下

$ gradle init

Select type of build to generate:
  1: Application
  2: Library
  3: Gradle plugin
  4: Basic (build structure only)
Enter selection (default: Application) [1..4] 1

Select implementation language:
  1: Java
  2: Kotlin
  3: Groovy
  4: Scala
  5: C++
  6: Swift
Enter selection (default: Java) [1..6]  3

Project name (default: demo):

Enter target Java version (min: 7, default: 21):

Select application structure:
  1: Single application project
  2: Application and library project
Enter selection (default: Single application project) [1..2] 2

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2]

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no]

BUILD SUCCESSFUL
1 actionable task: 1 executed

init 任務會產生具有以下結構的新專案

├── gradle (1)
│   ├── libs.versions.toml (2)
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew (3)
├── gradlew.bat (3)
├── settings.gradle.kts (4)
├── buildSrc
│   ├── build.gradle.kts (5)
│   ├── settings.gradle.kts (5)
│   └── src
│       └── main
│           └── kotlin (6)
│               ├── buildlogic.groovy-application-conventions.gradle.kts
│               ├── buildlogic.groovy-common-conventions.gradle.kts
│               └── buildlogic.groovy-library-conventions.gradle.kts
├── app
│   ├── build.gradle.kts (7)
│   └── src
│       ├── main (8)
│       │   └── java
│       │       └── demo
│       │           └── app
│       │               ├── App.java
│       │               └── MessageUtils.groovy
│       └── test (9)
│           └── java
│               └── demo
│                   └── app
│                       └── MessageUtilsTest.groovy
├── list
│   ├── build.gradle.kts (7)
│   └── src
│       ├── main (8)
│       │   └── java
│       │       └── demo
│       │           └── list
│       │               └── LinkedList.groovy
│       └── test (9)
│           └── java
│               └── demo
│                   └── list
│                       └── LinkedListTest.groovy
└── utilities
    ├── build.gradle.kts (7)
    └── src
        └── main (8)
            └── java
                └── demo
                    └── utilities
                        ├── JoinUtils.groovy
                        ├── SplitUtils.groovy
                        └── StringUtils.groovy
├── gradle (1)
│   ├── libs.versions.toml (2)
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew (3)
├── gradlew.bat (3)
├── settings.gradle (4)
├── buildSrc
│   ├── build.gradle (5)
│   ├── settings.gradle (5)
│   └── src
│       └── main
│           └── groovy (6)
│               ├── buildlogic.groovy-application-conventions.gradle
│               ├── buildlogic.groovy-common-conventions.gradle
│               └── buildlogic.groovy-library-conventions.gradle
├── app
│   ├── build.gradle (7)
│   └── src
│       ├── main (8)
│       │   └── java
│       │       └── demo
│       │           └── app
│       │               ├── App.java
│       │               └── MessageUtils.java
│       └── test (9)
│           └── java
│               └── demo
│                   └── app
│                       └── MessageUtilsTest.java
├── list
│   ├── build.gradle (7)
│   └── src
│       ├── main (8)
│       │   └── java
│       │       └── demo
│       │           └── list
│       │               └── LinkedList.java
│       └── test (9)
│           └── java
│               └── demo
│                   └── list
│                       └── LinkedListTest.java
└── utilities
    ├── build.gradle (7)
    └── src
        └── main (8)
            └── java
                └── demo
                    └── utilities
                        ├── JoinUtils.java
                        ├── SplitUtils.java
                        └── StringUtils.java
1 為 Wrapper 檔案產生的資料夾
2 產生的版本目錄
3 Gradle Wrapper 啟動腳本
4 設定檔以定義建置名稱和子專案
5 buildSrc 的建置腳本,用於配置建置邏輯的依賴關係
6 以 Groovy 或 Kotlin DSL 編寫的慣例外掛的來源資料夾
7 三個子專案(applistutilities)的建置腳本
8 每個子專案中的 Groovy 來源資料夾
9 子專案中的 Groovy 測試來源資料夾

您現在已設定專案以建置 Groovy 應用程式,該應用程式已模組化為多個子專案。

檢閱專案檔案

settings.gradle(.kts) 檔案有兩個有趣的行

settings.gradle.kts
rootProject.name = "demo"
include("app", "list", "utilities")
settings.gradle
rootProject.name = 'demo'
include('app', 'list', 'utilities')
  • rootProject.name 會為建置指派名稱,這會覆寫依據目錄命名建置的預設行為。建議設定固定名稱,因為如果專案共用(例如作為 Git 儲存庫的根目錄),則資料夾可能會變更。

  • include("app", "list", "utilities") 定義建置包含對應資料夾中的三個子專案。可以透過擴展列表或新增更多 include(…​) 陳述式來新增更多子專案。

由於我們的建置包含多個子專案,我們希望在它們之間共用建置邏輯和配置。為此,我們利用位於 buildSrc 資料夾中的所謂慣例外掛buildSrc 中的慣例外掛是利用 Gradle 外掛系統編寫可重複使用建置配置位元的簡單方法。

在此範例中,我們可以找到三個彼此關聯的慣例外掛

buildSrc/src/main/kotlin/buildlogic.groovy-common-conventions.gradle.kts
plugins {
    groovy (1)
}

repositories {
    mavenCentral() (2)
}

dependencies {
    constraints {
        implementation("org.apache.commons:commons-text:1.12.0") (3)

        implementation("org.codehaus.groovy:groovy-all:3.0.23")
    }

    implementation("org.codehaus.groovy:groovy-all") (4)

    testImplementation("org.junit.jupiter:junit-jupiter:5.11.3") (5)

    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.named<Test>("test") {
    useJUnitPlatform() (6)
}
buildSrc/src/main/groovy/buildlogic.groovy-common-conventions.gradle
plugins {
    id 'groovy' (1)
}

repositories {
    mavenCentral() (2)
}

dependencies {
    constraints {
        implementation 'org.apache.commons:commons-text:1.12.0' (3)

        implementation 'org.codehaus.groovy:groovy-all:3.0.23'
    }

    implementation 'org.codehaus.groovy:groovy-all' (4)

    testImplementation 'org.junit.jupiter:junit-jupiter:5.11.3' (5)

    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform() (6)
}

groovy-common-conventions 定義應由我們所有 Groovy 專案共用的一些配置,無論它們代表程式庫還是實際應用程式。首先,我們應用 Groovy 外掛 (1),以取得所有用於建置 Groovy 專案的功能。然後,我們宣告儲存庫 - mavenCentral() - 作為外部依賴關係的來源 (2)、定義依賴約束 (3) 以及所有子專案共用的標準依賴關係,並將 JUnit 5 設定為測試框架 (4…​)。其他共用設定,例如編譯器旗標或 JVM 版本相容性,也可以在此處設定。

buildSrc/src/main/kotlin/buildlogic.groovy-library-conventions.gradle.kts
plugins {
    id("buildlogic.groovy-common-conventions") (1)
    `java-library` (2)
}
buildSrc/src/main/groovy/buildlogic.groovy-library-conventions.gradle
plugins {
    id 'buildlogic.groovy-common-conventions' (1)
    id 'java-library' (2)
}
buildSrc/src/main/kotlin/buildlogic.groovy-application-conventions.gradle.kts
plugins {
    id("buildlogic.groovy-common-conventions") (1)
    application (2)
}
buildSrc/src/main/groovy/buildlogic.groovy-application-conventions.gradle
plugins {
    id 'buildlogic.groovy-common-conventions' (1)
    id 'application' (2)
}

groovy-library-conventionsgroovy-application-conventions 都應用 groovy-common-conventions 外掛 (1),以便程式庫和應用程式專案共用在那裡執行的配置。接下來,它們分別應用 java-libraryapplication 外掛 (2),從而將我們的通用配置邏輯與程式庫或應用程式的特定內容結合起來。雖然此範例中沒有更精細的配置,但程式庫或應用程式專案特定的建置配置可以放入其中一個慣例外掛腳本中。

讓我們看看子專案中的 build.gradle(.kts) 檔案。

app/build.gradle.kts
plugins {
    id("buildlogic.groovy-application-conventions")
}

dependencies {
    implementation("org.apache.commons:commons-text")
    implementation(project(":utilities"))
}

application {
    mainClass = "demo.app.App" (1)
}
app/build.gradle
plugins {
    id 'buildlogic.groovy-application-conventions'
}

dependencies {
    implementation 'org.apache.commons:commons-text'
    implementation project(':utilities')
}

application {
    mainClass = 'demo.app.App' (1)
}
list/build.gradle.kts
plugins {
    id("buildlogic.groovy-library-conventions")
}
list/build.gradle
plugins {
    id 'buildlogic.groovy-library-conventions'
}
utilities/build.gradle.kts
plugins {
    id("buildlogic.groovy-library-conventions")
}

dependencies {
    api(project(":list"))
}
utilities/build.gradle
plugins {
    id 'buildlogic.groovy-library-conventions'
}

dependencies {
    api project(':list')
}

查看建置腳本,我們可以看到它們最多包含三個區塊

  • 每個建置腳本都應該有一個 plugins {} 區塊來應用外掛。在結構良好的建置中,它可能只應用一個慣例外掛,如本範例所示。然後,慣例外掛將負責應用和配置核心 Gradle 外掛(例如 applicationjava-library)、其他慣例外掛或外掛入口網站中的社群外掛。

  • 其次,如果專案有依賴關係,則應新增 dependencies {} 區塊。依賴關係可以是外部的,例如我們在 groovy-common-conventions 中新增的 JUnit 依賴關係,也可以指向其他本機子專案。為此,使用 project(…​) 標記法。在我們的範例中,utilities 程式庫需要 list 程式庫。而 app 使用 utilities 程式庫。如果本機專案彼此依賴,Gradle 會負責在需要時(且僅在需要時)建置依賴專案。若要了解更多資訊,請查看有關 Gradle 中的依賴管理的文件。

  • 第三,外掛可能有一個或多個配置區塊。只有在它們配置某個專案特定的內容時,才應直接在建置腳本中使用這些區塊。否則,此類配置也屬於慣例外掛。在本範例中,我們使用 application {} 區塊,該區塊特定於 application 外掛,以在我們的 app 專案中將 mainClass 設定為 demo.app.App (1)

我們擁有的最後一個建置檔案是 build.gradle(.kts) 檔案,位於 buildSrc 中。

buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl` (1)
}

repositories {
    gradlePluginPortal() (2)
}
buildSrc/build.gradle
plugins {
    id 'groovy-gradle-plugin' (1)
}

repositories {
    gradlePluginPortal() (2)
}

此檔案正在為建置慣例外掛本身設定階段。透過應用外掛開發的外掛之一 - groovy-gradle-pluginkotlin-dsl - (1),我們啟用了在 buildSrc 中將慣例外掛編寫為建置檔案的支援。這些是我們已在上面檢查過的慣例外掛。此外,我們新增 Gradle 的外掛入口網站作為儲存庫 (2),這讓我們可以存取社群外掛。若要使用外掛,需要將其宣告為 dependencies {} 區塊中的依賴關係。

除了 Gradle 建置檔案之外,您還可以在對應的資料夾中找到範例 Groovy 原始碼和測試原始碼。您可以隨意修改這些產生的原始碼和測試,以探索 Gradle 在執行接下來描述的建置時如何回應變更。

執行測試

您可以使用 ./gradlew check 來執行所有子專案中的所有測試。當您使用純任務名稱(例如 check)呼叫 Gradle 時,將會為提供該任務的所有子專案執行該任務。若要僅針對特定子專案,您可以使用任務的完整路徑。例如,:app:check 將僅執行 app 專案的測試。但是,在此範例中,其他子專案仍會被編譯,因為 app 宣告了對它們的依賴關係。

$ ./gradlew check

BUILD SUCCESSFUL
9 actionable tasks: 9 executed

如果所有測試都成功通過,Gradle 不會在主控台中列印更多輸出。您可以在 <子專案>/build/reports 資料夾中找到測試報告。您可以隨意變更一些範例程式碼或測試,然後重新執行 check 以查看測試失敗時會發生什麼情況。

執行應用程式

由於有了 application 外掛,您可以直接從命令列執行應用程式。run 任務會告知 Gradle 執行指派給 mainClass 屬性的類別中的 main 方法。

$ ./gradlew run

> Task :app:run
Hello world!

BUILD SUCCESSFUL
2 actionable tasks: 2 executed
第一次執行 Wrapper 腳本 gradlew 時,下載該版本的 gradle 並將其本機儲存在您的 ~/.gradle/wrapper/dists 資料夾中可能會有延遲。

捆綁應用程式

application 外掛還會為您捆綁應用程式及其所有依賴關係。封存檔也將包含一個腳本,可透過單一命令啟動應用程式。

$ ./gradlew build

BUILD SUCCESSFUL in 0s
7 actionable tasks: 7 executed

如果您執行如上所示的完整建置,Gradle 將為您產生兩種格式的封存檔:app/build/distributions/app.tarapp/build/distributions/app.zip

發布建置掃描

了解您的建置在幕後執行哪些操作的最佳方法是發布 建置掃描。若要執行此操作,只需使用 --scan 旗標執行 Gradle。

$ ./gradlew build --scan

BUILD SUCCESSFUL in 0s
7 actionable tasks: 7 executed

Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service.
Do you accept these terms? [yes, no] yes

Gradle Terms of Service accepted.

Publishing build scan...
https://gradle.com/s/5u4w3gxeurtd2

按一下連結並探索執行了哪些任務、下載了哪些依賴關係以及更多詳細資訊!

摘要

就是這樣!您現在已成功使用 Gradle 配置和建置 Groovy 應用程式專案。您已學習如何

  • 初始化產生 Groovy 應用程式的專案

  • 透過結合多個子專案來建立模組化軟體專案

  • 使用 buildSrc 中的慣例外掛在子專案之間共用建置配置邏輯

  • 在所有子專案中執行相似命名的任務

  • 在特定子專案中執行任務

  • 建置、捆綁和執行應用程式

後續步驟

當您的專案成長時,您可能會對如何配置 JVM 專案、建構多專案建置和依賴管理等更多詳細資訊感興趣