文档章节

gradle学习(15)-任务

xxjbs001
 xxjbs001
发布于 2015/01/16 11:26
字数 1813
阅读 272
收藏 1

1.任务覆盖


所谓任务覆盖就是,就是2个任务名称相同,但是却还可以同时存在。这是为啥,因为有overwrite,类似于java中重写。


task copy << {
	println "this is a first"
}

task copy(overwrite:true)<<{
	println "this is a second"
}

执行命令


D:\GRADLE~2\0112>gradle -q copy
this is a second

如果不在第二个copy中写overwrite的话,就会报错,提示任务已经存在。


D:\GRADLE~2\0112>gradle -q copy

FAILURE: Build failed with an exception.

* Where:
Build file 'D:\gradle_product\0112\build.gradle' line: 5

* What went wrong:
A problem occurred evaluating root project '0112'.
> Cannot add task ':copy' as a task with that name already exists.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.


2.跳过任务


gradle有很多种方式达到跳过任务执行的方式,下面一一列举:


使用断言


task hello <<{
	println 'hello world'
}

hello.onlyIf{!project.hasProperty('skipHello')}

如果执行gradle -q hello命令


D:\GRADLE~2\0112>gradle -q hello
hello world

但是在该命令后面加上一些-P参数,来添加属性,命令的执行结果就不一样了:


D:\GRADLE~2\0112>gradle -q hello -P skipHello
D:\GRADLE~2\0112>

没有打印任何信息,说明任务hello被跳过了。


抛出StopExecutionException


和java类似,可以通过抛出异常,来跳过某个任务的执行


task compile <<{
	println "We are doing the compile"
}

compile.doFirst{
	if(true){throw new StopExecutionException()}
}

task myTask(dependsOn:'compile')<<{
	println 'I am not affected'
}

执行结果如下:


D:\GRADLE~2\0112>gradle -q myTask
I am not affected


任务的enabled属性


每一次任何都有一个enabled属性,默认情况下该属性是true的。但是你也可以根据自己的需要将该属性设置为false,来达到跳过任务的作用的。



task disableMe <<{
	println 'ni dou bu hui zhi xing ,ni hai shuo zhe me duo hua'
}

disableMe.enabled = false

执行命令后的是没有任何输出的:


D:\GRADLE~2\0112>gradle disableMe
:disableMe SKIPPED

BUILD SUCCESSFUL

Total time: 2.216 secs

3.跳过up-to-date式的任务


task transform{
	ext.srcFile = file('mountains.xml')
	ext.destDir = new File(buildDir,'generated')
	doLast{
		println "Transforming source file"
		destDir.mkdirs()
		def mountains = new XmlParser().parse(srcFile)
		mountains.mountain.each{
			mountain ->
			def name = mountain.name[0].text()
			def height = mountain.height[0].text()
			def destFile = new File(destDir,"${name}.txt")
			destFile.text = "$name -> ${height}\n"
		}
	}
}

这个时候执行任务是会报错的:


D:\GRADLE~2\0112>gradle -q transform
Transforming source file

FAILURE: Build failed with an exception.

* Where:
Build file 'D:\gradle_product\0112\build.gradle' line: 7

* What went wrong:
Execution failed for task ':transform'.
> D:\gradle_product\0112\mountains.xml (系统找不到指定的文件。)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.

因为需要添加一个mountains.xml文件。



那么这个xml文件里写啥呢?不能说定义一个空的xml文件吧。那就要从任务的定义来看了,因为build.gradle中要读的属性有mountain,name,height。mountain又包含name和height。那么我的xml应该定义如下:


<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
<mountain>
 <name>doctorq</name>
 <height>111</height>
</mountain>

这个时候执行命令:


D:\GRADLE~2\0112>gradle transform
:transform
Transforming source file

BUILD SUCCESSFUL

Total time: 3.416 secs
D:\GRADLE~2\0112>gradle transform
:transform
Transforming source file

BUILD SUCCESSFUL

Total time: 2.309 secs

从上面可以看出2次执行的结果输出的结果是一样的,没有什么差异。那么如果能让任务是一个up-to-date式呢。


我们修改一下build.gradle中transform任务的定义,添加2个属性inputs和outputs:


task transform{
	ext.srcFile = file('mountains.xml')
	ext.destDir = new File(buildDir,'generated')
	inputs.file srcFile
	outputs.file destDir
	doLast{
		println "Transforming source file"
		destDir.mkdirs()
		def mountains = new XmlParser().parse(srcFile)
		mountains.mountain.each{mountain ->
			def name = mountain.name[0].text()
			def height = mountain.height[0].text()
			def destFile = new File(destDir,"${name}.txt")
			destFile.text = "$name -> ${height}\n"
		}
	}
}


这个时候我们再执行任务的时候就会发现,第一次执行的时候是没有任何差异的,但是以后执行的时候,任务后面就会多了一个up-to-date的标识:


D:\GRADLE~2\0112>gradle transform
:transform
Transforming source file

BUILD SUCCESSFUL

Total time: 2.496 secs
D:\GRADLE~2\0112>gradle transform
:transform UP-TO-DATE

BUILD SUCCESSFUL

Total time: 2.34 secs
D:\GRADLE~2\0112>gradle transform
:transform UP-TO-DATE

BUILD SUCCESSFUL

Total time: 2.325 secs

当你把build/generated目录删除掉以后,重新执行gradle transform任务的时候,是没有UP-TO-DATE标识的。但是一旦有build/generated目录就会显示UP-TO-DATE目录,提示你是最新生成的。


上面的2两个属性分别所属类别如下:

inputs属于TaskInputs类型下的

outputs属于TaskOutputs类型下的


需要注意的是,如果一个任务没有定义outputs属性,就永远都不会出现UP-TO-DATE的。对于下面情形,task任务仍然被看作UP-TO-DATE。

1.outputs定位的不是文件

2.TaskOutpusts.upToDateWhen方法被调用


原理


上面说了那么多,那么我们让任务出现UP-TO-DATE到底有什么用呢?

gradle在任务第一次被执行的时候,会记住任务的输入文件以及里面的内容。执行成功后,会记住任务的输出文件以及里面的内容。在下次执行任务的时候,同样会记住这些内容,我们称这些为记忆。


在新的一次任务执行来了以后,在该任务执行前,gradle会生成新的记忆。然后将该新的记忆和之前的记忆来比对,如果输出的文件和文件中的内容没有任何变化,就标记为UP-TO-DATE且跳过该任务,只有不同的时候,才会执行该任务。这样的话可以使任务的执行更快。



4.任务规则


任务的行为依赖传入的参数,这个时候需要提供任务的规则。


tasks.addRule("Pattern:ping<ID>"){
    String taskName ->
    if(taskName.startsWith("ping")){
        task(taskName)<<{
            println taskName
            println "Pinging: " + (taskName-'ping')
        }
    }
}


输出:


D:\GRADLE~2\0112>gradle -q pingServer1
pingServer1
Pinging: Server1

build.gradle文件中,addRule中的参数是一个字符串,它其实是该rule的描述信息。可以通过gradle tasks查看:


Rules
-----
Pattern:ping<ID>

To see all tasks and more detail, run with --all.

BUILD SUCCESSFUL

上面我们是通过命令行来传入,下面来看看通过依赖的方式,调用。


tasks.addRule("Pattern:ping<ID>"){
	String taskName ->
	if(taskName.startsWith("ping")){
		task(taskName)<<{
			println "Pinging: " + (taskName-'ping')
		}
	}
}
task groupPing{
	dependsOn pingServer1,pingServer2
}

D:\GRADLE~2\0112>gradle -q groupPing
Pinging: Server1
Pinging: Server2


5.Finalizer任务


这让我想起了java中Object类中的finalize方法。需要注意的是,该特性目前还不完善,以后可能发生改变。

在这个里面我们要理解2个概念,一个是终止的任务finalizer task,一个是被终止的任务finalized  task。

finalizer task是我们这节要讲的task,finalized task是被finalizer修饰的task。看下面的例子:


task taskX << {
	println 'taskX'
}

task taskY << {
	println 'taskY'
}

taskX.finalizedBy taskY

D:\GRADLE~2\0112>gradle -q taskX
taskX
taskY


上面的任务taskX ,taskY哪一个是finalizer,哪个是finalized呢?

被修饰的是taskX,所以taskX是finalized,taskY是finalizer,知道这两个概念是很重要的。

下面再来研究一下finalizer任务的特性:


被修饰任务失败,finalizer任务也会照常执行


task taskX << {
	throw new RuntimeException()
	println 'taskX'
}

task taskY << {
	println 'taskY'
}

taskX.finalizedBy taskY

执行命令后输出:


D:\GRADLE~2\0112>gradle -q taskX
taskY

FAILURE: Build failed with an exception.

* Where:
Build file 'D:\gradle_product\0112\build.gradle' line: 2

* What went wrong:
Execution failed for task ':taskX'.
> java.lang.RuntimeException (no error message)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.

这个时候你会发现在taskX执行失败的情况下,taskY却正常执行。finalizer任务是依赖于taskX的,如果taskX不执行,那么taskY也不执行,那么至于taskX执行的成不成功,不是finalizer任务所关系的。

本文转载自:http://blog.csdn.net/itfootball/article/details/42638123

xxjbs001
粉丝 55
博文 753
码字总数 217215
作品 0
浦东
QA/测试工程师
私信 提问
自动化构建Android项目 ---- Jenkins自动化部署学习笔记(二)

  上篇文章跟大家分享了在Windows上安装Jenkins的方法,这篇文章来跟大家分享一下利用Jenkins自动化构建Android项目: 一、所需准备: Android项目上传至版本管理平台,这里我准备了Githu...

onestravel
2018/05/22
0
0
拥抱 Android Studio 之二:Android Studio 与 Gradle 深入

关于学习方式 曾经跟朋友讨论过我们所接受过的大学工科教育,都是一上来先学基础理论,最后再来一个金工实习。一开始不知道为什么而学,学不进去,荒废了基础,等到金工实习的时候,又发现基...

张磊
2016/05/25
131
0
全面理解Gradle - 执行时序

什么是Gradle? 一个像 Ant 一样的非常灵活的通用构建工具 一种可切换的, 像 maven 一样的基于合约构建的框架 支持强大的多工程构建 支持强大的依赖管理(基于 ApacheIvy ) 支持已有的 maven ...

SuShine
2018/08/31
103
0
Gradle学习(十五)——增量构建

转载请注明出处:http://blog.csdn.net/lastsweetop/article/details/79025517 任何构建工具最重要的一个功能就是防止做重复工作。例如对于编译进程来说,如果已经执行了一次编译,那么就不需...

lastsweetop
2018/01/10
0
0
Learn Gradle - CH 2 基本的构建脚本介绍

1、项目和任务 Gradle 构建脚本包括两个最基本的概念,就是项目(projects)和任务(tasks)。 项目是指我们的构建产物(比如jar包)或实施产物(比如web application等)。Gradle构建脚本包...

Hassan
2015/07/12
425
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
6分钟前
0
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
8分钟前
1
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
6
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
4
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部