通过开发构建脚本,学习编写 Gradle 构建的基础知识。

在本节中,您将

  • 理解 Project 对象

  • 更新构建脚本

  • 更新插件

  • 应用插件

  • 运行插件中的任务

步骤 0. 开始之前

  1. 您已在第 1 部分初始化了您的 Java 应用。

  2. 您已从第 2 部分理解了 Gradle 构建生命周期。

  3. 您已在第 3 部分添加了一个子项目和一个单独的构建。

  4. 您已在第 4 部分查看了一个 Settings 文件。

步骤 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 classpath。

为 Gradle 项目声明的每个依赖项都必须应用于一个范围。也就是说,依赖项在编译时、运行时或两者都需要。这称为配置 (configuration),当依赖项仅在运行时 classpath 中需要时,使用 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 init 生成 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 或 运行 greeting 任务

$ ./gradlew :app:greeting

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

下一步: 编写任务 >>