转载请注明出处:http://blog.csdn.net/lastsweetop/article/details/78962619
项目和任务
Gradle的所有都是基于两个基础概念:项目和任务
每个Gradle构建是由一个或者多个项目构成的,项目表示什么取决于你用Gradle做什么。比如,项目可以表示jar库或者web程序。它也可以表示由其他项目生产的jar包后打包成的发布zip包。一个项目不一定非要表示构建什么。它也可以表示做什么,比如把你的app发布到脚手架或者生产环境。讲到这里,你可能有点迷糊,但是不要担心,Gradle对按惯例构建的支持给出了项目是什么更明确的定义。
每个项目是由一个和多个任务构成的。任务表示构建运行的工作原件。它可以是编译classes,创建jar,生成javadoc,也可以是发布archives到仓库中。
我们本章内容都是同一个项目下的一些简单的任务操作,多项目交互的要到后面的章节体现。
Hello World
运行gradle
命令时,Gralde回去查找当前目录下的build.gradle
文件,这个文件就可以叫做构建脚本,虽然看起来更像是构建配置脚本。构建脚本中定义了一个项目和项目的一些任务。
build.gradle
的内容如下:
task hello {
doLast {
println 'Hello World'
}
}
然后在当前目录执行gradle -q hello
命令,结果如下:
± % gradle -q hello
Hello World
让我们来看看发生了什么,首先构建脚本定义了一个叫hello的任务,并且添加了一个action。当你运行gradle -q hello
的时候,Gradle就会执行hello任务,然后执行你提供的action。这个action只是一个包含了简单的groovy代码的closure。
构建脚本即code
构建脚本其实就是groovy代码,通过强力的脚本语言groovy让构建脚本更加强力,例如:
task upper {
doLast {
def str = 'sWeeTop'
println 'Original:' + str
println 'Upper Case:'+str.toUpperCase()
}
}
然后执行upper任务:
± % gradle -q upper
Original:sWeeTop
Upper Case:SWEETOP
再来一个:
task count {
doLast {
4.times { println it}
}
}
然后执行count任务:
± % gradle -q count
0
1
2
3
任务依赖
我们在命令行那张也涉及了一点任务依赖的例子,我们现在再来讲解一下,例子如下:
task hello {
doLast {
println 'Hello World'
}
}
task intro(dependsOn:hello) {
doLast {
println "I'm Gradle"
}
}
然后执行intro任务:
± % gradle intro -q
Hello World
I'm Gradle
所依赖的任务还可以是预先未定义的,例子如下:
task taskX(dependsOn: 'taskY') {
doLast {
println 'taskX'
}
}
task taskY() {
doLast {
println 'taskY'
}
}
然后执行taskX任务:
± % gradle taskX -q
taskY
taskX
依赖于taskY的任务taskX却比taskY先定义,这个特性对多任务构建来说很重要。
还有一点要注意就是,采取惰性依赖你就无法使用所依赖任务的快捷符号了
动态任务
强力的Groovy各种66666,比如你可以定义动态的任务:
4.times { number ->
task "task$number" {
doLast {
println "I'm task number $number"
}
}
}
然后执行task2任务:
± % gradle task2 -q
I'm task number 2
操作已存在的任务
一旦任务被创建之后,你就可以通过api直接访问了,比如你可以动态的给一个任务增加点依赖,ant可以做不到这点,示例:
4.times { number ->
task "task$number" {
doLast {
println "I'm task number $number"
}
}
}
task0.dependsOn task2,task3
然后我们只想task0任务:
± % gradle task0 -q
I'm task number 2
I'm task number 3
I'm task number 0
或者为已经存在的任务增加点行为:
task hello {
doLast {
println 'Hello World'
}
}
hello.doFirst {
println 'Hello Dong'
}
hello.doLast {
println 'Hello Nan'
}
hello {
doLast {
println 'Hello Bei'
}
}
然后执行hello任务:
± % gradle hello -q
Hello Dong
Hello World
Hello Nan
Hello Bei
doFirst
和doLast
能被多次执行,他们可以在任务的开始和结尾增加action,任务执行的时候,action列表就会依次执行。
快捷符号
有个非常方便的符号可以访问已存在的任务,在构建脚本中的每个任务都有这些属性:
task hello {
doLast {
println 'Hello World'
}
}
hello.doLast {
println "Greeting from the $hello.name task"
}
然后执行hello任务:
± % gradle hello -q
Hello World
Greeting from the hello task
这样可以写出更加易读性的代码,特别是用那些插件提供的任务,比如compile
任务
扩展任务属性
你可以为任务增加自己的属性,要增加myProperty
属性你给ext.myProperty
设置一个初始值,然后这个属性就和其他预先定义的属性一样被读取和设置。示例:
task myTask {
ext.myProperty='init value'
}
task printTaskProperty {
doLast {
println myTask.myProperty
}
}
然后执行printTaskProperty任务
± % gradle printTaskProperty -q
init value
使用ant任务
ant任务是gradle的一等公民,gradle把通过把ant任务完全交托给groovy实现了卓越的集成。在groovy这里是由奇妙的AntBuilder
提供相关功能。在Gradle里使用ant任务就像直接在build.xml
里的任务一样简单而又强力。下面的例子演示了如何执行ant任务和访问ant属性:
task loadFile {
doLast {
def files = file('../unpublished').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file,property:file.name)
println " ***$file.name*** "
println ant.properties[file.name]
}
}
}
}
然后执行loadFile任务:
± % gradle loadFile -q
***build.gradle***
apply plugin: 'java'
archivesBaseName='hello'
***settings.gradle***
version = 1.0
使用方法
gralde在组织构建逻辑时可以进行分级扩展,组织构架逻辑的第一级就是提取方法:
task loadFile {
doLast {
fileListEachAction('../unpublished') { File file ->
ant.loadfile(srcFile: file, property: file.name)
println " ***$file.name*** "
println ant.properties[file.name]
}
}
}
task checkSum {
doLast {
fileListEachAction('../unpublished') { File file ->
ant.checksum(file: file, property: "cs_$file.name")
println "$file.name checksum is ${ant.properties["cs_$file.name"]}"
}
}
}
def fileListEachAction(String path, Closure closure) {
def files = file(path).listFiles().sort()
files.each { File file ->
if (file.isFile()) {
closure(file)
}
}
}
然后执行checkSum任务:
± % gradle checkSum -q
build.gradle checksum is 193e5061bf3681c0434d6f4d937f1fc3
settings.gradle checksum is 0cba3f2c2582e03de4dc86f1d495a39b
后面还会讲到,这样的方法在多项目构建中也可以跨项目调用。
默认任务
Gradle可以定义一个或者多个默认任务,当没有特别指定具体任务时,默认任务就会执行
defaultTasks 'clean','run'
task clean {
doLast {
println "task $it is running"
}
}
task run {
doLast {
println "task $it is runing"
}
}
执行默认任务:
± % gradle -q
task task ':clean' is running
task task ':run' is runing
相当于运行了gralde -q clean run
,在多项目构建中,每个子项目都可以设置自己的默认任务,当没有子项目的默认任务被指定那么就会执行root项目的默认任务
通过DAG配置Gradle
Gradle有配置阶段和运行阶段,在配置阶段之后,Gradle就会知道所以需要执行的任务,Gradle提供了hook可以让你使用这些信息,有一个用例就是你需要确认release任务是否在执行的任务之中,在这个基础上你可以设置不同的变量。
下面的例子会演示contribution任务和release任务下会有不同的version值:
task distribution {
doLast {
println "Current Version is $version"
}
}
task release(dependsOn: distribution) {
doLast {
println 'We release now'
}
}
gradle.taskGraph.whenReady { taskGraph ->
if (taskGraph.hasTask(release)) {
version = '1.0.0'
} else {
version = '1.0.0-SNAPSHOT'
}
}
执行distribution任务:
± % gradle distribution -q
Current Version is 1.0.0-SNAPSHOT
执行release任务:
± % gradle release -q
Current Version is 1.0.0
We release now
最重要的是whenReady会影响release任务是在release任务执行之前,即使release任务不是该次构建的主要任务。