Gradle Task

Posted by CoXier on April 1, 2017

一、Task 概述

Gradle 有两个很基础的对象 project 和 task 。每个 Gradle 构建工程有一个或多个 project,project 由多个 task 组成。task 之间可以存在依赖关系,也可以定义执行顺序。从面向对象角度来看,task 是某个类型 Task 的一个实例。如 Android 工程,每个 Module (包括 root)都会有一个 build.gradle, 这是 Gradle 默认的 build 配置文件,根据 build.gradle 文件可以初始化 project 对象以及该 project 下的若干个 task。

本文将从五个方面来梳理 Task :

  • 一、定义 task
  • 二、task 依赖关系
  • 三、task 间的执行顺序 mustRunAfter
  • 四、自定义 Task

二、定义 task

project.task("task1")

task("task2")

task task3{
  description "Task3"
  //or description("task3")、description = "task3"
  group "UniqueStudio"
  // or group("UniqueStudio")、group = "UniqueStudio"


  doLast{
    println "HelloWorld"
  }

}

task3 的声明方式是最常用的。gradle 为了方便开发者管理 project 中的 task,定义了属性 group。为了描述某个 task 的任务,定义了 description 。

使用gradle tasks查看当前 project 的 tasks,输出如下:

UniqueStudio tasks
------------------
task3 - Task3

要查看 task1 task2,使用 gradle tasks --all

三、Task 依赖关系

3.1 dependsOn

定义:如果 task A 没有 task B 无法正常工作,则称 A dependsOn B,所以也隐含了 B 运行在 A 之前。

例如穿鞋应该 dependsOn 穿袜子:

task putOnSocks {
    doLast {
        println "Putting on Socks."
    }
}

task putOnShoes {
    dependsOn "putOnSocks"
    doLast {
        println "Putting on Shoes."
    }
}

除了上述的声明方式外,还有另外几种。

3.1.1 Adding dependency on task from another project

project('projectA') {
    task taskX(dependsOn: ':projectB:taskY') {
        doLast {
            println 'taskX'
        }
    }
}

project('projectB') {
    task taskY {
        doLast {
            println 'taskY'
        }
    }
}

除了同一个 project 下的 task 可以声明依赖关系,不同 project 间的 task 也可以声明依赖关系。每一个 task 的完整名 : :currentProject:taskA

3.1.2 Adding dependency using task object

task taskX {
    doLast {
        println 'taskX'
    }
}

task taskY {
    doLast {
        println 'taskY'
    }
}

taskX.dependsOn taskY

通过 task 对象直接声明依赖关系。这个方式特别有用,有些 gradle plugin 内置了一些 task,我们想在已有的 task 基础上做些事情,比如在 assembleDebug 运行之前检查代码规范。

3.3 mustRunAfter

A 和 B 单独执行并不存在依赖关系,但是如果需要同时执行,则 A 必须在 B之后,则就说 A mustRunAfter B

定义看上去略有些抽象,先看个小例子。

task taskA {
  doLast{
    println "from A"
  }
}

task taskB {
  doLast{
    println "from B"
  }
}

taskB.mustRunAfter taskA

执行 taskB 和 taskA,输出结果:

gradle -q taskB taskA
from A
from B

虽然输入时 taskB 在前,但是因为声明了 taskB.mustRunAfter taskA,所以 taskA 先执行。另外需要说明,taskA 和 taskB 没有依赖关系,他们可以独自被执行。这也是 mustRunAfterdependsOn 的最大区别:dependsOn 侧重指定哪些 task 需要被执行,而且这些 task 执行有一定顺序;而 mustRunAfter 侧重强调多个 task 同时执行时的顺序。

五、自定义 Task

自定义 Task 只需要继承 DefaultTask,下面的例子是对上面几部分的一个总结。

class GreetingToFileTask extends DefaultTask {

    def destination

    File getDestination() {
        project.file(destination)
    }

    @TaskAction
    def greet() {
        def file = getDestination()
        file.parentFile.mkdirs()
        file.write "Hello!"
    }
}

task greet(type: GreetingToFileTask) {
    destination = { project.greetingFile }
}

task sayGreeting(dependsOn: greet) {
    doLast {
        println file(greetingFile).text
    }
}

ext.greetingFile = "$buildDir/hello.txt"