透過開發建置指令碼,瞭解撰寫 Gradle 的基礎知識。

在此部分中,您將

  • 了解 Project 物件

  • 更新建置指令碼

  • 更新外掛

  • 套用外掛

  • 從外掛執行任務

步驟 0. 開始前

  1. 您已在 第 1 部分 初始化 Java 應用程式。

  2. 您已從 第 2 部分 了解 Gradle 建置生命週期。

  3. 您已在 第 3 部分 新增子專案和個別建置。

  4. 您已在 第 4 部分 查看設定檔。

步驟 1. Project 物件

建置指令碼呼叫 Gradle API 來設定建置。

在設定階段,Gradle 會在根目錄和子專案目錄中尋找建置指令碼。

當找到建置指令碼 build.gradle(.kts) 時,Gradle 會設定 Project 物件。

Project 物件的目的是建立 Task 物件的集合、套用外掛和擷取依賴項。

您可以在指令碼中直接使用 Project 介面上的任何方法和屬性。

例如

defaultTasks("some-task")      // Delegates to Project.defaultTasks()
reportsDir = file("reports")   // Delegates to Project.file() and the Java Plugin
defaultTasks 'some-task'      // Delegates to Project.defaultTasks()
reportsDir = file('reports')  // Delegates to Project.file() and the Java Plugin

步驟 2. 建置指令碼

讓我們分解外掛的建置指令碼

gradle/license-plugin/plugin/build.gradle.kts
plugins {                                                             (1)
    `java-gradle-plugin`                                              (2)
    id("org.jetbrains.kotlin.jvm") version "1.9.0"                    (3)
}

repositories {                                                        (4)
    mavenCentral()                                                    (5)
}

dependencies {                                                        (6)
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")     (7)
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

gradlePlugin {                                                        (8)
    val greeting by plugins.creating {                                (9)
        id = "license.greeting"
        implementationClass = "license.LicensePlugin"
    }
}

// Additional lines //
1 在 Kotlin DSL 中使用 KotlinSettingsScriptplugins{} 區塊
2 套用 Java Gradle 外掛開發外掛以新增支援開發 Gradle 外掛
3 套用 Kotlin JVM 外掛以新增支援 Kotlin
4 使用 Project.repositories() 設定此專案的儲存庫
5 使用 Maven Central 解析相依性
6 使用 Project.dependencies() 設定此專案的相依性
7 使用 Kotlin JUnit 5 整合
8 在 Kotlin DSL 中使用 GradlePluginDevelopmentExtensiongradlePlugin{} 區塊
9 定義外掛 idimplementationClass
gradle/license-plugin/plugin/build.gradle
plugins {                                                           (1)
    id 'java-gradle-plugin'                                         (2)
    id 'groovy'                                                     (3)
}

repositories {                                                      (4)
    mavenCentral()                                                  (5)
}

dependencies {                                                      (6)
    testImplementation libs.spock.core
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

gradlePlugin {                                                      (7)
    plugins {
        greeting {
            id = 'license.greeting'                                 (8)
            implementationClass = 'license.LicensePlugin'
        }
    }
}

// Additional lines //
1 在 Groovy DSL 中使用 PluginDependenciesSpec APIplugins{} 區塊
2 套用 Java Gradle 外掛開發外掛以新增支援開發 Gradle 外掛
3 套用 Groovy 外掛以新增支援 Groovy
4 使用 Project.repositories() 設定此專案的儲存庫
5 使用 Maven Central 解析相依性
6 使用 Project.dependencies() 設定此專案的相依性
7 在 Groovy DSL 中使用 PluginAware APIgradlePlugin{} 區塊
8 定義外掛 idimplementationClass

外掛可提升您的建置功能,包含方式如下

plugins {
    id("java")                          // core plugin, no version required
    id("org.some.plugin") version "2.8" // community plugin, version required
}
plugins {
    id 'java'                          // core plugin, no version required
    id 'org.some.plugin' version '2.8' // community plugin, version required
}

儲存庫區段讓 Gradle 知道從何處提取相依性

repositories {
    mavenCentral()  // get dependencies from the Maven central repository
}
repositories {
    mavenCentral()  // get dependencies from the Maven central repository
}

相依性是建置應用程式或函式庫的要求

dependencies {
    // group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0'
    implementation("org.apache.commons:commons-lang3:3.13.0")
}
dependencies {
    // group: 'org.apache.commons', name: 'commons-lang3', version: '3.13.0'
    implementation 'org.apache.commons:commons-lang3:3.13.0'
}

在此範例中,implementation() 表示必須將 commons-lang3 函式庫新增至 Java 類別路徑。

為 Gradle 專案宣告的每個相依性都必須套用至範圍。亦即,相依性在編譯時間、執行時間或兩者都需要。這稱為設定檔,而 implementation 設定檔在僅於執行時間類別路徑需要相依性時使用。

設定檔區塊(不要與上述的相依性設定檔混淆)通常用於設定套用的外掛

gradlePlugin {  // Define a custom plugin
    val greeting by plugins.creating {  // Define `greeting` plugin using the `plugins.creating` method
        id = "license.greeting" // Create plugin with the specified ID
        implementationClass = "license.LicensePlugin"   // and specified implementation class
    }
}
gradlePlugin {  // Define a custom plugin
    plugins {
        greeting {  // Define a plugin named greeting
            id = 'license.greeting' // using the id
            implementationClass = 'license.LicensePlugin' // and implementationClass
        }
    }
}

套用 java-gradle-plugin 時,使用者必須使用 gradlePlugin{} 設定檔區塊設定他們正在開發的外掛。

任務是建置期間執行的作業單位。它們可以由外掛或內嵌定義

val functionalTest by tasks.registering(Test::class) {
    testClassesDirs = functionalTestSourceSet.output.classesDirs
    classpath = functionalTestSourceSet.runtimeClasspath
    useJUnitPlatform()
}

tasks.named<Test>("test") {
    // Use JUnit Jupiter for unit tests.
    useJUnitPlatform()
}
tasks.register('functionalTest', Test) {
    testClassesDirs = sourceSets.functionalTest.output.classesDirs
    classpath = sourceSets.functionalTest.runtimeClasspath
    useJUnitPlatform()
}

tasks.named('test') {
    // Use JUnit Jupiter for unit tests.
    useJUnitPlatform()
}

在 Gradle init 產生的範例中,我們定義兩個任務

  1. functionalTest:此任務使用 tasks.register() 註冊。它會設定功能測試的測試任務。

  2. test:此任務使用 tasks.named() 設定現有的 test 任務。它也會設定任務以使用 JUnit Jupiter 進行單元測試。

步驟 3. 更新建置指令碼

在以下各節中,我們會將 LicensePlugin 更新為自動為原始程式碼檔案產生授權標頭的外掛程式。讓我們先使用新 license 外掛程式的正確名稱更新建置指令碼

gradle/license-plugin/plugin/build.gradle.kts
gradlePlugin {
    val license by plugins.creating {   // Update name to license
        id = "com.tutorial.license"     // Update id to com.gradle.license
        implementationClass = "license.LicensePlugin"
    }
}
gradle/license-plugin/plugin/build.gradle
gradlePlugin {
    // Define the plugin
    plugins {
        license {                       // Update name to license
            id = 'com.tutorial.license' // Update id to com.gradle.license
            implementationClass = 'license.LicensePlugin'
        }
    }
}

步驟 3. 套用外掛程式

讓我們將 license 外掛程式套用至 app 子專案

app/build.gradle.kts
plugins {
    application
    id("com.tutorial.license")  // Apply the license plugin
}
app/build.gradle
plugins {
    id 'application'
    id('com.tutorial.license')  // Apply the license plugin
}

步驟 4. 查看外掛程式任務

建置初始化會在產生 Gradle 外掛程式專案時建立一個「hello world」外掛程式。LicensePlugin 內部只是一個會在主控台列印問候語的任務,任務名稱為 greeting

gradle/license-plugin/plugin/src/main/kotlin/license/LicensePlugin.kt
class LicensePlugin: Plugin<Project> {
    override fun apply(project: Project) {                          // Apply plugin
        project.tasks.register("greeting") { task ->                // Register a task
            task.doLast {
                println("Hello from plugin 'com.tutorial.greeting'")  // Hello world printout
            }
        }
    }
}
gradle/license-plugin/plugin/src/main/groovy/license/LicensePlugin.groovy
class LicensePlugin implements Plugin<Project> {
    void apply(Project project) {
        // Register a task
        project.tasks.register("greeting") {
            doLast {
                println("Hello from plugin 'com.tutorial.greeting'")
            }
        }
    }
}

我們可以看到,套用 license 外掛程式時,會公開一個 greeting 任務,並附有簡單的列印陳述式。

步驟 5. 查看外掛程式任務

license 外掛程式套用至 app 專案時,greeting 任務就會可用

若要在根目錄中查看任務,請執行

$ ./gradlew tasks --all

------------------------------------------------------------
Tasks runnable from root project 'authoring-tutorial'
------------------------------------------------------------

...

Other tasks
-----------
app:greeting
app:task1
app:task2
lib:task3

最後,使用 ./gradlew greeting

$ ./gradlew :app:greeting

> Task :app:greeting
Hello from plugin 'com.tutorial.greeting'

下一步: 撰寫任務 >>