任务简介
The work that Gradle can do on a project is defined by one or more tasks.
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 thebuild
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 的日志输出,仅显示任务的实际输出。
任务的多种定义方式
定义一个任务有多种方式,总体分为两大类:
通过 Project 中的
task()
方法(已弃用)。通过
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
将按顺序执行 clean
、compile
和 test
:
Cleaning build directory...
Compiling source code...
Running tests...
任务类型
Gradle 提供了许多内置任务类型(Task Types),例如 Copy
、Jar
和 Exec
。以下是一个使用 Copy
任务类型的示例:
task copyFiles(type: Copy) {
from 'source'
into 'destination'
}
解释:
type: Copy
表示任务使用 Gradle 的Copy
任务类型。from
和into
配置了文件复制的源路径和目标路径。
运行 gradle copyFiles
将把 source
目录中的文件复制到 destination
目录。
跳过任务
Gradle 提供了多种方式来控制任务是否执行,例如 onlyIf
和 enabled
。
使用 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 执行任务时,会通过控制台为任务标注结果。在 Gradle 中有五种任务结果:
(无标签)或 EXECUTED
任务执行了
Task有动作,Gradle执行了这些动作。
任务没有操作和一些依赖关系,Gradle执行了一个或多个依赖关系。另请参见生命周期任务。
UP-TO-DATE
任务的输出没有改变
任务有输出和输入,但它们没有改变。请参见增量构建。
任务有动作,但任务本身告诉Gradle它并没有改变它的输出。
任务没有动作和一些依赖关系,但所有的依赖关系都是最新的、跳过的或冻结的。请参阅生命周期任务。
任务没有操作,也没有依赖关系。
FROM-CACHE
任务的输出可以从之前的执行中找到
任务已从构建缓存中恢复输出。请参见构建缓存。
SKIPPED
任务未执行其操作
NO-SOURCE
任务不需要执行其操作
任务有输入和输出,但没有来源(即找不到输入)。