在 Java version 及其他 JVM 生態系統中,過去常見的建置工具以 Apache Ant 或 Apache Maven 為主。然而,兩者有各自的限制:Ant 雖然靈活但需要繁複編寫 XML;Maven 則擁有強大的相依管理功能,但高度的「慣例優於配置」和 XML 配置也讓部分開發者覺得不夠彈性。
自從 Google 在 2013 年於 Android SDK 中將 Gradle inc 正式納入建置系統後,Gradle 迅速成為新的建置利器。它不僅能解決 Maven 和 Ant 之間的痛點,還透過 Groovy 或 Kotlin 的 DSL(Domain-Specific Language)讓您可以以更直覺、可讀且可維護的方式撰寫建置流程。Gradle 提供自動化建構流程,並在設計上深度結合了相依管理與靈活客製的特性。
本篇文章內容將結合豐富的原廠文件與社群經驗,並整理多個 Gradle 使用案例,協助讀者全面了解 Gradle 的特性與應用。文內亦會穿插常見的技巧與問題,並透過範例與程式碼示範重要概念,力求提供一篇詳盡而實用的 Gradle 入門與進階指南。
第一章:Gradle 概述
1.1 什麼是 Gradle
Gradle 是一套基於 JVM 的開源自動化建置工具,融合了 Apache Ant 與 Apache Maven 的優點,並以 Groovy 或 Kotlin 作為建置腳本語言,同時提供自動化建構流程。它透過彈性的 DSL 描述各種建置邏輯,不再需要使用繁瑣的 XML。Gradle 在設計上深度結合了:
- Maven 的相依管理概念,可自動從 Maven 中央倉庫、企業內部私有倉庫或其他公共倉庫下載套件。
- Ant 的可定義任務靈活度,以及輕鬆整合現有的 Ant 腳本或自動化流程。
- Groovy(或 Kotlin) DSL 的條件判斷力與高可讀性,使複雜的流程也能以程式化的方式描述。
1.2 為什麼要使用 Gradle
- 高彈性與可擴充性
Gradle 提供一個高度可組態化(configurable)的系統,支援複雜的多專案建置、客製化任務、調度佈署、程式碼檢查、打包佈署等等。彈性遠高於僅以 XML 定義的 Maven。 - 自動處理相依關係
Gradle 採用了類似 Maven 的依賴管理模式,可自動取得套件並解決傳遞相依(transitive dependencies)或版本衝突。這對於快速變動的專案尤其重要。 - 增量建置和快取機制
Gradle 可以在偵測到程式碼或資源沒有改變時,跳過部分重複的編譯、測試或打包步驟,大幅縮短建置時間,對大型專案尤其有感。 - 良好與 CI/CD 及 IDE 整合
Intellij IDEA、Android Studio、Eclipse、VS Code 均可無縫支援 Gradle。同時對於 Jenkins、GitLab CI、GitHub Actions 等多種 CI/CD 服務,也有成熟整合或外掛可使用。 - 支援多語言、多平台
除了最常見的 Java、Android、Kotlin、Groovy、Scala 之外,Gradle 亦支援 C/C++、Swift 等語言的建置流程。
第二章:Gradle 與其他建置工具的比較
Gradle 與 Maven、Ant 同樣都是建置工具,但三者在編排方式、相依管理及易用性有顯著差異。尤其是 Gradle 與 Maven 的比較最常被開發者拿來參考。
以下是一個簡化的對照表,說明 Gradle 與 Maven 的主要不同:
功能 / 特點 | Gradle | Maven |
---|---|---|
建置腳本語言 | Groovy/Kotlin DSL | XML |
配置與自訂彈性 | 高,DSL 可程式化 | 中等,依賴 XML 結構 |
增量建置 | 有,並提供快取機制 | 有,但較依賴套件的整體快取 |
平行建置 | 有,預設支援 | 無,需外掛或特殊配置 |
處理大型專案性能 | 較優,擁有多層快取和並行能力 | 容易因 POM 複雜度而增長建置時間 |
組件化建置 | 有,並能彈性設計多模組架構 | 有,多模組配置透過繼承與聚合(Aggregation) |
儲存庫管理 | 預設支援 Maven Central,也可設定其他自訂倉庫 | 使用 Maven Central,亦可加自訂倉庫 |
套件生態系統 | 豐富,多為社群外掛與 Gradle 官方外掛 | 也相當豐富,但以 XML 為核心,靈活度不如 Gradle |
學習曲線 | 初始易上手,但深入客製化需理解 DSL 與 Groovy/Kotlin | 傳統 XML 配置,入門快;進階客製化相對複雜 |
支援的 IDE | IntelliJ IDEA、Android Studio、Eclipse、VSCode 等 | IntelliJ IDEA、Eclipse、NetBeans 等 |
熱門應用領域 | Android、微服務、多語言建置、Kotlin 多平台 | Java、傳統大型專案、企業環境 |
小結:若專案希望有高彈性的自訂建置與快速增量編譯等優勢,並使用 Groovy 或 Kotlin DSL,則非常適合採用 Gradle。如果只需要基本的相依管理且專案慣於 XML 風格,Maven 也依舊可行。
第三章:Gradle 的核心概念
3.1 建置腳本(build.gradle / build.gradle.kts)
build.gradle(或 build.gradle.kts)是最主要的專案配置檔。在此檔案中,我們能指定(也可透過環境變數動態調整):
- 外掛程式 (Plugins):如 java、application、org.springframework.boot 等,宣告之後即能使用該外掛定義的任務或功能。
- 倉庫 (Repositories):指定相依套件取得來源,如 mavenCentral()、企業內部 Nexus 或 Artifactory。
- 相依關係 (Dependencies):最常見關鍵字包含 implementation、compileOnly、runtimeOnly、testImplementation 等,對應不同階段或範圍的相依。
- 任務 (Tasks):在 Gradle 中任何可執行的過程都稱為「任務」,例如編譯、測試、打包、佈署都可以被定義或修改。
一個常見的範例 build.gradle(使用 Groovy DSL)如下:
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
// 自訂任務
tasks.register('customTask') {
doLast {
println '這是自訂的任務執行結果!'
}
}
若使用 Kotlin DSL,則檔名會是 build.gradle.kts,語法風格略有不同,但本質是相同的配置。
3.2 設定檔 (settings.gradle / settings.gradle.kts)
在更複雜的專案或多模塊專案中,settings.gradle 負責定義根專案名稱、子專案、額外外掛或配置等。範例如下:
rootProject.name = "MyMultiModuleProject"
include("moduleA")
include("moduleB")
這樣即可告知 Gradle 存在 moduleA、moduleB 兩個子模組,並在各自directory中擁有 build.gradle。
3.3 Gradle Wrapper
Gradle Wrapper 包含 gradlew、gradlew.bat 及 gradle/wrapper 目錄等,允許團隊在沒有安裝 Gradle 主程式的環境中,依舊能以同樣的版本 Gradle 執行建置。只要執行:
./gradlew build
在windows或linux系統上,即可自動下載並使用專案定義的 Gradle 版本。(若尚未安裝 Gradle,可將其執行檔放入系統 path 環境變數以方便使用)保證團隊環境一致性。
3.4 外掛程式 (Plugins)
Gradle 的主要功能大多是由外掛實作。核心功能之外,大量實用外掛可透過 plugins.gradle.org 或 Maven Central 安裝,如:
- java、java-library、application:Java 專案基礎外掛
- org.springframework.boot:Spring Boot 專案外掛
- com.google.cloud.tools.jib:打包容器映像
- io.freefair.lombok:Lombok 整合
- kotlin、groovy:Kotlin、Groovy 相應外掛
- …等等
指定外掛的方式通常是:
plugins {
id "com.google.cloud.tools.jib" version "3.3.1"
}
或在 buildscript 區塊中定義。外掛可加快建置工作、提供預設任務與函式庫整合。
3.5 依賴約束 (Dependency constraints)
Gradle 提供一種 constraints 機制,可約束可接受的相依版本範圍,並處理不同套件之間的傳遞依賴。例如:
dependencies {
implementation 'org.apache.httpcomponents:httpclient'
constraints {
implementation('org.apache.httpcomponents:httpclient:4.5.3') {
because '較舊版本存在 bug 影響系統'
}
implementation('commons-codec:commons-codec:1.11') {
because '隨同 httpclient 取得的 1.9 有問題'
}
}
}
3.6 增量建置與快取
Gradle 具有增量建置機制:若對於某個任務而言,其輸入或輸出未改變,Gradle 可透過 Task Cache 或 Gradle Build Cache 跳過不必要的重編譯、測試與打包,大幅縮短建置時間。這也讓 Gradle 特別適合於大型、多模組的企業專案。
第四章:常見的任務與命令介紹
在 IntelliJ IDEA 或 Android Studio 的 Gradle 工具視窗(Gradle Tab)中,我們可看到許多自動產生的任務。例如:
- build:最常用的任務,整合包含了編譯、測試、打包等流程。
- clean:刪除 build/ 目錄,清理建置輸出。
- assemble:組合所有產物,但不會跑測試。
- test:執行測試,包含單元測試與整合測試。
- bootRun(Spring Boot):直接執行 Spring Boot 專案。
- bootJar(Spring Boot):產生可執行 JAR。
- javadoc:產生 Java API 文件。
- dependencies:顯示專案全部相依關係樹。
- tasks:列出所有當前可執行的任務。
這些任務對應到日常作業流程,像是編譯、測試、打包等。透過終端機命令列也可直接執行,例如:
./gradlew build # 完整建置
./gradlew bootRun # 執行Spring Boot專案
./gradlew clean test # 先清理後再測試
./gradlew tasks --all # 顯示所有任務
若想要查詢任務的詳細資訊,可使用 gradle help –task <taskName>。
第五章:建置腳本更進階的應用
5.1 自訂任務
在 build.gradle 中,我們可以很容易地使用 tasks 區塊來自訂任務。例如:
tasks.register('createArchive', Zip) {
from 'build/libs/'
into 'build/archive/'
include '*.jar'
}
tasks.register('cleanTempFiles', Delete) {
delete 'temp/'
}
tasks.register('runCustomScript', Exec) {
commandLine 'sh', 'scripts/custom_script.sh'
}
- Zip:示範如何把輸出 JAR 檔壓縮到 archive.zip。
- Delete:快速刪除指定的檔案或資料夾。
- Exec:在建置過程中執行外部指令,如 shell script、停啟伺服器等。
5.2 多個檔案拆分:apply from
若專案的建置腳本越來越複雜,也可將任務與配置拆分到多個檔案。例如建立 aplugin.gradle,放入若干任務或組態:
// aplugin.gradle
tasks.register('fromPlugin') {
doLast {
println "Hello from separate gradle file!"
}
}
在主要 build.gradle 中引用:
apply from: 'aplugin.gradle'
刷新專案後,即可在 Gradle Tool Window 看到名為 fromPlugin 的新任務。
5.3 gradle.properties 與系統參數
gradle.properties 檔可存放一些預設變數或敏感資訊,而不需直接硬編碼在 build.gradle,減少資訊外洩風險。格式如下:
storePassword=myStorePassword
keyAlias=myKeyAlias
customValue=abc123
然後在 build.gradle 以 project.properties[‘customValue’] 或 System.getProperty() 取用。也可透過命令列以 -PsysProp=”xxx” 或 -Dsystem=yyy 覆蓋設定。
第六章:多模組專案 (Multi-Project Builds)
當專案規模龐大時,常將程式碼拆分成多個子模組(Subproject)。在根目錄下會有一個 settings.gradle 指定子模組,並在每個子模組資料夾內都有自己的 build.gradle。
6.1 根專案設定 (Root Build Script)
典型地,最外層 build.gradle 可能只指定共同插件或跨模組相依管理,以及設定版本號。例如:
plugins {
// apply false 表示在根專案中不實際套用該外掛,但子專案可選擇引用
id 'org.springframework.boot' version '3.0.3' apply false
id 'io.spring.dependency-management' version '1.1.0' apply false
}
allprojects {
group = 'com.example'
version = '1.0'
repositories {
mavenCentral()
}
}
6.2 子專案設定 (Subproject Build Script)
子專案則可能有自己的 build.gradle,如:
// moduleA/build.gradle
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
dependencies {
implementation project(':common-library')
implementation 'org.springframework.boot:spring-boot-starter-web'
}
// moduleB/build.gradle
apply plugin: 'java'
dependencies {
implementation 'org.apache.commons:commons-lang3:3.12.0'
}
6.3 相互依賴
若子模組 moduleA 需要使用 moduleB 的程式碼,可在 moduleA 的 build.gradle 宣告:
dependencies {
implementation project(':moduleB')
}
如此即可使用 moduleB 輸出的類別或函式,且不需再手動打包與引入 Jar。
6.4 共同設定
根專案可透過 subprojects {} 或 allprojects {} 块,為子專案進行統一設定,例如:
subprojects {
apply plugin: 'java'
sourceCompatibility = '17'
dependencies {
testImplementation 'junit:junit:4.13.2'
}
}
這樣每個子專案都自動套用相同的 Java 插件與 JUnit 相依。
第七章:Gradle 與 Android
Android Studio 內建使用 Gradle 作為建置系統,提供 app 與 library 模組外掛(com.android.application、com.android.library)。Android Gradle Plugin 擴充了下列功能:
- 多版本編譯 (Build Variants):可同時針對不同口味(Product Flavors)與建置類型(Build Types)產生多個 APK。
- 簽名管理:可在 build.gradle 直接配置簽名檔、版本號。對於需要簽名的 Android App,要特別注意安全性與金鑰保管。
- 佈署與執行:assembleDebug、assembleRelease、installDebug 等常見任務都可透過命令列或 IDE 操作。
- 動態版本代碼:可在編譯過程針對不同 ABI、螢幕密度或風味設定自動產生 versionCode。
舉例來說,在 Android 專案的 build.gradle(模組級)可寫:
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.example.myapp"
minSdkVersion 21
targetSdkVersion 33
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
若需要針對多種口味與 build type,則可以設定 flavorDimensions、productFlavors 與 variantFilter 等進行更細緻的組合篩選。
第八章:進階技巧與最佳化
8.1 Code Shrinking / R8 / ProGuard
對於 Android 專案或一般 Java 專案,需要縮減與混淆程式碼時,可開啟 minifyEnabled true,並提供 ProGuard 或 R8 的規則檔案(proguard-rules.pro 等)。對於非 Android 的 Java 專案,也可透過外掛來進行 ProGuard 混淆。
8.2 Lint 與程式碼檢查
在 Android 專案中,lintOptions {} 區塊可設定要忽略、啟用或只檢查特定問題 ID。對於其他 Java 專案,也有第三方外掛支援 Checkstyle、PMD、SpotBugs 等工具。
8.3 測試與測試配置
可以輕鬆整合 JUnit、TestNG、Spock 或其他測試框架。只要在 dependencies 中加入 testImplementation 對應的套件即可:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
}
test {
useJUnitPlatform() // 使用 JUnit 5
}
針對整合測試或功能測試,也能建立額外的 SourceSet 或自訂任務,以區隔不同測試流程。
8.4 建置掃描 (Build Scan)
可在命令列下使用 ./gradlew build –scan 啟用建置掃描。Gradle 會將建置過程與環境詳細資訊上傳至 scans.gradle.com(免費版本),並生成唯一的連結供查閱與分享。這對於除錯與持續整合尤為有用。
- 如無法接受將專案訊息上傳至公有雲,也可考慮付費使用 Gradle Enterprise 架設內部 Build Scan 伺服器,保留分析與報告功能。
8.5 應用程式簽名
對於需要發布的應用程式(如 Android 或一般 JAR),可以在 build.gradle 內透過 signingConfigs 配置簽章資訊,也可將敏感字串放在 gradle.properties 以保護憑證密碼。
android {
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword "password"
keyAlias "my-alias"
keyPassword "password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
8.6 與 Ant 的整合
若原有專案使用 Ant,一時無法全部轉到 Gradle,可以利用 ant.importBuild ‘build.xml’ 將 Ant 的 target 轉成 Gradle 任務。Gradle 幾乎與 Ant 有完整相容性,方便漸進式移轉。
常見問題 (FAQ)
Q1:學習 Gradle 難嗎?
A1:基礎使用不難。只需撰寫少量 DSL 即可完成相依管理、打包佈署。要進階客製化任務或多模組建置時,則需對 Groovy/Kotlin 語言與 Gradle DSL 結構更熟悉。
Q2:我已經習慣 Maven,是否有必要轉 Gradle?
A2:若您的專案單純、升級成本高、對 Maven 十分熟悉,也未嘗不可維持 Maven。然而,如果專案需要更精細控制、增量建置、簡化配置與較佳的整合彈性,Gradle 會帶來長期好處。
Q3:Gradle 和 Kotlin DSL 或 Groovy DSL 哪個比較好?
A3:功能一致。Groovy DSL 歷史較長、社群資源多;Kotlin DSL 支援更好的 IDE 補全與型別檢查。若團隊以 Kotlin 為主,可以考慮 Kotlin DSL。
Q4:如何在團隊中確保每個人都使用相同的 Gradle 版本?
A4:使用 Gradle Wrapper,專案中包含 gradlew 與相應設定,開發者只需執行 ./gradlew <task> 即會自動下載並使用所需版本。
Q5:在多模組專案中,如何加快整體建置?
A5:建議啟用並行建置與 Gradle Build Cache,讓 Gradle 同時處理無相依的子專案,並快取未改動部分。此外,也可以透過細分任務與增量建置讓多模組專案表現更佳。
總結
Gradle 已成為現今 Java 與 Android 領域中最受歡迎的建置工具,亦適用於其他多種程式語言。它結合了 Maven 相依管理、Ant 的任務靈活度,以及 Groovy/Kotlin 的高可讀性與程式化,讓開發者可以在配置與使用上取得最大的彈性,也能依專案需求進行深入客製與自動化。對於需要高效率、高可擴充性並希望增進 CI/CD 流程的團隊,Gradle 提供了完善的解決方案。
若您有興趣進一步學習,可至 Gradle 官方文件 分析您的建置資訊。在現今強調快速迭代與持續整合的軟體開發環境中,Gradle 以其優雅與彈性,已成為不可或缺的利器。
參考資料
- Gradle – 維基百科,自由的百科全書
- Gradle 秘訣與方法 | Android Studio | Android Developers
- iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天