http://www.jcodecraeer.com/a/anzhuokaifa/Android_Studio/2015/0128/2372.html
http://www.jcodecraeer.com/a/anzhuokaifa/Android_Studio/2015/0128/2372.html
http://www.jcodecraeer.com/a/anzhuokaifa/Android_Studio/2015/0128/2372.html
Gradle之构建脚本入门
编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过!
6.1. Projects and tasks工程和任务
Gradle中的任何东西都基于俩概念: projects 工程 和 tasks 任务。
一个Gradle构建由一个或多个工程构成。一个工程 就 是项目里的几个组件,这确切的依赖于要构建的项目。比如,一个工程可以是一个jar库文件,也可以是一个web应用。它可以是从其他项目jar中汇聚成的 一个zip包。它不一定是标识要做的事,也可能是已经完成的事,比如部署项目。啊好凌乱啊有木有?没关系,Gradle的基于约定配置对工程有明确的定 义,可以去看看。
每个工程由众多任务构成(有没有想到ant?),一个任务是构建过程的一些原子片段。可以是编译,打包,生成文档,甚至发布到库。
好了好了,别睡着了,坐起来看我们要开工了。先是一个简单的工程,后续有负责的任务和工程引导。
6.2. Hello world牛刀初试
使用 gradle 命令行进行构建,它会寻找当前目录的 build.gradle
文件(是不是和其他构建工具一样啊),该文件称为构建脚本文件,当然严格的说它是构建配置脚本文件。构建脚本定义了工程和它的任务。
自己不来一发嘛,创建 build.gradle 文件并写入下面的脚本:
Example 6.1. The first build script
build.gradle
1
2
3
4
5
6
|
task hello {
doLast {
println
'Hello world!'
}
}
|
在当前目录下执行gradle -q hello
来运行
:
What does -q
do?
我们的例子会经常用到-q参数。它会抑制Gradle的日志输出而只有任务输出。这样看起来清爽一些。如果不需要完全可以不用。在18章讲日志中会详细说明各参数对输出的影响。
Example 6.2. Execution of a build script
1
2
|
> gradle -q hello
Hello world!
|
喔喔喔,发生什么了呢?构建脚本定义了一个认为叫hello并给它赋了一个动作。当执行gradle hello
时
, Gradle 会执行hello任务,也就是执行它里面的动作。动作是一些正确可执行的Groovy代码放在大括号里。
是 不是和Ant很像呢,呵呵。Gradle的任务就相当于Ant里的目标,不过更强悍一些。官方反复斟酌认为任务这个属于比目标更适合用于Gradle。不 过这和Ant里的任务冲突了(ant把它的命令叫任务,比如javac,copy),所以我们现在说任务,你要记得它总是指的Gradle的任务,也就是 Ant里的目标。需要的话,我们就明确说Ant的任务如何如何。
6.3. A shortcut task definition任务定义新方法--快捷定义
有一种更简明的方法定义任务:
Example 6.3. A task definition shortcut
build.gradle
1
2
3
|
task hello << {
println
'Hello world!'
}
|
我们用一个大括号定义了Hello任务,以后我们就都这样了哈。
6.4. Build scripts are code 何处不coding?
构建脚本的强大得益于Groovy的强大,我们来看下:
Example 6.4. Using Groovy in Gradle's tasks
build.gradle
1
2
3
4
5
|
task upper << {
String someString =
'mY_nAmE'
println
"Original: "
+ someString
println
"Upper case: "
+ someString.toUpperCase()
}
|
Output of gradle -q upper
1
2
3
|
> gradle -q upper
Original: mY_nAmE
Upper
case
: MY_NAME
|
下一个
Example 6.5. Using Groovy in Gradle's tasks
build.gradle
1
2
3
|
task count << {
4.times { print
"$it "
}
}
|
Output of gradle -q count
1
2
|
> gradle -q count
0 1 2 3
|
6.5. Task dependencies任务依赖
你肯定早想到了任务之间可以依赖吧(没办法,谁让你是工程师而我是心理学家呢)
Example 6.6. Declaration of dependencies between tasks
build.gradle
1
2
3
4
5
6
|
task hello << {
println
'Hello world!'
}
task intro(dependsOn: hello) << {
println
"I'm Gradle"
}
|
Output of gradle -q intro
1
2
3
|
> gradle -q intro
Hello world!
I'm Gradle
|
任务依赖的其他任务可以不预先定义
Example 6.7. Lazy dependsOn - the other task does not exist (yet)
build.gradle
1
2
3
4
5
6
|
task taskX(dependsOn:
'taskY'
) << {
println
'taskX'
}
task taskY << {
println
'taskY'
}
|
Output of gradle -q taskX
1
2
3
|
> gradle -q taskX
taskY
taskX
|
看见了吧我没瞎说,taskX依赖于taskY而taskY定义在后面,这样做对于多工程构建很重要。任务依赖的希艾娜关系讨论在Section 15.4, “Adding dependencies to a task”.
呔注意了,不能用快捷记号引用任务的喔。
6.6. Dynamic tasks动态任务
Groovy的强大可不是只能来定义任务干什么,你还可以用它动态创建任务:
Example 6.8. Dynamic creation of a task
build.gradle
1
2
3
4
5
|
4.times { counter ->
task
"task$counter"
<< {
println
"I'm task number $counter"
}
}
|
Output of gradle -q task1
1
2
|
> gradle -q task1
I'm task number 1
|
6.7. Manipulating existing tasks操纵任务
和Ant不同的是Gradle的任务创建后可以通过API来访问,比如增加依赖。
Example 6.9. Accessing a task via API - adding a dependency
build.gradle
1
2
3
4
5
6
|
4.times { counter ->
task
"task$counter"
<< {
println
"I'm task number $counter"
}
}
task0.dependsOn task2, task3
|
Output of gradle -q task0
1
2
3
4
|
> gradle -q task0
I
'm task number 2
I'
m task number 3
I'm task number 0
|
或者你可以增加任务的行为
Example 6.10. Accessing a task via API - adding behaviour
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
|
task hello << {
println
'Hello Earth'
}
hello.doFirst {
println
'Hello Venus'
}
hello.doLast {
println
'Hello Mars'
}
hello << {
println
'Hello Jupiter'
}
|
Output of gradle -q hello
1
2
3
4
5
|
> gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
|
你可以多次调用 doFirst
和doLast
,它们分别在任务动作列表的开头和结尾增加行为。执行的时候会依序执行,而<<操作符就是
doLast的别名
.
6.8. Shortcut notations快捷符号
你早就注意到了吧,没错,一个任务就是一个脚本的属性,你可以访问它:
Example 6.11. Accessing task as a property of the build script
build.gradle
1
2
3
4
5
6
|
task hello << {
println
'Hello world!'
}
hello.doLast {
println
"Greetings from the $hello.name task."
}
|
Output of gradle -q hello
1
2
3
|
> gradle -q hello
Hello world!
Greetings from the hello task.
|
对于插件提供的盒子任务。(e.g. compile
)这尤其方便
6.9. Extra task properties新增属性
可以通过ext增加任务属性值:要增加名为myProperty的熟悉用
ext.myProperty
即可。增加后就好像早就定义在里面了一样。
Example 6.12. Adding extra properties to a task
build.gradle
1
2
3
4
5
6
7
|
task myTask {
ext.myProperty =
"myValue"
}
task printTaskProperties << {
println myTask.myProperty
}
|
Output of gradle -q printTaskProperties
1
2
|
> gradle -q printTaskProperties
myValue
|
像这样混入属性不仅仅局限于任务,有兴趣看下Section 13.4.2, “Extra properties”.
6.10. Using Ant Tasks使用Ant任务
Ant任务是Gradle界的一等公民,Gradle通过Groovy对Ant任务进行了牛逼的整合,因为Groovy有一个牛逼的AntBuilder
. Gradle使用Ant任务绝不比Ant使用build.xml差劲甚至还更强大。
Example 6.13. Using AntBuilder to execute ant.loadfile target
build.gradle
1
2
3
4
5
6
7
8
9
10
|
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]}"
}
}
}
|
Output of gradle -q loadfile
1
2
3
4
5
6
7
8
9
|
> 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)
|
你想怎么干Ant就可以怎么干,只有你有种。更多请看Chapter 17, Using Ant from Gradle.
6.11. Using methods方法
Gradle很吊,但要看你怎么写你的脚本逻辑了。对于上面的例子,第一层次就是抽取为方法.
Example 6.14. Using methods to organize your build logic
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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()
}
|
Output of gradle -q loadfile
1
2
3
|
> gradle -q loadfile
I
'm fond of agile.manifesto.txt
I'
m fond of gradle.manifesto.txt
|
以后你就明白:娃是多么幸福,因为多工程构建可以共享方法。如果你还想要复杂,Gradle也提供了组织方法,就怕你不够复杂。我们搞了一整章吓唬你,去看看吧:Chapter 59, Organizing Build Logic.
6.12. Default tasks默认任务
默认任务是定义的,可以给你的构建定义一两个。
Example 6.15. Defining a default tasks
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
|
defaultTasks
'clean'
,
'run'
task clean << {
println
'Default Cleaning!'
}
task run << {
println
'Default Running!'
}
task other << {
println
"I'm not a default task!"
}
|
Output of gradle -q
1
2
3
|
> gradle -q
Default Cleaning!
Default Running!
|
这就和执行 gradle clean run
一样样的了。多工程构建中每个工程都可以有自己的默认任务。要是你不定义,就是用父任务定义的默认任务。
6.13. Configure by DAG
我们后面会详细讲(See Chapter 55, The Build Lifecycle) Gradle的配置阶段和执行阶段。配置阶段结束后Gradle了解了所有的要执行的任务(Gradle提供了一个钩子来使用这个信息)。你可以检查要执行的任务里有没有发布任务。这样就可以为不同的变量指不同的值了。
下面这个例子给分发任务和发布任务指了不同的版本号。
Example 6.16. Different outcomes of build depending on chosen tasks
build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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'
}
}
|
Output of gradle -q distribution
1
2
|
> gradle -q distribution
We build the zip
with
version=1.0-SNAPSHOT
|
Output of gradle -q release
1
2
3
|
> gradle -q release
We build the zip
with
version=1.0
We release now
|
一旦选定发布任务,在它执行前会影响版本号,即使它有依赖任务。
原文地址 http://www.gradle.org/docs/current/userguide/tutorial_using_tasks.html