gradle task入门
//源码来自w3cschool https://www.w3cschool.cn/gradle/
//以下是本人阅读教程总结 欢迎指正!
//所有的程序都从hello world开始 O(∩_∩)O~~
task hello{
doLast{
println 'Hello world!'
}
}
//上一个任务的简写形式
task hello1 << {
println 'This is task hello1'
}
//这么写是全局执行的 当执行这个任务之后定义的任何任务时都会执行这个任务(所以要注释掉)
//task hello2 {
// println 'This is task hello2'
//}
//字符串转大写
task upper << {
String someString = 'mY_nAmE'
println 'Original: ' + someString
println 'Upper case: ' + someString.toUpperCase()
}
//循环输出4次
task count << {
4.times{println '$it '}
}
//见识下lambda
task count1 << {
5.times{counter->
println counter + ''
println counter*10 + ''
}
}
//难道标准的无参lambda不是这样的嘛? 抱歉,这么玩是不行的 O(∩_∩)O哈哈~
//task count2 << {
// 2.times{()->
// println 'stand.'
// }
//}
//任务依赖,先执行依赖的任务 再执行当前任务
task intro(dependsOn: hello) << {
println "I'm Gradle"
}
//延迟依赖,加引号的作用是依赖的任务可以在当前任务之后定义,延迟依赖=依赖的任务可以延迟定义
task latter(dependsOn: 'depLatter') << {
println "I'm Latter"
}
task depLatter << {
println "I'm depLatter"
}
//测试能不能调用依赖任务中定义的变量(结果:不能!)
task mytest(dependsOn: 'upper') << {
println 'mytest case: ' + someString.toUpperCase()
}
//创建动态任务,循环创建三个任务:task1 task2 task3. 执行如:gradle -q task2等
3.times{counter->
task "task$counter" << {
println "I'm task number $counter"
}
}
//任务操作,动态添加依赖, 执行:gradle -q task0 以查询结果
task0.dependsOn task1,task2
//还有一个爆炸式的动态依赖添加! 现在再运行下hello任务吧 嘿嘿
hello.dependsOn {
tasks.findAll{ task->task.name.startsWith('b')}
}
//除了dependsOn还有一些其他的操作,比如:
hello.mustRunAfter task0
task0.shouldRunAfter hello
//如何添加任务行为?观察下列任务输出顺序
//doFisrt和doLast可以多次调用 调用的时机和名称一致,<<方式是doLast的简写形式
task operationTask << {
println 'operation'
}
operationTask.doFirst {
println 'operation first'
}
operationTask.doLast {
println 'operation last'
}
operationTask << {
println 'just'
}
//所以,任务的标准形式应该是这样的!兄die, 你可以写无数个doFirst和doLast在里面!哈不哈皮?^_^
//(抱歉!变量在doFirst和doLast是不共享的喔!以下任务会报错)
task normalTask {
doFirst {
String subStr = 'Hello Task'
println subStr
}
doFirst {
println 'first others'
}
doLast {
println " last."
}
}
//那么如何定义一个可以共享的变量呢?这样!
task paramTask {
ext.paramString = "look here!"
doFirst {
println paramString
}
doLast {
println paramString
}
}
//ok,还可以任务之间共享喔!cool!
task paramtask1 << {
println paramTask.paramString
}
//*******************************************************************************
//来!看一个ant调用的示例
//这里先在当前目录下新建一个为文件夹test,在文件夹中放两个文本文件task_file_1.txt、task_file_2.txt
//第一:有一个方法定义->fileList,返回一个文件数组,这个方法做了两件事,过滤文件夹中的文件并排序
//第二:任务checksum和任务loadfile分别调用了ant的checksum和loadfile
task checksum << {
fileList('./test').each {File file ->
ant.checksum(file: file, property: "cs_$file.name")
println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"
}
}
task loadfile << {
fileList('./test').each {File file ->
ant.loadfile(srcFile: file, property: file.name)
println "I'm fond of $file.name"
}
}
File[] fileList(String dir) {
file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}
//*******************************************************************************
//定义默认任务 直接执行gradle吧 不需要写任务名称喽
//经测试得知,当我们不指定需要执行的任务时会执行文件中定义的默认任务;
//当指定需要执行的任务时会执行指定的任务而不执行默认的任务
//另:防止你不知道, 当需要执行多个任务的时候请这么写:gradle -q task1 task2 ...
defaultTasks 'clean', 'build'
task clean << {
println 'clean project!'
}
task build << {
println 'build project!'
}
//Configure by DAG(什么是DGA? what fuck?先不要管他是什么,执行下下面的任务再说!)
//分别执行distribution和release可知version会设置成不同的值,所以起到了一个标量的效果
//另:和大多数脚本语言一样,带有变量的字符串需要用双引号括起来!
task distribution << {
println "We build the zip with version=$version"
}
task release(dependsOn:'distribution') << {
println 'We release now'
}
gradle.taskGraph.whenReady {taskGraph->
if (taskGraph.hasTask(release)) {
version = '1.0'
} else {
version = '1.0-SNAPSHOT'
}
}
//突然想到的一个尝试 ^O^
task myLambda << {
println functionForMyLambda("return")
}
String functionForMyLambda(str) {
return "call " + str
}
//使用project中的一些属性:name、path、description、projectDir、buildDir等
task printNameA << {
println project.name
}
//写了这么多任务,其实任务的定义还有很多种形式,看看下面几个吧!
//task(buobao){
// println "buobao"
//}
task(buobao1) << {
println "buobao1"
}
task('buobao2') << {
println "buobao2"
}
//尝试下这个写法 :-D
task 'buobao3' << {
println "buobao3"
}
//给个结论吧 以上任务的定义完全和没有小括号是一样的效果,可以去掉小括号哟!
//但是,小括号这么无用为什么要有小括号这种写发呢?看下面↓↓↓↓
//下面这个任务名称是copy,实现的将一个文件复制到指定的文件夹下
//这里我们可以看到小括号的作用是指定了任务来的类型type
//type指定新建的task会从哪个类派生,gradle本身提供了一些通用的task包括:Copy Delete Sync等
task(copy, type: Copy) {
from(file('./test/task_file_2.txt'))
into(buildDir)
}
task copyFun(type: Copy) {
from(file('./test/task_file_1.txt'))
into(buildDir)
}
//思考一个问题,下面的这个任务是不会执行复制操作的,为什么呢??
//是因为继承的关系吗?
//记住一个事情,继承的任务或者说是定了type的任务就不要再加<<了
task copyFun1(type: Copy) << {
from(file('./test/task_file_1.txt'))
into(buildDir)
}
//我们在写个删除的任务试试看
task deleteBuildDir(type:Delete) {
delete buildDir
}
//我们看看buildDir到底是哪个目录吧
task printBuildDir << {
println buildDir
}
//之前所有的任务定义,不管是带括号还是不带括号的,都是基于一个关键字task来定义的
//那么 还有一个更容易被面向对象开发这接受的定义方式,如下:
//tasks.create(name:'createCopy', type:Copy) {
// from(file('./test/task_file_2.txt'))
// into(buildDir)
//}
tasks.create(name:'createTest') << {
println 'createTest'
}
//我们知道任务中定义的ext变量是可以共享的,比如paramTask中的paramString
//除了定义的变量 我们还可以获取任务的默认属性值,比如名称:name
//访问任务名称有好几种方式呢!花里胡哨的~
task echoName << {
println paramTask.paramString
println hello.name
println project.hello.name
println tasks.hello.name
println tasks['hello'].name
}
//来,再尝试下type访问吧!
//矮油,没有type这个property??确实没有啊!
//task除了name这个property还有其他property吗?
task echoType << {
println hello.type
println copy.type
}
//任务的调用
//这里调用javaproject中的printName任务
//这里只需要在当前项目的更目录下创建一个javaproject项目,
//并创建一个settings.gradle文件,文件中写入 include ':javaproject'
//在javaproject项目中创建build.gradle文件,写入task printNameB即可在此调用
task callTaskFromOtherProject(dependsOn:':javaproject:printNameB') << {
println 'callback'
}
//下面看一个比较重要的东西,闭包
//什么是闭包呢?android gradle配置文件中最常见的配置就是闭包
//比如:android{.....} dependencies{.....} 等等,熟悉不?\(^o^)/~
//我们改造下上面copy task的例子,如下:
task stdCopy(type:Copy)
stdCopy {
description 'Copies the resource directory to the target directory.'
from './test'
into buildDir
//include('**/*.txt', '**/*.class')
include '**/*.java'
}
//到这个例子才感觉这些教程有点用了 /(ㄒoㄒ)/~~
//看懂了么? 我们的android dependencies都是任务啊!再看下这个:
Copy stdCopy1 = task(stdCopy1, type: Copy)
stdCopy1.from './test'
stdCopy1.into buildDir
stdCopy1.include('**/*.txt', '**/*.class')
//任务也是可以被重写的。
task stdCopy(overwrite: true) << {
println('I am the new one.')
}
//ok.我们尝试下重写一个从未定义的task,也是可以跑通的喔!
task HaHa(overwrite: true) << {
println 'Ha Ha'
}
//有一个很常见的需求,我们可能在某些情况下要设置某一个或多个任务不执行,怎么办?
//通过断言跳过一个任务的执行
//分别执行两个命令以查看结果有何不同:gradle -q hello -PskipHello、gradle -q hello
hello.onlyIf { !project.hasProperty('skipHello') }
//跳过一个任务也可以通过StopExecutionException实现,如:
//我们看看下面的compile会不会执行?
task toCompile << {
println 'We are doing the compile.'
}
toCompile.doFirst {
if (true) { throw new StopExecutionException() }
}
task stopCompile(dependsOn: 'toCompile') << {
println 'I am not affected'
}
//除了以上两种方式可以跳过一个任务的执行,我们还可以设置任务禁用来避免一个任务的执行
stopCompile.enabled = false
//我们来自由发挥下!
task freeTask
freeTask.doLast() {
println 'freeTask'
}
task freeTask1 << {
tasks.freeTask.execute()
}