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 不做保证:

  1. 通过shouldRunAfter 导致了循环的情况;mustRunAfter对于循环的情况会报错。
  2. 当并行执行时,除了 “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配置相关推荐

  1. FC网络学习笔记02 -网络配置方法

    随着新一代飞机的综合化航电系统对通信需求的不断提高,传统的ARINC429.1553B总线的传输速率分别只有100Kbps和1Mbps,其带宽已远远不 论文联盟 http://Www.LWlm.cOm ...

  2. vue学习篇--02内置指令 计算属性 侦听属性

    文章目录 18个指令 v-text v-html: v-show: v-if: v-for: 可以遍历数组 对象 数字 字符串 v-bind: 解析属性:title src href type alt ...

  3. java数据类型转换方向_java基础学习篇02(数据类型转换和基本面试题)

    JAVA基本数据类型转换 java中的数据类型,分为,引用数据类型和基本数据类型.基本数据类型有8中 整型:byte 8位 . short 16位 .int 32位 .long 64位. (8位=1个 ...

  4. Servlet和HTTP请求协议-学习笔记02【Servlet_体系结构与urlpartten配置、HTTP请求协议】

    Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...

  5. 计算机与交换机基础配置入门,新手入门篇:交换机配置窍门深入学习 -电脑资料...

    新手入门篇:交换机配置技巧深入学习,关于交换机配置技巧的问题,涉及到的东西比较多, 交换机配置技巧一直以来是非常神秘的,不仅对于一般用户,对于绝大多数网管人员来说也是如此,同时也是作为网管水平高低衡量 ...

  6. Hadoop学习篇(一)——初识Hadoop Hadoop单机配置

    Hadoop学习篇(一) 本文档适用于Hadoop开发学习者使用 说明:如涉及到侵权,请及时联系我,并在第一时间删除文章. Hadoop简介:Hadoop是一个由Apache基金会所开发的分布式系统基 ...

  7. 一篇就够用了——深度学习Ubuntu16.04环境配置+Win10双系统

    一篇就够用了深度学习Ubuntu16.04环境配置 必看!此教程使用说明 [必备配置]基本环境配置 1.win10+ubuntu16.04双系统安装 2.ubuntu最重要的事--切换下载源 3.ub ...

  8. 国产版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 ...

  9. 网络安全学习篇35_第二阶段_lnmp、Nginx简单配置+安装报错:C compiler cc is not found缺少环境解决、安装php5.3.28

    上一篇博客:网络安全学习篇34_第二阶段_apache.mysql等配置+ centOS设置中文输入法 目录 Nginx的简单介绍 Nginx的安装 安装的时候报了一个错:C compiler cc ...

最新文章

  1. .Net Core快速创建Windows服务
  2. mysql慢时如何防止重复账户_如何进行mysql数据库的优化? --慢查询定位 --索引详解 -- 定时备份...
  3. [BZOJ 4034][HAOI2015]树上操作(欧拉序列+线段树)
  4. A/B 测试:以变应变,给用户更好的体验“宠爱”
  5. 计算机应用基础在powerpoint中,计算机应用基础PowerPoint习题1
  6. Eclipse+ADT+Android SDK 搭建安卓开发环境
  7. 前端vscode插件合集
  8. esp8266 at接收数据中断时间_利用ESP8266获取网络同步时间(北京时间)
  9. 机器学习--支持向量机(一)什么是支持向量机
  10. 时区时钟插件html,日期、时间选择控件 - datetimepicker
  11. java 迭代_java迭代是什么意思
  12. linux 0.11 内核学习路线
  13. hdmi怎么支持2k分辨率_选择2K显示器有没有必要?
  14. 用Python编写账号密码登录程序
  15. 【耀杨的前世今生】耀杨的毕生所学——《狗叫江湖》之“葫芦给学习法”(1)
  16. 闲鱼上怎么引流学生粉?闲鱼如何引流客源?闲鱼的引流技巧
  17. 随机漫步模拟及概率分析
  18. 情人节你应该会用到 【表白 告白】
  19. Excel添加单引号
  20. 如何使软件标准真正能够落地?且看《深入理解GJB5000A》公开课!

热门文章

  1. 微信公众号开发——服务器配置
  2. php mysql三_PHP 和 MySQL 基础教程(三)
  3. 【分享】微软面试题及答案 (很需要开放性思维啊)
  4. java contains方法_Java contains用法示例
  5. #模拟#洛谷 1338 末日的传说
  6. Eclipse版本和JDK版本对应关系
  7. Qt实用技巧:ubuntu发布程序打包流程(解决插件xcb加载失败)
  8. SpringMVC一
  9. 剑指泛娱乐,互联网企业产业布局再度升级
  10. Windows鼠标隐藏