Gradle tip #3-Task顺序

翻译 2015年07月18日 01:31:34

原文链接

我注意到我在使用Gradle的时候遇到的大多数问题都是和task的执行顺序有关的。很明显如果我的构建会工作的更好如果我的task都是在正确的时候执行。下面我们就深入了解一下如何更改task的执行顺序。

dependsOn

我认为最直接的方式来说明的你task的执行时依赖别的task的方法就是使用dependsOn方法。
比如下面的场景,已经存在task A,我们要添加一个task B,它的执行必须要在A执行完之后:
B->A
这是一个很简单的场景,假定A和B的定义如下:

task A << {println 'Hello from A'}
task B << {println 'Hello from B'}

只需要简单的调用B.dependsOn A,就可以了。
这意味着,只要我执行task B,task A都会先执行。

paveldudka$ gradle B
:A
Hello from A
:B
Hello from B

另外,你也可以在task的配置区中来声明它的依赖:

task A << {println 'Hello from A'}
task B {
    dependsOn A
    doLast {
        println 'Hello from B'  
    }
}

如果我们想要在已经存在的task依赖中插入我们的task该怎么做呢?
insert task
过程和刚才类似。假定已经存在如下的task依赖:

task A << {println 'Hello from A'}
task B << {println 'Hello from B'}
task C << {println 'Hello from C'}

B.dependsOn A
C.dependsOn B

加入我们的新的task

task B1 << {println 'Hello from B1'}
B1.dependsOn B
C.dependsOn B1

输出:

paveldudka$ gradle C
:A
Hello from A
:B
Hello from B
:B1
Hello from B1
:C
Hello from C

注意dependsOn把task添加到依赖的集合中,所以依赖多个task是没有问题的。
multi depends

task B1 << {println 'Hello from B1'}
B1.dependsOn B
B1.dependsOn Q

输出:

paveldudka$ gradle B1
:A
Hello from A
:B
Hello from B
:Q
Hello from Q
:B1
Hello from B1

mustRunAfter

现在假定我又一个task,它依赖于其他两个task。这里我使用一个真实的场景,我有两个task,一个单元测试的task,一个是UI测试的task。另外还有一个task是跑所有的测试的,它依赖于前面的两个task。
all tests

task unit << {println 'Hello from unit tests'}
task ui << {println 'Hello from UI tests'}
task tests << {println 'Hello from all tests!'}

tests.dependsOn unit
tests.dependsOn ui

输出:

paveldudka$ gradle tests
:ui
Hello from UI tests
:unit
Hello from unit tests
:tests
Hello from all tests!

尽管unitest和UI test会子啊test task之前执行,但是unit和ui这两个task的执行顺序是不能保证的。虽然现在来看是按照字母表的顺序执行,但这是依赖于Gradle的实现的,你的代码中绝对不能依赖这种顺序。
由于UI测试时间远比unit test时间长,因此我希望unit test先执行。一个解决办法就是让ui task依赖于unit task。
ui->unit

task unit << {println 'Hello from unit tests'}
task ui << {println 'Hello from UI tests'}
task tests << {println 'Hello from all tests!'}

tests.dependsOn unit
tests.dependsOn ui
ui.dependsOn unit // <-- I added this dependency

输出:

paveldudka$ gradle tests
:unit
Hello from unit tests
:ui
Hello from UI tests
:tests
Hello from all tests!

现在unit test会在ui test之前执行了。
但是这里有个很恶心的问题,我的ui测试其实并不依赖于unit test。我希望能够单独的执行ui test,但是这里每次我执行ui test,都会先执行unit test。
这里就要用到mustRunAfter了。mustRunAfter并不会添加依赖,它只是告诉Gradle执行的优先级如果两个task同时存在。比如我们这里就可以指定ui.mustRunAfter unit,这样如果ui task和unit task同时存在,Gradle会先执行unit test,而如果只执行gradle ui,并不会去执行unit task。

task unit << {println 'Hello from unit tests'}
task ui << {println 'Hello from UI tests'}
task tests << {println 'Hello from all tests!'}

tests.dependsOn unit
tests.dependsOn ui
ui.mustRunAfter unit

输出:

paveldudka$ gradle tests
:unit
Hello from unit tests
:ui
Hello from UI tests
:tests
Hello from all tests!

依赖关系如下图:
mustRunAfter

mustRunAfter在Gradle2.4中目前还是实验性的功能。

finalizedBy

现在我们已经有两个task,unit和ui,假定这两个task都会输出测试报告,现在我想把这两个测试报告合并成一个:
merge

task unit << {println 'Hello from unit tests'}
task ui << {println 'Hello from UI tests'}
task tests << {println 'Hello from all tests!'}
task mergeReports << {println 'Merging test reports'}

tests.dependsOn unit
tests.dependsOn ui
ui.mustRunAfter unit
mergeReports.dependsOn tests

现在如果我想获得ui和unit的测试报告,执行task mergeReports就可以了。

paveldudka$ gradle mergeReports
:unit
Hello from unit tests
:ui
Hello from UI tests
:tests
Hello from all tests!
:mergeReports
Merging test reports

这个task是能工作,但是看起来好笨啊。mergeReports从用户的角度来看感觉不是特别好。我希望执行tests task就可以获得测试报告,而不必知道mergeReports的存在。当然我可以把merge的逻辑挪到tests task中,但我不想把tests task搞的太臃肿,我还是继续把merge的逻辑放在mergeReports task中。
finalizeBy来救场了。顾名思义,finalizeBy就是在task执行完之后要执行的task。修改我们的脚本如下:

task unit << {println 'Hello from unit tests'}
task ui << {println 'Hello from UI tests'}
task tests << {println 'Hello from all tests!'}
task mergeReports << {println 'Merging test reports'}

tests.dependsOn unit
tests.dependsOn ui
ui.mustRunAfter unit
mergeReports.dependsOn tests

tests.finalizedBy mergeReports

现在执行tests task就可以拿到测试报告了:

paveldudka$ gradle tests
:unit
Hello from unit tests
:ui
Hello from UI tests
:tests
Hello from all tests!
:mergeReports
Merging test reports

注意,finalizedBy也是Gradle2.4的实验性功能

Gradle 第三讲 之 task依赖及属性设置

本讲继续根据gradle user guide进行学习 1.任务依赖 2.动态任务 3.快捷标记 4.附加的task属性 1.任务依赖: task intro(dependsOn: hell...
  • u010479969
  • u010479969
  • 2015年12月01日 16:42
  • 4294

Gradle Task基本知识

本文内容是参考http://android.jobbole.com/81485/整理得来的。 1:gradle脚本是使用groovy语言写的(DSL),groovy中有一个重要的概念闭包(Closu...
  • xueshanhaizi
  • xueshanhaizi
  • 2015年11月01日 12:38
  • 4293

Gradle Task的使用

文/咖枯(简书作者) 原文链接:http://www.jianshu.com/p/cd1a78dc8346 前言 我们的项目打包APK前需要根据业务需要更改AndroidMa...
  • a_ycmbc
  • a_ycmbc
  • 2017年01月03日 19:04
  • 7934

gradle 两种task的区别

gradle 可以定义两类task   第一种   task a(){ //todo sometings } 第二种 task b // todo some...
  • u012398902
  • u012398902
  • 2016年01月13日 17:53
  • 2600

gradle学习笔记之hook task

这周在项目中加入hotfix功能,在gradle下需要在构建流程中嵌入代码注入的处理,用到了hook task(在已有插件Taskgraph中嵌入自定义task),参考ReactNative的reac...
  • yuanjw2014
  • yuanjw2014
  • 2017年01月07日 19:58
  • 1475

Gradle task简单使用

还望支持个人博客站:http://www.enjoytoday.cntask是什么task是gradle构建脚本的最小运行单元,我们通过在gradle脚本中创建task任务,以期完成某个特定的功能,t...
  • chf1142152101
  • chf1142152101
  • 2017年05月31日 11:15
  • 760

Gradle执行顺序

1 gradle的解析顺序:rootproject 的setting.gradle,然后是rootproject的build.gradle,然后是各个subproject。所以project下的bu...
  • m75100313
  • m75100313
  • 2016年12月01日 21:55
  • 1746

Gradle run方法报错

当一个项目中存在多个main方法的时候,我们就需要指定我们的main方法 报错信息解决方法在build.gradle中加入如下语句://运行时的主类 mainClassName = "com.wuba...
  • qhshiniba
  • qhshiniba
  • 2015年07月30日 15:38
  • 1191

Eclipse搭建Gradle项目并在tomcat上运行(git项目)

Gradle提供了不输于maven的依赖管理 在改用Gradle作为构建工具。一部分的github上的示例代码也在用Gradle构建,如果还是只能用maven,那么很多好的项目都只能用肉眼看,不能真正...
  • hj7jay
  • hj7jay
  • 2016年12月01日 18:12
  • 9742

6个技巧加速你的gradle编译

最近我们都在讨论build系统,我们看了一些技巧可以让你的Maven build更快。结论和反映都势不可挡。由于我们提供的技巧,更多的人都很高兴能加快他们完成自己的项目。现在,让我们看一下怎么处理gr...
  • lyhhj
  • lyhhj
  • 2016年02月22日 19:49
  • 7778
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Gradle tip #3-Task顺序
举报原因:
原因补充:

(最多只允许输入30个字)