Gradle7.x学习篇02 - task配置
task的类型
tasks是org.gradle.api.internal.tasks.DefaultTaskContainer的一种实例,新版本一般建议通过register 来配置和创建task的:
// DefaultTaskContainer 的register的方法
TaskProvider<Task> register(String name, Action<? super Task> configurationAction)
register 方法通过TaskCreatingProvider来创建task,其返回类型也是TaskCreatingProvider。TaskContainer提供了findByPath来获取创建的task的对象,可以看到默认的task是DefaultTask的一种实现:
def sayHello = tasks.register('sayHello') {doLast {println 'sayHello' + " hai"}
}println sayHello
println "Class:"+sayHello.getClass().getName()
println "Superclass:"+sayHello.getClass().getSuperclass().getName()
println "-"*30def t = tasks.findByPath("sayHello")
println t.getClass()
println t.getClass().getSuperclass().getName()
输出结果:
> Configure project :
provider(task 'sayHello', class org.gradle.api.DefaultTask)
Class:org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider_Decorated
Superclass:org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider
------------------------------
class org.gradle.api.DefaultTask_Decorated
org.gradle.api.DefaultTask
TaskContainer 的register 有一些重载方法,可以指定task的类型, 比如:
<T extends Task> TaskProvider<T> register(String name, Class<T> type)
<T extends Task> TaskProvider<T> register(String name, Class<T> type, Object... constructorArgs)
<T extends Task> TaskProvider<T> register(String name, Class<T> type, Action<? super T> configurationAction)
指定的类型必须是Task一种具体实现,而且Gradle提供了一些具备特定功能的Task具体类型,比如:
Task Class | Description |
---|---|
Copy | 将文件复制到目标目录 |
Delete | 删除文件和目录 |
Exec | 执行命令行程序 |
GradleBuild | 执行Gradle构建 |
JavaExec | 在一个子进程中执行一个Java程序 |
SourceTask | 对源文件执行一些操作 |
Sync | 同步文件或者目录 |
Upload | 将配置的组件上传到执行的仓库 |
WorkResults | Helps access trivial WorkResult objects. |
WriteProperties | Writes a Properties in a way that the results can be expected to be reproducible. |
例如,可以定义一个复制文件的task,需要做的主要内容是配置task,具体的动作Copy 已经实现了:
tasks.register("copyTxt", Copy){from "origin"into "desc"
}
task的执行结果(outcomes)
task的执行结果可以被标记以下几种:
- (no label) or EXECUTED: task执行了其动作
- UP-TO-DATE:task的outputs 和inputs没有变化,动作不会被执行
- FROM-CACHE:启用缓存,task也支持缓存,task的outputs 可以从以前的执行中找到
- SKIPPED:task没有执行其动作
- NO-SOURCE:没有sources,task不需要执行其动作(Task has inputs and outputs, but no sources. For example, source files are .java files for JavaCompile.)
还是以Copy task举例,通过-i 参数显示更多日志,执行task来观察其标记标签:
- 第一次执行 gradle -i copyTxt
> Task :copyTxt Caching disabled for task ':copyTxt' because:Build cache is disabled Task ':copyTxt' is not up-to-date because:No history is available. :copyTxt (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 0.007 secs.
没有看到标签,task执行过了
- 再次执行gradle -i copyTxt
> Task :copyTxt UP-TO-DATE Caching disabled for task ':copyTxt' because:Build cache is disabled Skipping task ':copyTxt' as it is up-to-date. :copyTxt (Thread[Execution worker for ':',5,main]) completed. Took 0.002 secs.
可以看到被标记UP-TO-DATE,task被跳过了。修改源目录下文件的文本内容,再次执行:
> Task :copyTxt Caching disabled for task ':copyTxt' because:Build cache is disabled Task ':copyTxt' is not up-to-date because:Input property 'rootSpec$1' file E:\learn_gradle\test\origin\hello.txt has changed. :copyTxt (Thread[Execution worker for ':',5,main]) completed. Took 0.005 secs.
没有标签,因为源文件内容发生了变化,所以task将会被执行;同样如果目标文件内容发生了变化,task同样会被执行。:
> Task :copyTxt Caching disabled for task ':copyTxt' because:Build cache is disabled Task ':copyTxt' is not up-to-date because:Output property 'destinationDir' file E:\learn_gradle\test\desc\hello.txt has changed. :copyTxt (Thread[Execution worker for ':',5,main]) completed. Took 0.004 secs.
- 如果要启用缓存的话,可以在执行任务的时候加上参数--build-cache 或者在gradle.properties文件中指定org.gradle.caching=true, 但是并不是所有的task都支持缓存,gradle提供一些内建的支持缓存的任务,比如JavaCompile、Javadoc、Test,copy不在此列。
# 在控制台执行:gradle -i --build-cache copyTxt > Task :copyTxt UP-TO-DATE Caching disabled for task ':copyTxt' because:Caching has not been enabled for the task Skipping task ':copyTxt' as it is up-to-date. :copyTxt (Thread[Execution worker for ':',5,main]) completed. Took 0.002 secs.
可以看到Caching has not been enabled for the task。支持缓存的task需要可以使用注解@CacheableTask,此注解不可以被继承,默认task是不使用缓存的。
- 当不满足执行条件,task被跳过时,会被标记为SKIPPED
def hello = tasks.register('hello') {doLast {println 'hello world'} }hello.configure {onlyIf { !project.hasProperty('skipHello') } }
# 命令行执行:gradle hello -PskipHello -i > Task :hello SKIPPED Skipping task ':hello' as task onlyIf is false. :hello (Thread[Execution worker for ':',5,main]) completed. Took 0.001 secs.
配置inputs和outputs
task会不会被标记为UP-TO-DATE,与inputs和outputs息息相关。一种简单地配置inputs和outputs的方式可以通过Task的属性inputs和outputs:
/*** <p>Returns the inputs of this task.</p>** @return The inputs. Never returns null.*/@InternalTaskInputs getInputs();/*** <p>Returns the outputs of this task.</p>** @return The outputs. Never returns null.*/@InternalTaskOutputs getOutputs();
通过TaskInputs 和TaskOutputs 提供的接口,可以在配置任务的定义其输入和输出:
tasks.register('task_one') {inputs.file("origin/hello.txt")outputs.file("desc/test.txt")doLast {println "执行任务$name"}
}
# 命令行:gradle task_one -i
> Task :task_one
Watching 1 directory hierarchies to track changes
Caching disabled for task ':task_one' because:Build cache is disabled
Task ':task_one' is not up-to-date because:No history is available.
执行任务task_one
:task_one (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 0.007 secs.
在不改变文件内容的情况下,再次执行:
# 命令行:gradle task_one -i
> Task :task_one UP-TO-DATE
Caching disabled for task ':task_one' because:Build cache is disabled
Skipping task ':task_one' as it is up-to-date.
:task_one (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 0.002 secs.
如果修改了outputs包含的文件,那么会再次执行task:
# 命令行:gradle task_one -i
> Task :task_one
Watching 1 directory hierarchies to track changes
Caching disabled for task ':task_one' because:Build cache is disabled
Task ':task_one' is not up-to-date because:Output property '$1' file E:\learn_gradle\test\desc\test.txt has changed.
执行任务task_one
:task_one (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 0.002 secs.
TaskInputs 接口
Modifier and Type | Method | Description |
---|---|---|
TaskInputFilePropertyBuilder
|
dir(Object dirPath)
|
Registers an input directory hierarchy. |
TaskInputFilePropertyBuilder
|
file(Object path)
|
Registers some input file for this task. |
TaskInputFilePropertyBuilder
|
files(Object... paths)
|
Registers some input files for this task. |
FileCollection
|
getFiles()
|
Returns the input files of this task. |
boolean
|
getHasInputs()
|
Returns true if this task has declared the inputs that it consumes. |
boolean
|
getHasSourceFiles()
|
Returns true if this task has declared that it accepts source files. |
Map<String,Object>
|
getProperties()
|
Returns a map of input properties for this task. |
FileCollection
|
getSourceFiles()
|
Returns the set of source files for this task. |
TaskInputs
|
properties(Map<String,?> properties)
|
Registers a set of input properties for this task. |
TaskInputPropertyBuilder
|
property(String name, Object value)
|
Registers an input property for this task. |
TaskOutputs 接口
Modifier and Type | Method | Description |
---|---|---|
void
|
cacheIf(String cachingEnabledReason, Spec<? super Task> spec)
|
Cache the results of the task only if the given spec is satisfied. |
void
|
cacheIf(Spec<? super Task> spec)
|
Cache the results of the task only if the given spec is satisfied. |
TaskOutputFilePropertyBuilder
|
dir(Object path)
|
Registers an output directory for this task. |
TaskOutputFilePropertyBuilder
|
dirs(Object... paths)
|
Registers some output directories for this task. |
void
|
doNotCacheIf(String cachingDisabledReason, Spec<? super Task> spec)
|
Disable caching the results of the task if the given spec is satisfied. |
TaskOutputFilePropertyBuilder
|
file(Object path)
|
Registers some output file for this task. |
TaskOutputFilePropertyBuilder
|
files(Object... paths)
|
Registers some output files for this task. |
FileCollection
|
getFiles()
|
Returns the output files of this task. |
boolean
|
getHasOutput()
|
Returns true if this task has declared any outputs. |
void
|
upToDateWhen(Closure upToDateClosure)
|
Adds a predicate to determine whether previous outputs of this task can be reused. |
void
|
upToDateWhen(Spec<? super Task> upToDateSpec)
|
Adds a predicate to determine whether previous outputs of this task can be reused. |
配置task的执行顺序
dependsOn
task的依赖必须先执行,这个之前已经了解了
mustRunAfter
tasks.register('task_one') {println "配置任务$name"doLast {println "执行任务$name"}
}tasks.register('task_two') {mustRunAfter tasks.task_oneprintln "配置任务$name"doLast {println "执行任务$name"}
}
# gradle task_two task_one
配置任务task_one
配置任务task_two> Task :task_one
执行任务task_one> Task :task_two
执行任务task_two
# gradle task_two
配置任务task_one
配置任务task_two> Task :task_two
执行任务task_two
mustRunAfter 跟dependsOn 很大的不同就是,task不是必须要执行mustRunAfter指定的任务,而是当指定顺序的task都存在的时候,需要按照先后顺序来执行;dependsOn 则是无论有没有在命令行指明要执行依赖的task,任务的依赖都会先执行;
另外一点需要注意的,task的配置阶段执行顺序并不是当前的task一定在mustRunAfter之后。例如通过以下方式定义顺序,task_two将会先配置,所以尽量不要依赖配置阶段的执行顺序:
def task_one = tasks.register('task_one') {println "配置任务$name"doLast {println "执行任务$name"}
}def task_two = tasks.register('task_two') {println "配置任务$name"doLast {println "执行任务$name"}
}task_two.configure {mustRunAfter task_one
}
# gradle task_two task_one
配置任务task_two
配置任务task_one> Task :task_one
执行任务task_one> Task :task_two
执行任务task_two
shouldRunAfter
跟mustRunAfter相似,但是并不严格,两种情况下shouldRunAfter 不做保证:
- 通过shouldRunAfter 导致了循环的情况;mustRunAfter对于循环的情况会报错。
- 当并行执行时,除了 “should run after” 类型依赖之外,其他类型的依赖都满足的情况下,当前任务就会执行。可以认为并行的时候并不会考虑shouldRunAfter。
finalizedBy
指定当前任务的终结任务,可以用来指定在其后执行什么任务
tasks.register('task_one') {finalizedBy tasks.task_twoprintln "配置任务$name"doLast {println "执行任务$name"}
}tasks.register('task_two') {println "配置任务$name"doLast {println "执行任务$name"}
}
# gradle task_one
配置任务task_two
配置任务task_one> Task :task_one
执行任务task_one> Task :task_two
执行任务task_two
finalizedBy 更重要的作用体现在出现异常的情况, 即便出现异常,其Finalizer 也会执行:
tasks.register('task_one') {finalizedBy tasks.task_twoprintln "配置任务$name"doLast {println "执行任务$name"throw new RuntimeException()}
}tasks.register('task_two') {println "配置任务$name"doLast {println "执行任务$name"}
}
# gradle task_one
配置任务task_two
配置任务task_one> Task :task_one FAILED
执行任务task_one> Task :task_two
执行任务task_twoFAILURE: Build failed with an exception.
超时配置
超过配置的时间,任务失败并终止
tasks.register('task_one') {timeout = Duration.ofSeconds(3)println "配置任务$name"doLast {println "开始执行任务$name"Thread.sleep(5000)println "结束执行任务$name"}
}
# gradle task_one
配置任务task_one> Task :task_one
开始执行任务task_one
Requesting stop of task ':task_one' as it has exceeded its configured timeout of 3s.> Task :task_one FAILEDFAILURE: Build failed with an exception.* What went wrong:
Execution failed for task ':task_one'.
> Timeout has been exceeded
Task rules
可以通过定义Rule 在运行的时候来定义、配置并执行任务:
tasks.addRule("自定义一个Rule") { String taskName ->if (taskName.startsWith("say_")) {task(taskName) {println "rule task $name"doLast {println "执行$name"}}}
}tasks.register("task_one") {dependsOn("say_hi","say_hello")println "配置任务$name"doLast {println "执行任务$name"}
}
# gradle say_bye
rule task say_bye> Task :say_bye
执行say_bye
# gradle task_one
配置任务task_one
rule task say_hi
rule task say_hello> Task :say_hello
执行say_hello> Task :say_hi
执行say_hi> Task :task_one
执行任务task_one
通过Rule来定义的task最开始不会出现tasks任务列表中,通过gradle tasks --all 查不到, 只能看到rule的描述,所以如果定义Rule最好将描述写的更好一点。
# gradle tasks --all 结果的一部分
Rules
-----
自定义一个Rule
Gradle7.x学习篇02 - task配置相关推荐
- FC网络学习笔记02 -网络配置方法
随着新一代飞机的综合化航电系统对通信需求的不断提高,传统的ARINC429.1553B总线的传输速率分别只有100Kbps和1Mbps,其带宽已远远不 论文联盟 http://Www.LWlm.cOm ...
- vue学习篇--02内置指令 计算属性 侦听属性
文章目录 18个指令 v-text v-html: v-show: v-if: v-for: 可以遍历数组 对象 数字 字符串 v-bind: 解析属性:title src href type alt ...
- java数据类型转换方向_java基础学习篇02(数据类型转换和基本面试题)
JAVA基本数据类型转换 java中的数据类型,分为,引用数据类型和基本数据类型.基本数据类型有8中 整型:byte 8位 . short 16位 .int 32位 .long 64位. (8位=1个 ...
- Servlet和HTTP请求协议-学习笔记02【Servlet_体系结构与urlpartten配置、HTTP请求协议】
Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...
- 计算机与交换机基础配置入门,新手入门篇:交换机配置窍门深入学习 -电脑资料...
新手入门篇:交换机配置技巧深入学习,关于交换机配置技巧的问题,涉及到的东西比较多, 交换机配置技巧一直以来是非常神秘的,不仅对于一般用户,对于绝大多数网管人员来说也是如此,同时也是作为网管水平高低衡量 ...
- Hadoop学习篇(一)——初识Hadoop Hadoop单机配置
Hadoop学习篇(一) 本文档适用于Hadoop开发学习者使用 说明:如涉及到侵权,请及时联系我,并在第一时间删除文章. Hadoop简介:Hadoop是一个由Apache基金会所开发的分布式系统基 ...
- 一篇就够用了——深度学习Ubuntu16.04环境配置+Win10双系统
一篇就够用了深度学习Ubuntu16.04环境配置 必看!此教程使用说明 [必备配置]基本环境配置 1.win10+ubuntu16.04双系统安装 2.ubuntu最重要的事--切换下载源 3.ub ...
- 国产版Jetson Nano学习篇2—详细讲解Jetson Nano的开发环境配置和其 Ubuntu 18.04系统的操作,入门必看
目录 前言 1.开发环境配置 1.1联网 1.2系统汉化和安装中文输入法 1.2.1系统汉化(按需求选择) 1.2.2安装中文输入法 1.3更换关屏设置 1.4更新源和部分软件(仅供参考) 2.Pyt ...
- 网络安全学习篇35_第二阶段_lnmp、Nginx简单配置+安装报错:C compiler cc is not found缺少环境解决、安装php5.3.28
上一篇博客:网络安全学习篇34_第二阶段_apache.mysql等配置+ centOS设置中文输入法 目录 Nginx的简单介绍 Nginx的安装 安装的时候报了一个错:C compiler cc ...
最新文章
- .Net Core快速创建Windows服务
- mysql慢时如何防止重复账户_如何进行mysql数据库的优化? --慢查询定位 --索引详解 -- 定时备份...
- [BZOJ 4034][HAOI2015]树上操作(欧拉序列+线段树)
- A/B 测试:以变应变,给用户更好的体验“宠爱”
- 计算机应用基础在powerpoint中,计算机应用基础PowerPoint习题1
- Eclipse+ADT+Android SDK 搭建安卓开发环境
- 前端vscode插件合集
- esp8266 at接收数据中断时间_利用ESP8266获取网络同步时间(北京时间)
- 机器学习--支持向量机(一)什么是支持向量机
- 时区时钟插件html,日期、时间选择控件 - datetimepicker
- java 迭代_java迭代是什么意思
- linux 0.11 内核学习路线
- hdmi怎么支持2k分辨率_选择2K显示器有没有必要?
- 用Python编写账号密码登录程序
- 【耀杨的前世今生】耀杨的毕生所学——《狗叫江湖》之“葫芦给学习法”(1)
- 闲鱼上怎么引流学生粉?闲鱼如何引流客源?闲鱼的引流技巧
- 随机漫步模拟及概率分析
- 情人节你应该会用到 【表白 告白】
- Excel添加单引号
- 如何使软件标准真正能够落地?且看《深入理解GJB5000A》公开课!