1、项目(project)和任务(task)
Gradle中的任何事都基于两个基本概念:项目(project)和任务(task)
每一个构建(build)都是由一个或多个项目组成的。一个项目代表什么取决于你使用Gradle做什么。例如,一个项目也许代表一个库或者一个web应用程序,它也许代表一个由其他项目产生的JAR文件组成的ZIP。一个工程不一定代表一件要去构建的事,它也许代表一件要去做的事情,例如将你的应用程序部署到工作台或者生产环境。现在看来,这些概念似乎有一点模糊,不过别担心,Gradle的基于约定的构建会对一个项目是什么有更具体的定义。
每一个项目由一个或多个任务(task)组成,一个任务代表一些执行构建工作的最小工作单元。它也许编译一些类,创建一个JAR,生成Javadoc文档,或者向库发布一些文档。

一个build包含多个project,一个project包含多个task
现在,我们将在一个项目中定义一些简单的任务,后面的章节将会使用多个项目,并且还有更多关于使用项目和任务的知识。
2、Hello World
你可以使用gradle命令运行Gradle的构建。gradle命令在当前目录下查找一个名为build.gradle的文件,我们称build.gradle文件是一个“构建脚本”,严格的说它是一个构建配置脚本。构建脚本定义了一个项目及其任务。
试一试:创建如下构建脚本,并命名为“build.gradle”
task hello{
doLast{
println 'Hello World!'
}
}
在控制台中移动到此文件所在目录,并输入“gradle -q hello”执行该文件,可看到控制台中输出Hello World。
(关于 -q :用户手册中的大多数例子都使用了 -q 命令行选项,它会抑制Gradle的日志信息,所以会只显示task的输出。这会使手册中例子的输出更简洁,你完全可以不使用它。)
对build.gradle的说明:构建脚本定义了一个名为“hello”的task,并为其添加了一个操作。当你运行“gradle hello”的时候,Gradle执行这个名为“hello”的task时,会去执行你提供的操作。这个操作是一个闭包,包含了Groovy代码去执行。
3、使用更简单/快捷的定义方式定义task
task hello << {
println 'Hello World!'
}
如上,这使用了 [一个简单的闭包(翻译不恰当)] 定义了一个名为“hello”的task,我们将在用户手册中使用这种风格定义task
4、构建脚本代码
Gradle的构建脚本给你Groovy的全部权利。
例1:在名为“build.gradle”的文件中输入如下代码:
task upper <<{
String str = 'aBcD'
println "original:" + str
println "Upper case:" + str.toUpperCase()
}
运行结果如下:
例2:在名为“build.gradle”的文件中输入如下代码:
task count << {
.times { print "$it " }
println ''
}
结果如下:
5、task依赖
也许你已经猜到了,你可以声明依赖于其他tasks的task
例:在名为“build.gradle”的文件中输入如下代码:
task hello << {
println "hello"
}
task world(dependsOn: hello) <<{
println "world"
}
结果如下:
可见,若先执行名为hello的task,则会只执行该task;若先执行名为world的task,则会先执行该task所依赖的其他task(hello),然后再执行自身那个task。即,被依赖的task会先执行。
懒依赖:被依赖的task不存在(被依赖的task后定义)
task world(dependsOn: "hello") <<{
println "world"
}
task hello << {
println "hello"
}
注意:task world依赖的task的名字要加上引号
结果如下:
Task world对task hello的依赖关系声明在task hello定义之前,这对于多项目构建非常重要。
请注意,当引用一个未被定义的task时,你不能使用 shortcut notation (即点运算符 . )
6、动态task
Groovy能不仅能用于指定一个task能做什么,你也能用它去动态创建task。
.times{ counter ->
task "task$counter" <<{
println "No. $counter task"
}
}
结果如下:
7、操作现有的task
一旦task被创建,他们就能通过API被访问到。
例如,你可以在运行时动态地为task添加依赖关系。
.times{ counter ->
task "task$counter" <<{
println "No. $counter task"
}
}
task1.dependsOn task2, task3
为task1添加对task2,task3的依赖。
结果如下:
为现有的task添加行为:
task hello <<{
println "hello"
}
hello.doFirst{
println "doFirst"
}
hello.doLast{
println "doLast"
}
hello << {
println '88888'
}
结果如下:
可见,执行的顺序为:doFirst - task本身 - doLast - <<(doLast)
doFirst和doLast可以被多次调用,doFirst在task的操作列表开头,doLast在task的操作列表结尾,当task执行时,操作列表中的操作会按顺序执行。
“<<”操作符只不过是doLast的别名。
8、快捷访问符(. )
也许你已经注意到,可以使用快捷访问符访问现存的task,构建脚本中的每一个task的属性都可以使用快捷访问符访问。
task hello <<{
println "hello world"
}
hello.doLast{
println "my name is $hello.name !"
}
结果如下:
这使得代码很易读,特别是当使用插件提供的task时,例如编译task(compile task)
9、额外的task属性
你可以为task添加你自己的属性。
添加一个名为“myProperty”的属性,并为其赋初值。从这时起,这个属性就能像一个预定义的task属性一样读、写(设置)
task myTask {
ext.myProperty = "Xiaming_Chen"
}
task printMyProperty <<{
println myTask.myProperty
myTask.myProperty = "Chen_Xiaming"
println myTask.myProperty
}
结果如下:
可见,额外的task属性不局限于task,myProperty属性可以被其他的task读,也能在其他task中为其赋值。
10、使用Ant tasks
11、使用方法
在Gradle中,你可以怎样组织你的构建逻辑是有等级限制的。上面的示例“提取一个方法”只是第一级。
12、默认task
如果你没有指定其他的task,Gradle允许你定义一个或多个默认task执行。
defaultTasks "default1","default2"
task default1<<{
println "No.1 default task"
}
task default2<<{
println "No.2 default task"
}
task myTask<<{
println "my task"
}
结果如下:
指定默认task为default1和default2,当执行时若不指定要执行的task,则会执行所有默认的task。
这与运行“gradle default1 default2”等效。
在一个多项目构建中,每个子项目能拥有他们自己特定的默认task,如果一个子项目没有指定默认task,则父项目的默认task会被使用(如果定义了的话)。
13、用DAG配置Gradle有配置阶段和执行阶段,在配置阶段之后,Gradle知道所有需要被执行的task,Gradle为你提供了可以利用这些信息的工具。一个用例将会检查发布的task是否在要被执行的所有task中,由此,你可以为不同的变量分配不同的值。
在下面的例子中,task的执行结果会因变量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"
}
}
执行gradle -q distribution:
执行gradle -q release:
“whenReady”会在release task执行之前影响release,即使release task不是首要的task这也会起作用。