Gradle是什麼?從入門安裝到進階應用

Gradle是什麼?從入門安裝到進階應用

在 Java version 及其他 JVM 生態系統中,過去常見的建置工具以 Apache Ant 或 Apache Maven 為主。然而,兩者有各自的限制:Ant 雖然靈活但需要繁複編寫 XML;Maven 則擁有強大的相依管理功能,但高度的「慣例優於配置」和 XML 配置也讓部分開發者覺得不夠彈性。

自從 Google 在 2013 年於 Android SDK 中將 Gradle inc 正式納入建置系統後,Gradle 迅速成為新的建置利器。它不僅能解決 Maven 和 Ant 之間的痛點,還透過 GroovyKotlin 的 DSL(Domain-Specific Language)讓您可以以更直覺、可讀且可維護的方式撰寫建置流程。Gradle 提供自動化建構流程,並在設計上深度結合了相依管理與靈活客製的特性。

本篇文章內容將結合豐富的原廠文件與社群經驗,並整理多個 Gradle 使用案例,協助讀者全面了解 Gradle 的特性與應用。文內亦會穿插常見的技巧與問題,並透過範例與程式碼示範重要概念,力求提供一篇詳盡而實用的 Gradle 入門與進階指南。

第一章:Gradle 概述

1.1 什麼是 Gradle

Gradle 是一套基於 JVM 的開源自動化建置工具,融合了 Apache Ant 與 Apache Maven 的優點,並以 Groovy 或 Kotlin 作為建置腳本語言,同時提供自動化建構流程。它透過彈性的 DSL 描述各種建置邏輯,不再需要使用繁瑣的 XML。Gradle 在設計上深度結合了:

  1. Maven 的相依管理概念,可自動從 Maven 中央倉庫、企業內部私有倉庫或其他公共倉庫下載套件。
  2. Ant 的可定義任務靈活度,以及輕鬆整合現有的 Ant 腳本或自動化流程。
  3. 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)是最主要的專案配置檔。在此檔案中,我們能指定(也可透過環境變數動態調整):

  1. 外掛程式 (Plugins):如 java、application、org.springframework.boot 等,宣告之後即能使用該外掛定義的任務或功能。
  2. 倉庫 (Repositories):指定相依套件取得來源,如 mavenCentral()、企業內部 Nexus 或 Artifactory。
  3. 相依關係 (Dependencies):最常見關鍵字包含 implementation、compileOnly、runtimeOnly、testImplementation 等,對應不同階段或範圍的相依。
  4. 任務 (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

windowslinux系統上,即可自動下載並使用專案定義的 Gradle 版本。(若尚未安裝 Gradle,可將其執行檔放入系統 path 環境變數以方便使用)保證團隊環境一致性。

3.4 外掛程式 (Plugins)

Gradle 的主要功能大多是由外掛實作。核心功能之外,大量實用外掛可透過 plugins.gradle.orgMaven 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)中,我們可看到許多自動產生的任務。例如:

  1. build:最常用的任務,整合包含了編譯、測試、打包等流程。
  2. clean:刪除 build/ 目錄,清理建置輸出。
  3. assemble:組合所有產物,但不會跑測試。
  4. test:執行測試,包含單元測試與整合測試。
  5. bootRun(Spring Boot):直接執行 Spring Boot 專案。
  6. bootJar(Spring Boot):產生可執行 JAR。
  7. javadoc:產生 Java API 文件。
  8. dependencies:顯示專案全部相依關係樹。
  9. 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 以其優雅與彈性,已成為不可或缺的利器。

參考資料

返回頂端