Gradle 可以在项目上执行的工作由一个或多个 task 定义。

author gradle 5

一个 task 代表构建执行的某个独立工作单元。这可能是编译一些类、创建 JAR、生成 Javadoc 或将一些归档文件发布到仓库。

当用户在命令行中运行 ./gradlew build 时,Gradle 将执行 build task 以及它所依赖的任何其他 task。

列出可用 task

Gradle 为项目提供了几个默认 task,可以通过运行 ./gradlew tasks 列出

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project 'myTutorial'
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'myTutorial'.
...

Task 要么来自 build 脚本,要么来自 插件

一旦我们将插件应用到我们的项目,例如 application 插件,其他 task 就会变为可用

build.gradle.kts
plugins {
    id("application")
}
build.gradle
plugins {
    id 'application'
}
$ ./gradlew tasks

> Task :tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

Application tasks
-----------------
run - Runs this project as a JVM application

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Other tasks
-----------
compileJava - Compiles main Java source.

...

许多这些 task,例如 assemblebuildrun,对于开发人员来说应该是熟悉的。

Task 分类

可以执行两种类型的 task

  1. 可操作 task 附加了一些 action 以在你的构建中执行工作:compileJava

  2. 生命周期 task 是没有附加 action 的 task:assemblebuild

通常,一个 生命周期 task 依赖于许多 可操作 task,并用于一次执行多个 task。

Task 注册和 action

让我们看一下构建脚本中的一个简单的“Hello World”task

build.gradle.kts
tasks.register("hello") {
    doLast {
        println("Hello world!")
    }
}
build.gradle
tasks.register('hello') {
    doLast {
        println 'Hello world!'
    }
}

在该示例中,构建脚本使用 TaskContainer API 注册了一个名为 hello 的 task,并为其添加了一个 action

如果列出项目中的 task,则 hello task 对 Gradle 可用

$ ./gradlew app:tasks --all

> Task :app:tasks

------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------

Other tasks
-----------
compileJava - Compiles main Java source.
compileTestJava - Compiles test Java source.
hello
processResources - Processes main resources.
processTestResources - Processes test resources.
startScripts - Creates OS-specific scripts to run the project as a JVM application.

你可以使用 ./gradlew hello 在构建脚本中执行该 task

$ ./gradlew hello
Hello world!

当 Gradle 执行 hello task 时,它会执行提供的 action。在这种情况下,action 只是一个包含一些代码的块:println("Hello world!")

Task 组和描述

可以使用 描述 详细说明上一节中的 hello task,并使用以下更新将其分配给一个

build.gradle.kts
tasks.register("hello") {
    group = "Custom"
    description = "A lovely greeting task."
    doLast {
        println("Hello world!")
    }
}
build.gradle
tasks.register('hello') {
    group = 'Custom'
    description = 'A lovely greeting task.'
    doLast {
        println 'Hello world!'
    }
}

一旦 task 被分配到一个组,它将被 ./gradlew tasks 列出

$ ./gradlew tasks

> Task :tasks

Custom tasks
------------------
hello - A lovely greeting task.

要查看有关 task 的信息,请使用 help --task <task-name> 命令

$./gradlew help --task hello

> Task :help
Detailed task information for hello

Path
:app:hello

Type
Task (org.gradle.api.Task)

Options
--rerun     Causes the task to be re-run even if up-to-date.

Description
A lovely greeting task.

Group
Custom

正如我们所看到的,hello task 属于 custom 组。

Task 依赖

你可以声明依赖于其他 task 的 task

build.gradle.kts
tasks.register("hello") {
    doLast {
        println("Hello world!")
    }
}
tasks.register("intro") {
    dependsOn("hello")
    doLast {
        println("I'm Gradle")
    }
}
build.gradle
tasks.register('hello') {
    doLast {
        println 'Hello world!'
    }
}
tasks.register('intro') {
    dependsOn tasks.hello
    doLast {
        println "I'm Gradle"
    }
}
$ gradle -q intro
Hello world!
I'm Gradle

taskXtaskY 的依赖可以在定义 taskY 之前声明

build.gradle.kts
tasks.register("taskX") {
    dependsOn("taskY")
    doLast {
        println("taskX")
    }
}
tasks.register("taskY") {
    doLast {
        println("taskY")
    }
}
build.gradle
tasks.register('taskX') {
    dependsOn 'taskY'
    doLast {
        println 'taskX'
    }
}
tasks.register('taskY') {
    doLast {
        println 'taskY'
    }
}
$ gradle -q taskX
taskY
taskX

来自先前示例的 hello task 已更新为包含依赖

build.gradle.kts
tasks.register("hello") {
    group = "Custom"
    description = "A lovely greeting task."
    doLast {
        println("Hello world!")
    }
    dependsOn(tasks.assemble)
}
build.gradle
tasks.register('hello') {
    group = "Custom"
    description = "A lovely greeting task."
    doLast {
        println("Hello world!")
    }
    dependsOn(tasks.assemble)
}

hello task 现在依赖于 assemble task,这意味着 Gradle 必须在执行 hello task 之前 执行 assemble task

$ ./gradlew :app:hello

> Task :app:compileJava UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar UP-TO-DATE
> Task :app:startScripts UP-TO-DATE
> Task :app:distTar UP-TO-DATE
> Task :app:distZip UP-TO-DATE
> Task :app:assemble UP-TO-DATE

> Task :app:hello
Hello world!

Task 配置

一旦注册,就可以通过 TaskProvider API 访问 task 以进行进一步配置。

例如,你可以使用它在运行时动态地向 task 添加依赖

build.gradle.kts
repeat(4) { counter ->
    tasks.register("task$counter") {
        doLast {
            println("I'm task number $counter")
        }
    }
}
tasks.named("task0") { dependsOn("task2", "task3") }
build.gradle
4.times { counter ->
    tasks.register("task$counter") {
        doLast {
            println "I'm task number $counter"
        }
    }
}
tasks.named('task0') { dependsOn('task2', 'task3') }
$ gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0

或者你可以向现有 task 添加行为

build.gradle.kts
tasks.register("hello") {
    doLast {
        println("Hello Earth")
    }
}
tasks.named("hello") {
    doFirst {
        println("Hello Venus")
    }
}
tasks.named("hello") {
    doLast {
        println("Hello Mars")
    }
}
tasks.named("hello") {
    doLast {
        println("Hello Jupiter")
    }
}
build.gradle
tasks.register('hello') {
    doLast {
        println 'Hello Earth'
    }
}
tasks.named('hello') {
    doFirst {
        println 'Hello Venus'
    }
}
tasks.named('hello') {
    doLast {
        println 'Hello Mars'
    }
}
tasks.named('hello') {
    doLast {
        println 'Hello Jupiter'
    }
}
$ gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
可以多次执行调用 doFirstdoLast。它们在 task 的 actions 列表的开头或结尾添加一个 action。当 task 执行时,action 列表中的 actions 按照顺序执行。

这是一个使用 named 方法配置插件添加的 task 的示例

build.gradle.kts
tasks.dokkaHtml.configure {
    outputDirectory.set(buildDir)
}
build.gradle
tasks.named("dokkaHtml") {
    outputDirectory.set(buildDir)
}

Task 类型

Gradle task 是 Task 的子类。

在构建脚本中,HelloTask 类是通过扩展 DefaultTask 创建的

build.gradle.kts
// Extend the DefaultTask class to create a HelloTask class
abstract class HelloTask : DefaultTask() {
    @TaskAction
    fun hello() {
        println("hello from HelloTask")
    }
}

// Register the hello Task with type HelloTask
tasks.register<HelloTask>("hello") {
    group = "Custom tasks"
    description = "A lovely greeting task."
}
build.gradle
// Extend the DefaultTask class to create a HelloTask class
class HelloTask extends DefaultTask {
    @TaskAction
    void hello() {
        println("hello from HelloTask")
    }
}

// Register the hello Task with type HelloTask
tasks.register("hello", HelloTask) {
    group = "Custom tasks"
    description = "A lovely greeting task."
}

hello task 使用 类型 HelloTask 注册。

执行我们的新 hello task

$ ./gradlew hello

> Task :app:hello
hello from HelloTask

现在 hello task 的类型是 HelloTask 而不是 Task 类型。

Gradle help task 显示了更改

$ ./gradlew help --task hello

> Task :help
Detailed task information for hello

Path
:app:hello

Type
HelloTask (Build_gradle$HelloTask)

Options
--rerun     Causes the task to be re-run even if up-to-date.

Description
A lovely greeting task.

Group
Custom tasks

内置 task 类型

Gradle 提供了许多具有常用和流行功能的内置 task 类型,例如复制或删除文件。

此示例 task 使用 Copy 内置 task 将 *.war 文件从 source 目录复制到 target 目录

build.gradle.kts
tasks.register<Copy>("copyTask") {
    from("source")
    into("target")
    include("*.war")
}
build.gradle
tasks.register('copyTask', Copy) {
    from("source")
    into("target")
    include("*.war")
}

开发人员可以利用许多 task 类型,包括 GroovyDocZipJarJacocoReportSignDelete,这些类型在 DSL 中可用。

下一步: 学习如何编写 Tasks >>