Kotlin Gradle 建構系統 (Kotlin DSL)

Gradle 是目前 Java 與 Kotlin 生態系中最主流的自動化建構工具 (Build Tool)。 Google 官方的 Android Studio 也是預設使用 Gradle 作為建置系統。

過去 Gradle 主要使用 Groovy 語言來撰寫設定檔 (build.gradle),但隨著 Kotlin 的崛起,Gradle 官方也大力推行使用 Kotlin DSL (build.gradle.kts)。這篇文章將帶你了解如何使用 Kotlin 來管理你的專案。

為什麼選擇 Gradle Kotlin DSL (.kts)?

相比於傳統的 Groovy DSL,Kotlin DSL 帶來了幾個顯著的優勢:

  1. 更佳的 IDE 支援:因為是靜態型別語言,IntelliJ IDEA 可以提供精準的 自動補全 (Autocomplete)重構 (Refactoring)跳轉定義 (Go to definition) 功能。
  2. 編譯期檢查:寫錯語法或設定名稱時,IDE 會直接報錯,不用等到執行時才發現。
  3. 單一語言體驗:如果你已經在寫 Kotlin 專案,那麼連建置腳本也用 Kotlin 寫,能降低 Context Switch 的心智負擔。

專案結構 (Project Layout)

一個標準的 Kotlin Gradle 專案結構通常如下:

MyKotlinProject/
├── build.gradle.kts        // [核心] 專案建置腳本
├── settings.gradle.kts     // [核心] 專案設定 (定義專案名稱、Include 模組)
├── gradle/
│   ├── wrapper/            // Gradle Wrapper 檔案 (確保團隊使用相同 Gradle版本)
│   └── libs.versions.toml  // (選用) Version Catalog 依賴版本管理
├── gradlew                 // Unix/Mac 的執行腳本
├── gradlew.bat             // Windows 的執行腳本
└── src/
    ├── main/
    │   ├── kotlin/         // 放置 Kotlin 原始碼
    │   └── resources/      // 放置資源檔 (如設定檔、圖片)
    └── test/
        ├── kotlin/         // 放置測試程式碼
        └── resources/      // 測試用資源

build.gradle.kts 核心剖析

這是控制專案如何建置的核心檔案。讓我們看一個典型的 build.gradle.kts 範例:

// 1. Plugins區塊:引入需要的插件
plugins {
    kotlin("jvm") version "1.9.20" // 引入 Kotlin JVM 插件
    application                    // 引入 Application 插件 (若要產生可執行檔)
}

// 2. 專案資訊
group = "com.fooish"
version = "1.0.0-SNAPSHOT"

// 3. 倉庫設定:去哪裡下載依賴
repositories {
    mavenCentral() // 最常用的 Maven 中央倉庫
    // google()    // 若是 Android 專案通常需要這個
}

// 4. 依賴管理:專案需要哪些第三方庫
dependencies {
    // 引用 Kotlin 標準函式庫 (通常不需要顯式宣告,除非特定版本)
    // implementation(kotlin("stdlib"))
    
    // 協程函式庫 (Coroutines)
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")

    // 測試框架 (JUnit 5)
    testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
    testImplementation(kotlin("test"))
}

// 5. 任務設定:調整編譯與執行的行為
tasks.test {
    useJUnitPlatform() // 指定使用 JUnit 5 平台
}

kotlin {
    jvmToolchain(17) // 設定目標 JVM 版本為 Java 17
}

application {
    mainClass.set("com.fooish.MainKt") // 指定程式進入點
}

常見配置項說明

implementation vs api

dependencies 區塊中,你最常看到這幾個關鍵字:

設定 (Configuration)說明適用情境
implementation實作依賴。依賴的函式庫 不會 暴露給依賴此專案的其他人。大部分依賴都應該用這個,能加快編譯速度。
api介面依賴 (需 java-library plugin)。依賴會傳遞暴露出去。你寫的是 Library,且你的 Public API 裡用到了這個依賴的類別。
testImplementation測試依賴。只有在執行測試時才看得到,打包時不會包含。JUnit, Mockk 等測試工具。
compileOnly僅編譯時。像是 Lombok 或某些 Annotation Processors。編譯時需要,但 Runtime 環境已經由別的地方提供了。
在 Kotlin DSL 中,加入依賴使用的是函式呼叫 implementation("..."),字串必須用雙引號包起來,這點與 Groovy DSL 的單引號不同。

依賴版本管理:Version Catalogs

從 Gradle 7.0 開始,官方推薦使用 Version Catalogs 來統一管理依賴版本。這比以往在 buildSrcext 變數中管理更標準且效能更好。

1. 建立 gradle/libs.versions.toml

[versions]
kotlin = "1.9.20"
coroutines = "1.7.3"
junit = "5.10.0"

[libraries]
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }

2. 在 build.gradle.kts 中使用

Gradle 會自動將 .toml 中的定義轉成型別安全的 Accessors:

plugins {
    alias(libs.plugins.kotlin.jvm)
}

dependencies {
    implementation(libs.kotlin.coroutines)
    testImplementation(libs.junit.jupiter)
}

這樣做的好處是,當你要升級 Library 版本時,只需要修改一個 .toml 檔案,所有模組都會同步更新。

Gradle Wrapper (gradlew)

你的專案根目錄下通常會有一個 gradlew (Linux/Mac) 和 gradlew.bat (Windows) 腳本。 永遠使用 Wrapper 來執行 Gradle 指令,而不是你本機安裝的 Gradle。

為什麼? 因為 gradle/wrapper/gradle-wrapper.properties 裡定義了這個專案唯一指定的 Gradle 版本。使用 Wrapper 可以確保不管在誰的電腦、或是在 CI/CD Server 上,使用的 Gradle 版本都是完全一致的,避免「我這裡會過,你那裡卻壞掉」的相容性問題。

# Good: 使用專案指定的版本
./gradlew build

# Bad: 使用你電腦全域安裝的版本 (可能過舊或過新)
gradle build

常用指令 (Tasks)

指令用途
./gradlew build主要指令。編譯原始碼 -> 執行測試 -> 打包 (產生 JAR 檔)。
./gradlew clean清除 build/ 目錄,確保下次是乾淨的重新建置 (Clean Build)。
./gradlew run執行應用程式 (需 application 插件)。
./gradlew test僅執行單元測試。
./gradlew tasks列出所有可用的任務。

排除測試進行快速建置

有時候測試跑太久,你只想確認編譯會過或是打包 Artifact:

./gradlew build -x test

-x test 代表 exclude (排除) test 任務。

多模組專案 (Multi-module Project)

Kotlin 開發中 (尤其是 Android),很流行將專案拆分成多個模組以降低耦合與加速編譯。

settings.gradle.kts 中定義模組:

rootProject.name = "MyProject"
include("app")
include("core")
include("utils")

app/build.gradle.kts 中引用其他模組:

dependencies {
    implementation(project(":core"))
    implementation(project(":utils"))
}

總結

  • Gradle Kotlin DSL (.kts) 是現在進行式,提供更好的 IDE 支援與型別安全。
  • 專案依賴管理推薦使用 Version Catalogs (libs.versions.toml)
  • 務必習慣使用 ./gradlew Wrapper 腳本來執行指令。
  • 善用 implementation 來隱藏不需要暴露的依賴細節。