ITmob-Ly
发布于 2025-01-02 / 5 阅读
0

Gradle 详解:如何创建和使用 Task

任务简介

The work that Gradle can do on a project is defined by one or more tasks.

task-in-gradle.jpeg

A task represents some independent unit of work that a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.

When a user runs ./gradlew build in the command line, Gradle will execute the build task along with any other tasks it depends on.

上文是 官方文档 中关于任务(Task)的介绍,任务(Task)表示构建执行的一些独立工作单元,是包含一系列操作的可执行代码,Gradle 在项目上执行的工作是由一个或多个 Task/任务 定义的,这可能是编译一些类、创建 JAR、生成 Javadoc 或将一些档案发布到存储库,任务可以由用户定义,也可以通过插件引入。

本文中我们尝试了解 ******什么是 Gradle Task、如何创建和使用它们,以及如何让它们协同工作。

任务定义

任务可以通过 task 关键字在构建脚本中定义。以下是一个简单的任务定义示例:

task hello {
    doLast {
        println 'Hello, World!'
    }
}

解释

  • task hello 定义了一个名为 hello 的任务。

  • doLast 是一个任务动作(Action),它指定了任务执行时运行的代码块。

  • 在这个例子中,运行 gradle hello 将打印 Hello, World!

您可以通过在终端运行以下命令来执行该任务:

gradle -q hello

输出:
Hello, World!

-q 标志用于减少 Gradle 的日志输出,仅显示任务的实际输出。

任务的多种定义方式

定义一个任务有多种方式,总体分为两大类:

  1. 通过 Project 中的 task() 方法(已弃用)。

  2. 通过 tasks 对象的 create() (已弃用)或者 register() 方法。

推荐使用 register() 定义任务

任务动作

任务可以包含多个动作/Action,这些动作按顺序执行。doLast 添加一个动作到任务的末尾,而 doFirst 添加一个动作到任务的开头。以下是一个包含多个动作的任务示例:

task multipleActions {
    doFirst {
        println 'This runs first'
    }
    doLast {
        println 'This runs last'
    }
}

运行 gradle multipleActions 将依次输出:

This runs first
This runs last

配置任务属性

任务可以配置属性,例如描述(description)或依赖关系(dependsOn)。以下是一个配置了描述和依赖的任务示例:

task compile {
    description 'Compiles source code'
    doLast {
        println 'Compiling source code...'
    }
}

task packageApp {
    description 'Packages the application'
    dependsOn compile
    doLast {
        println 'Packaging the application...'
    }
}

解释

  • description 为任务添加了描述信息,可通过 gradle tasks 查看。

  • dependsOn compile 表示 packageApp 任务依赖于 compile 任务,运行 packageApp 时会先执行 compile

运行 gradle packageApp 将输出:

Compiling source code...
Packaging the application...

自定义任务类

为什么我们需要doFirst{}doLast{}?它是是在什么之前和之后执行呢?

为了回答这个问题,我们定义一个简单的任务类并运行包含新创建的任务类的任务。

class CustomTaskType extends DefaultTask {
    @TaskAction
    def actionInTheMiddle() {
        println("Before and after this action")
    }
}

task taskWithType(type: CustomTaskType) {
    group ("tasks group name")

    doFirst { println("This runs First?") }
    doLast { println("This runs Last?") }
}

运行 gradle taskWithType 将依次输出:

This runs First?
Before and after this action
This runs Last?

任务依赖和执行顺序

任务之间的依赖关系可以通过 dependsOn 显式声明,也可以通过任务输出和输入隐式推导。以下是一个更复杂的依赖关系示例:

task clean {
    doLast {
        println 'Cleaning build directory...'
    }
}

task compile(dependsOn: clean) {
    doLast {
        println 'Compiling source code...'
    }
}

task test(dependsOn: compile) {
    doLast {
        println 'Running tests...'
    }
}

运行 gradle test 将按顺序执行 cleancompiletest

Cleaning build directory...
Compiling source code...
Running tests...

任务类型

Gradle 提供了许多内置任务类型(Task Types),例如 CopyJarExec。以下是一个使用 Copy 任务类型的示例:

task copyFiles(type: Copy) {
    from 'source'
    into 'destination'
}

解释

  • type: Copy 表示任务使用 Gradle 的 Copy 任务类型。

  • frominto 配置了文件复制的源路径和目标路径。

运行 gradle copyFiles 将把 source 目录中的文件复制到 destination 目录。

跳过任务

Gradle 提供了多种方式来控制任务是否执行,例如 onlyIfenabled

使用 onlyIf 的示例:

task conditionalTask {
    onlyIf { project.hasProperty('runConditional') }
    doLast {
        println 'This task runs only if -PrunConditional is set'
    }
}

运行 gradle conditionalTask -PrunConditional 将执行任务,而运行 gradle conditionalTask 将跳过任务。

使用 enabled 的示例

tasks.register('myTask1') {
    doLast {
        println "Executing myTask"
    }
    enabled = false // 禁用这个任务
}

// 动态控制任务的启用状态
tasks.register('myTask2') {
    doLast {
        println "Executing myTask"
    }
    // 只有当 project.hasProperty('enable') 且其值为 'true' 时才启用
    enabled = project.hasProperty('enable') && project.property('enable').toString().toBoolean()
}

可以通过 gradle myTask2 -Penable=true 来启用它,或者直接 gradle myTask2 来禁用(因为默认 enable 属性不存在)。

任务规则

任务规则允许您动态定义一组任务。例如,以下规则为以 close 开头的任务名生成任务:

tasks.addRule("Pattern: close<Name>") { String taskName ->
    if (taskName.startsWith("close")) {
        task(taskName) {
            doLast {
                println "Closing $taskName"
            }
        }
    }
}

运行 gradle closeDatabase 将输出:

Closing closeDatabase

任务的输出结果

gradle-task-outcomes.jpg

Gradle 执行任务时,会通过控制台为任务标注结果。在 Gradle 中有五种任务结果:

(无标签)或 EXECUTED

任务执行了

  • Task有动作,Gradle执行了这些动作。

  • 任务没有操作和一些依赖关系,Gradle执行了一个或多个依赖关系。另请参见生命周期任务。

UP-TO-DATE

任务的输出没有改变

  • 任务有输出和输入,但它们没有改变。请参见增量构建。

  • 任务有动作,但任务本身告诉Gradle它并没有改变它的输出。

  • 任务没有动作和一些依赖关系,但所有的依赖关系都是最新的、跳过的或冻结的。请参阅生命周期任务。

  • 任务没有操作,也没有依赖关系。

FROM-CACHE

任务的输出可以从之前的执行中找到

  • 任务已从构建缓存中恢复输出。请参见构建缓存

SKIPPED

任务未执行其操作

NO-SOURCE

任务不需要执行其操作

  • 任务有输入和输出,但没有来源(即找不到输入)。

更多