Gradle是什么?
Gradle是一个开源的构建自动化工具,它被设计成足够灵活,可以构建几乎所有类型的软件。
Gradle 默认使用build.gradle脚本(Groovy)或者build.gradle.kts(Koltin)脚本,可以类比于maven中的pom.xml,但是gradle脚本就是代码,会更加灵活更加强大。
默认情况下,在控制台直接执行gradle, 将会搜索build.gradle并执行。可以通过 -b参数指定脚本文件,例如:
gradle -b hello.txt
Gradle脚本的执行分三个阶段
- 初始化阶段(Initialization):建立环境,决定哪些project会参与
- 配置阶段(Configuration):创建并配置task图,确定哪些task将会执行以及他们的执行顺序;
- 执行阶段(Execution):执行task
Gradle的核心 - task
task也是最基本的执行单元,它由三部分组成:Actions、Inputs、Outputs。
定义task
早期的Gradle版本一般都是这样的:
//早期版本 最新7.X版本也支持
task sayHelloV1 {
println "在配置阶段执行"
doLast {
println "后执行action"
}
}
//早期版本 << 表示doLast,最新版本不支持
task sayHelloV2 << {
println "后执行action"
}
最新版本目前给的例子都是通过tasks(这也是推荐的方式,留意后面配置阶段的执行可以看到区别)来定义task:
//build.gradle
tasks.register("sayHello") {
println "在配置阶段执行"
doFirst{
println "先执行"
}
doLast{
println "后执行"
}
}
执行task
tasks.register("sayWow") {
println "sayWow配置阶段执行"
doFirst {
println "sayWow doFirst action"
}
}
tasks.register("sayHello") {
println "sayHello配置阶段执行"
doFirst {
println "sayHello doFirst action"
}
doLast {
println "sayHello doLast action"
}
}
task sayGood {
println "sayGood配置阶段执行"
doLast {
println "sayGood doLast action"
}
}
执行时 gradle 指定需要执行的task名称,可以指定多个task,在控制台执行:gradle sayHello sayGood sayWow
> Configure project :
sayGood配置阶段执行
sayHello配置阶段执行
sayWow配置阶段执行
> Task :sayHello
sayHello doFirst action
sayHello doLast action
> Task :sayGood
sayGood doLast action
> Task :sayWow
sayWow doFirst action
BUILD SUCCESSFUL in 366ms
3 actionable tasks: 3 executed
多次验证下来可以发现以下几个结论:
- 任务的配置阶段优先与所有action,且同一种方式定义的task配置阶段执行的顺序,跟gradle 命令后指定的顺序有关;但是通过task定义的任务比tasks.register定义的任务优先执行配置;
- 通过task定义的任务,不论gradle命令后面有没有指定该任务,此任务的配置阶段都会执行;但是通过tasks.register定义的任务,只有gradle命令指定的任务的配置阶段才会执行;
- 在配置阶段执行完后,会执行任务的动作doFirst和doLast;任务的执行顺序跟gradle命令后面的参数顺序有关;
- 只有gradle命令指定的任务,才会在执行阶段执行(暂时不考虑依赖关系)
关于doFirst和doLast两种动作
doFirst每次定义都是要将当前的动作放在最开始执行,而doLast每次定义都是要将当前动作放在最后执行:
tasks.register("sayHello") {
println "sayHello配置阶段执行"
doFirst {
println "sayHello doFirst action 1"
}
doFirst {
println "sayHello doFirst action 2"
}
doLast {
println "sayHello doLast action 1"
}
doLast {
println "sayHello doLast action 2"
}
}
执行阶段的结果如下:
> Task :sayHello
sayHello doFirst action 2
sayHello doFirst action 1
sayHello doLast action 1
sayHello doLast action 2
task的依赖管理
task的依赖定义有很多种,比较简单且常用的有两种:
- 第一种简单方式
tasks.register("sayGood") {
println "sayGood配置阶段"
doLast {
println "sayGood doLast action"
}
}
tasks.register("sayNight") {
dependsOn tasks.sayGood
println "sayNight配置阶段"
doLast {
println "sayNight doLast action"
}
}
执行结果:
sayGood配置阶段
sayNight配置阶段
> Task :sayGood
sayGood doLast action
> Task :sayNight
sayNight doLast action
- 第二种简单方式
tasks.register("sayNight") {
dependsOn "sayGood"
println "sayNight配置阶段"
doLast {
println "sayNight doLast action"
}
}
tasks.register("sayGood") {
println "sayGood配置阶段"
doLast {
println "sayGood doLast action"
}
}
执行输出结果:
sayNight配置阶段
sayGood配置阶段
> Task :sayGood
sayGood doLast action
> Task :sayNight
sayNight doLast action
比较上面两个输出,可以看到两种方式定义的依赖其配置阶段执行的先后顺序不一致。
任务的依赖远不止这样,比如可以增加变量:
def sayNight = tasks.register("sayNight") {
println "sayNight配置阶段"
doLast {
println "sayNight doLast action"
}
}
def sayGood = tasks.register("sayGood") {
println "sayGood配置阶段"
doLast {
println "sayGood doLast action"
}
}
sayNight.configure {
dependsOn sayGood
}
还可以依赖别的project的task等等,还有多种用法;
借助代码更加灵活的定义task
这是官网的一个例子:
4.times { counter ->
tasks.register("task$counter") {
doLast {
println "I'm task number $counter"
}
}
}
tasks.named('task0') { dependsOn('task2', 'task3') }
或者可以使用更复杂的情况(因为是代码,所以可以充分发挥想象):
def c_tasks = "nice to meet you".split(" ")
def task_prefix = "myTask_"
c_tasks.each{ t ->
tasks.register(task_prefix + t) {
if (t == "to") {
dependsOn task_prefix + "nice"
}
println "config task $name"
doLast {
println "task name $name"
}
}
}
tasks.named(task_prefix + "you") {
dependsOn (task_prefix + "nice", task_prefix + "meet")
}