构建基础
projects 和tasks 是Gradle 中最重要的两个概念
projects
任何一个Gradle 构建都是由一个或多个project 组成
每个project 包括许多可构建组成部分,这完全取决于要构建些什么
示例:
每个project 可能是一个jar 包或者一个web 应用
也可以是一个由许多其他项目中产生的jar 构成的zip 压缩包
一个project 不仅仅只能进行构建操作,也可以部署应用或搭建环境
通过Gradle 的build-by-convention 来具体定义一个project 的操作
tasks
每个project 都由多个task 组成
每个task 都代表了构建执行过程中的一个原子性操作:
编译
打包
生成javadoc
发布到某个仓库等操作
构建
可以通过在命令行运行gradle 命令来执行构建
gradle 命令会从当前目录下寻找build.gradle 文件来执行构建
build.gradle 文件为构建脚本
这是一个构建配置脚本
这个构建脚本定义了一个project 和一些默认的task
脚本
task me {
doLast {
println 'chova'
}
}
gradle - q me
-q : 该参数用来控制gradle的日志级别,可以保证只输出需要的日志内容
该脚本定义了一个task, 并且添加了一个动作
当执行gradle me 时 ,Gralde 便会去调用me 这个任务来执行给定操作,这些操作就是一个用groovy 书写的闭包
Gradle 的tasks 类似于Ant 中的targets, 但是功能更加强大
任务
task upper << {
String someString = 'mY_nAmE'
println "Original: " + someString
println "Upper case: " + someString. toUpperCase ( )
}
gradle - q upper
Original: mY_nAmE
Upper case : MY_NAME
task count << {
4 . times { print "$it " }
}
gradle - q count
0 1 2 3
任务依赖
在两个任务之间指明依赖关系: 添加依赖task 也可以不必首先声明被依赖的task
task me << {
println 'me'
}
task intro ( dependsOn: me) << {
println "chova"
}
gradle - q intro
me
chova
延迟依赖
task taskX ( dependsOn: 'taskY' ) << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
gradle -q taskX
taskY
taskX
这里的taskX 是在taskY 之前定义的,这在多项目构建中非常有用
注意: 当引用的任务尚未定义的时候不可使用短标记法来运行任务
动态任务
Groovy 不仅可以定义简单任务,还可以动态定义任务
创建动态任务:
4 . times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
gradle - q task1
I'm task number 1
任务控制
增加依赖
4 . times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
task0. dependsOn task2, task3
gradle - q task0
I'm task number 2
I'm task number 3
I'm task number 0
增加任务行为
task hello << {
println 'Hello Earth'
}
hello. doFirst {
println 'Hello Venus'
}
hello. doLast {
println 'Hello Mars'
}
hello << {
println 'Hello Jupiter'
}
gradle - q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
doFirst 和doLast 可以进行多次调用,分别被添加在任务的开头和结尾
当任务开始执行时这些动作会按照既定顺序进行
<< 操作符是doLast 的简写形式
短标记法
以属性的方式访问任务
task hello << {
println 'Hello world!'
}
hello. doLast {
println "Greetings from the $hello.name task."
}
gradle - q hello
Hello world!
Greetings from the hello task.
增加自定义属性
可以为一个任务添加额外的属性
比如新增一个叫做myProperty的属性,用ext.myProperty的方式给赋初始值
这样就增加了一个自定义属性
为任务增加自定义属性
task myTask {
ext. myProperty = "myValue"
}
task printTaskProperties << {
println myTask. myProperty
}
gradle - q printTaskProperties
myValue
自定义属性不仅仅可以用在任务上,还可以用于其余操作
调用Ant任务
Ant 任务是Gradle 中的一等公民
Gradle 借助Groovy 对Ant 任务进行了整合
Gradle 自带了一个AntBuilder, 在Gradle 中调用Ant 任务比在build.xml 中调用更加的方便和强大
在Gradle 可以调用Ant 任务并且与Ant 中的属性进行通信
利用AntBuilder执行ant.loadfile
task loadfile << {
def files = file ( '../antLoadfileResources' ) . listFiles ( ) . sort ( )
files. each { File file ->
if ( file. isFile ( ) ) {
ant. loadfile ( srcFile: file, property: file. name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
gradle - q loadfile
** * agile. manifesto. txt ** *
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
** * gradle. manifesto. txt ** *
Make the impossible possible, make the possible easy and make the easy elegant.
( inspired by Moshe Feldenkrais)
方法抽取
Gradle 的强大体现在如何编写脚本逻辑
首先要做的就是要抽取方法
利用方法组织脚本逻辑
task checksum << {
fileList ( '../antLoadfileResources' ) . each { File file ->
ant. checksum ( file: file, property: "cs_$file.name" )
println "$file.name Checksum: ${ant.properties[" cs_$ file. name"]}"
}
}
task loadfile << {
fileList ( '../antLoadfileResources' ) . 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 ( )
}
定义默认任务
defaultTasks 'clean' , 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
gradle - q
Default Cleaning!
Default Running!
这与直接调用gradle clean run效果是一样的
在多项目构建中,每个子项目都可以指定单独的默认任务
如果子项目未进行指定将会调用父项目指定的的默认任务
DAG配置
配置阶段后 ,Gradle 会获取所有要执行的任务
Gradle 提供了一个钩子来捕获这些信息
可以为一些变量赋予不同的值
可以用于检查已经执行的任务中有没有被释放
依赖任务的不同输出
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'
}
}
gradle - q distribution
We build the zip with version= 1.0 - SNAPSHOT
gradle - q release
We build the zip with version= 1.0
We release now
whenReady 会在已发布的任务之前影响到已发布任务的执行,即使已发布的任务不是主要任务,即这个任务不是通过命令行直接调用