您可以使用 IntelliJ 原生匯入器Eclipse Buildship 在 IDE 內開啟此範例。

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

您將建置的內容

您將建置一個由應用程式和多個函式庫專案組成的 Kotlin 應用程式。

您需要準備的內容

建立專案資料夾

Gradle 內建一個名為 init 的工作,用於在空資料夾中初始化新的 Gradle 專案。init 工作使用(也內建)wrapper 工作來建立 Gradle wrapper 腳本 gradlew

第一步是為新專案建立資料夾並切換目錄到該資料夾。

$ mkdir demo
$ cd demo

執行 init 工作

在新的專案目錄中,使用終端機中的以下指令執行 init 工作:gradle init。當提示時,選取 1: application 專案類型和 2: Kotlin 做為實作語言。之後,選取 2: Add library projects。接著,你可以選擇用於撰寫建置腳本的 DSL - 1 : Groovy2: Kotlin。對於其他問題,按 Enter 使用預設值。

輸出會如下所示

$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 1

Split functionality across multiple subprojects?:
   1: no - only one application project
   2: yes - application and library projects
Enter selection (default: no - only one application project) [1..2] 2

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

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

Project name (default: demo):
Source package (default: demo):


BUILD SUCCESSFUL
2 actionable tasks: 2 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.kotlin-application-conventions.gradle.kts
│               ├── buildlogic.kotlin-common-conventions.gradle.kts
│               └── buildlogic.kotlin-library-conventions.gradle.kts
├── app
│   ├── build.gradle.kts (7)
│   └── src
│       ├── main (8)
│       │   └── java
│       │       └── demo
│       │           └── app
│       │               ├── App.java
│       │               └── MessageUtils.kt
│       └── test (9)
│           └── java
│               └── demo
│                   └── app
│                       └── MessageUtilsTest.kt
├── list
│   ├── build.gradle.kts (7)
│   └── src
│       ├── main (8)
│       │   └── java
│       │       └── demo
│       │           └── list
│       │               └── LinkedList.kt
│       └── test (9)
│           └── java
│               └── demo
│                   └── list
│                       └── LinkedListTest.kt
└── utilities
    ├── build.gradle.kts (7)
    └── src
        └── main (8)
            └── java
                └── demo
                    └── utilities
                        ├── JoinUtils.kt
                        ├── SplitUtils.kt
                        └── StringUtils.kt
├── 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.kotlin-application-conventions.gradle
│               ├── buildlogic.kotlin-common-conventions.gradle
│               └── buildlogic.kotlin-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 每個子專案中的 Kotlin 原始碼資料夾
9 子專案中的 Kotlin 測試原始碼資料夾

現在你已設定好專案,可以建置一個模組化成多個子專案的 Kotlin 應用程式。

檢閱專案檔案

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.kotlin-common-conventions.gradle.kts
plugins {
    id("org.jetbrains.kotlin.jvm") (1)
}

repositories {
    mavenCentral() (2)
}

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

    testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") (4)

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

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

repositories {
    mavenCentral() (2)
}

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

    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' (4)

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

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

kotlin-common-conventions 定義一些設定,這些設定應由我們的全部 Kotlin 專案共用,與它們代表函式庫或實際應用程式無關。首先,我們套用 Kotlin Gradle 外掛程式 (1) 以取得建置 Kotlin 專案的所有功能。然後,我們宣告一個儲存庫 — mavenCentral() — 作為外部依賴項目的來源 (2),定義依賴項約束 (3) 以及由所有子專案共用的標準依賴項,並設定 JUnit 5 作為測試架構 (4…​)。其他共用設定,例如編譯器旗標或 JVM 版本相容性,也可以在此設定。

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

kotlin-library-conventionskotlin-application-conventions 都套用 kotlin-common-conventions 外掛程式 (1),因此在那裡執行的設定會由函式庫和應用程式專案共用。接著,它們分別套用 java-libraryapplication 外掛程式 (2),因此將我們的共用設定邏輯與函式庫或應用程式的特定設定結合在一起。雖然此範例中沒有更精細的設定,但函式庫或應用程式專案特定的建置設定可以放入這些慣例外掛程式指令碼中。

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

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

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

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

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

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

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

dependencies {
    api project(':list')
}

檢視建置指令碼,我們可以看到它們包含多達三個區塊

  • 每個建置指令碼都應該有一個 plugins {} 區塊來套用外掛程式。在結構良好的建置中,它可能只套用一個慣例外掛程式,就像此範例一樣。然後,慣例外掛程式會負責套用和設定核心 Gradle 外掛程式(例如 applicationjava-library)、其他慣例外掛程式或來自外掛程式入口網站的社群外掛程式。

  • 其次,如果專案有依賴項,則應新增一個 dependencies {} 區塊。依賴項可以是外部的,例如我們在 kotlin-common-conventions 中新增的 JUnit 依賴項,或可以指向其他本機子專案。為此,我們使用 project(…​) 表示法。在我們的範例中,utilities 函式庫需要 list 函式庫。而 app 使用 utilities 函式庫。如果本機專案彼此依賴,則 Gradle 會在需要時(且僅在需要時)負責建置依賴專案。若要深入了解,請參閱關於 Gradle 中的依賴項管理 的文件。

  • 第三,外掛可能有一個或多個組態區塊。這些組態區塊應僅在建置指令碼中直接使用,如果它們針對一個專案設定特定組態。否則,此類組態也屬於慣例外掛。在此範例中,我們使用特定於 application 外掛的 application {} 區塊,將 app 專案中的 mainClass 設定為 demo.app.App (1)

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

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

repositories {
    gradlePluginPortal() (2)
}

dependencies {
    implementation(libs.kotlin.gradle.plugin)
}
buildSrc/build.gradle
plugins {
    id 'groovy-gradle-plugin' (1)
}

repositories {
    gradlePluginPortal() (2)
}

dependencies {
    implementation libs.kotlin.gradle.plugin
}

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

除了 Gradle 建置檔案外,您可以在對應資料夾中找到範例 Kotlin 原始碼和測試原始碼。請隨時修改這些產生的原始碼和測試,以探索 Gradle 如何在執行建置時對變更做出反應,如下所述。

執行測試

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

$ ./gradlew check

BUILD SUCCESSFUL
9 actionable tasks: 9 executed

如果所有測試都順利通過,Gradle 就不會在主控台中列印更多輸出。您可以在 <subproject>/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
8 actionable tasks: 8 executed

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

發佈建置掃描

深入了解建置在幕後執行的作業的最佳方式,是發佈 建置掃描。為此,只要執行 Gradle 並加上 --scan 旗標即可。

$ ./gradlew build --scan

BUILD SUCCESSFUL in 0s
8 actionable tasks: 8 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 成功設定和建置 Kotlin 應用程式專案。您已學會如何

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

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

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

  • 在所有子專案中執行名稱相似的作業

  • 在特定子專案中執行作業

  • 建置、打包和執行應用程式

後續步驟

當您的專案擴增時,您可能會對如何設定 JVM 專案、建置多專案建置和相依性管理有興趣