在现有的基础上工作
Gradle资料
Maven和Gradle对比: http://www.importnew.com/18008.html
Gradle官网的与Maven对比: https://gradle.org/maven_vs_gradle/
下载: https://services.gradle.org/distributions/gradle-3.0-all.zip
Gradle官方用户指南文档: https://docs.gradle.org/current/userguide/userguide.html
Gradle2用户指南中文版: https://waylau.gitbooks.io/gradle-2-user-guide/content/
安装
Gradle3.0后,需要java7或更高版本
Gradle会装载自己的Groovy库,所以,不需要安装Groovy,就算安装了Groovy也会被忽略掉。
下载
下载完整包后,里面会包含 Gradle、用户指南、API文档、示例
https://gradle.org/gradle-download/
配置环境变量
GRADLE_HOME=D:\resource\Gradle\gradle-3.0
path=%GRADLE_HOME%/bin
(linux: path=$GRADLE_HOME/bin
)
GRADLE_OPTS=-Xms256m -Xmx512m
(指定用于启动JVM命令行参数,选择配置)
GRADLE_USER_HOME=D:\resource\Gradle\repo
(配置本地仓库的位置)
检查是否安装成功
执行命令 gradle -v
Gradle命令
- 执行多task(列出每个task):
gradle dist test
task compile << {
println 'compiling source'
}
task compileTest(dependsOn: compile) << {
println 'compiling unit tests'
}
task test(dependsOn: [compile, compileTest]) << {
println 'running unit tests'
}
task dist(dependsOn: [compile, test]) << {
println 'building the distribution'
}
-
排除task(
-x
):gradle dist -x test -x compile
-
当task执行失败时,继续执行不依赖这个task的其它task
gradle --continue dist
-
任务名称缩写(只需提供足够的可以唯一区分出该 task 的字符):
gradle di
-
选择需要执行的脚本:
C:\>gradle -q -b D:/empty/build.gradle hello
在多子项目时,应该使用-p
:gradle -q -p subdir hello
-
忽略新版本检查(ignoring any up-to-date checks):
gradle --rerun-tasks di
-
查看构建信息
gradle -q projects
: 列出当前项目及其子项目(一并输出description
)
gradle -q tasks
(gradle -q tasks --all
): 列出当前项目的所有task
gradle help --task task1 task2
: 显示匹配到的task的详细信息
gradle -q dependencies api:dependencies webapp:dependencies
: 列出指定项目的依赖
gradle -q api:dependencies --configuration testCompile
: 列出指定项目及指定阶段的依赖
gradle buildEnvironment
: ?
gradle -q webapp:dependencyInsight --dependency groovy --configuration compile
: ? (对追踪为何依赖出现的版本很有帮助)
gradle -q api:properties
: 列出当前项目的属性 -
生成构建耗时报告
--profile
-
干跑(不真正执行,用来查看执行了哪些task)
gradle -m someTask1 someTask2
Gradle命令列表
https://docs.gradle.org/current/userguide/gradle_command_line.html
包括几个环境变量的说明:GRADLE_OPTS
GRADLE_USER_HOME
JAVA_HOME
Gradle Wrapper
- Wrapper的使用
Gradle Wrapper
解决在未安装Gradle
的情况下也能构建项目,并且避免用户选择了不正确的Gradle
版本
每个Gradle Wrapper
都会指定Gradle
版本,当首次使用Wrapper
时,将下载指定的Gradle
版本,并使用它进行构建
Wrapper
下载的Gradle
保存到目录$USER_HOME/.gradle/wrapper/dists
中
- 为项目添加Wrapper
只需要项目根目录下执行gradle wrapper --gradle-version 版本号
也可以在构建脚本build.gradle
中添加task
task wrapper(type: Wrapper) {
gradleVersion = '2.0'
}
执行命令后,将生成以下几个文件
demo/
gradlew
gradlew.bat
gradle/
wrapper/
gradle-wrapper.jar
gradle-wrapper.properties
配置文件gradle-wrapper.properties
中的各项配置说明(一般不需要变更):
https://docs.gradle.org/current/dsl/org.gradle.api.tasks.wrapper.Wrapper.html
- 校验Wrapper下载的Gradle文件
执行命令shasum -a 256 gradle-3.0-all.zip
生成hash码
windows下可以使用Git Bash
来执行
将生成 的hash吗,配置到gradle-wrapper.properties
中
distributionSha256Sum=9c8b7564ea6a911b5b9fcadd60f3a6cea4238413c8b1e1dd14400a50954aab99
- unix权限
在Unix系统中,如果遇到文件权限问题,可以这样执行sh gradlew
Gradle Daemon
可以通过Gradle Daemon
来解决,Gradle
启动会比较慢的问题
Gradle
启动慢是因为,它运行中Java Virtual Machine (JVM)上,并还会依赖几个比较耗时的支持库
Gradle Daemon
,是一直存活的,避免了JVM的启动耗时,并且缓存项目结构、文件、tasks等信息
在Gradle 3.0
中,Gradle Daemon
是默认启动的,不需要作其它的变动
在低版本Gradle
中,可以使用--daemon
来启用Gradle Daemon
使用了Gradle Daemon
,将会提升15-75%的构建速度
可以通过--profile
来生成耗时报告
可以通过命令gradle --status
来查看 Gradle Daemon
的状态
如果安装了JDK,可以使用jps
命令来查看
注意:目前,只有相同版本的Gradle
与Gradle Daemon
才能一起工作
禁用Gradle Daemon
可以通过配置文件,也可以直接使用命令gradle --stop
目前,建议,在持续集成服务器中禁用Gradle Daemon
,提高可靠性
https://docs.gradle.org/current/userguide/gradle_daemon.html
Gradle Daemon
,若存活时间超过3个小时,将会被回收
依赖管理基础
- 声明依赖
// java插件
apply plugin: 'java'
// 设定使用Maven中心仓库
repositories {
mavenCentral()
}
dependencies {
// 声明依赖hibernate-core版本为3.6.7.Final,在编译及运行时依赖它
compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
// 声明从仓库中获取版本>=4.0的junit,在test时依赖它
testCompile group: 'junit', name: 'junit', version: '4.+'
}
- 依赖配置
java插件中定义了以下几个标准的依赖配置
compile
编译时的依赖
runtime
程序运行时的依赖,默认包含compile
testCompile
单元测试编译时的依赖,默认包含compile
testRuntime
单元测试程序运行时的依赖,默认包含compile
、runtime
和testCompile
- 依赖的声明方式
依赖由group、name与version组成,除了上面的声明方式,还可以写成下面这样
dependencies {
compile 'org.hibernate:hibernate-core:3.6.7.Final'
testCompile 'junit:junit:4.+'
}
- 仓库
默认情况下,Gradle
不会定义依赖仓库,如果构建时需要第三方依赖,必须定义依赖仓库
如下设置仓库为Maven中心仓库
repositories {
mavenCentral()
}
如下设置仓库为Maven远程仓库
repositories {
maven {
url "https://repo1.maven.org/maven2/"
}
}
- 发部项目
通过执行命令gradle uploadArchives
,Gradle将构建并上传生成的jar包
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "D:/resource/maven/repo/")
}
}
}
多项目构建
共同点
- 在根项目中都有一个
settings.gradle
的文件 - 在根项目中都有一个
build.gradle
的构建文件 - 子项目中都有它们自己的
*.gradle
的构建文件
可以通过命令gradle -q projects
查询项目列表
官方建议,每个项目都在settings.gradle
中配置根项目名,示例spring源码中的rootProject.name = "spring"
不需要每个子项目都要有构建文件,但根项目中必须要有
子项目中构建文件的文件名不一定是build.gradle
,只要以.gradle
为后缀即可
在根项目中执行命令gradle test
,将都在各子项目中执行这个gradle test
命令
指定子项目的方法类似于路径,但不是用/
或\\
,而是使用:
。
如 gradle :services:webservice:tasks
,首个:
表示根项目,其它的:
表示路径分隔
持续构建
至目前3.0版本,这个特性尚未非常完善
通常,当前执行完所有指定的task后,就算是一次构建完毕,当下一次调用gradle命令时,才会进行下一次的构建动作
但持续构建时,Gradle会保持构建的功能,只有接收到停止命令时,才会停止。
如,对于编译JAVA文件,每当java文件变更时,Gradle自动对这个文件进行再次编译。
在一些情景下,持续构建能够发挥很大作用。
- 启动:添加参数
--continuous
或-t
。示例,gradle build --continuous
- 停止:如果是启动是在终端命令中,可以通过CTRL+D之后再接ENTER来结束;否则,需要使用kill命令来结束进程;某些工具或许会提供这个功能
只有在当前持续构建中,命令所涉及到的文件(构建脚本不算),被更改时,才会触发再次构建
当前构建脚本变更时,只有手动重启持续构建后,新的构建方案才会生效
注意事项:
- 循环构建:在构建的过程中,构建脚本更改了被Gradle监视着的文件,就会形成循环构建
- java9的限制:在Mac OS X中,Gradle为每10秒检测一遍文件的变更,而不是2秒;在Windows在,大项目可能运行不了持续构建
- 性能与稳定性:在Mac OS X中,由于依赖于它低效率的系统轮询,所以对文件变更的感知会延迟;此外,在Mac OS X中,重负载情况下,可能会导致死锁;在linux中,如使用的是OpenJDK,有可能会错过文件变更的事件通知
- 删除目标目录,不会引起新的构建
复合构建
至目前3.0版本,这个特性也尚未非常完善
复合构建与多项目构建有许多类似的地方
gradle 图形界面
使用命令gradle --gui
就可以弹出图形界面
构建环境
通过gradle.properties
配置编译环境
通过本地环境变量的配置,如GRADLE_OPTS
或JAVA_OPTS
等,会作用于所有项目构建
如果某个项目需要特殊配置时,可以使用gradle.properties
的配置来覆盖环境变更的配置
在下面三个地方中,如果存在相同的配置,后一个覆盖前一个
- 项目构建目录中的
gradle.properties
- Gradle用户目录下的
gradle.properties
- 系统属性,如,命令行输入的
-Dsome.property
这个功能需要jdk7或以上版本
下面列出用于配置Gradle构建环境的配置
org.gradle.daemon
当设置为true
时,将使用Gradle daemon
去构建。本地是默认使用的,在CI持续构建时,建议为false
org.gradle.java.home
指定Gradle构建程序使用的Java路径org.gradle.jvmargs
指定daemon
程序的jvm参数,这个设置是非常有用的,因为默认分配的daemon
内存是比较大的org.gradle.configureondemand
按需配置,只配置关联项目,使用大型项目能够快速构建 Configuration on demandorg.gradle.parallel
当配置了这个设置后,Gradle将以parallel模式执行org.gradle.workers.max
配置并发执行的最大数org.gradle.debug
当设置为true
时,以远程(监听端口5005)debug模式运行,相当于在jvm命令行中添加-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
org.gradle.daemon.performance.enable-monitoring
当设置为false
时,Gradle将不监控daemons
运行时的内存使用情况
可以在gradle.properties
配置文件中,配置http/https的访问代理
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=userid
systemProp.http.proxyPassword=password
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost
gradle的嵌入式编程
Gradle提供Tooling API
,使用者可以自行调用。主要使用者是IDE、CI server等,但,API是开放的,任何人都可以在项目中使用
- Gradle TestKit
- Eclipse Buildship
- IntelliJ IDEA
API有如下特性
- 查询构建明细,包括项目结构与依赖
- 执行构建,并监听输出日志
- 执行指定的测试类或测试方法
- 接收构建过程的事件,如项目配置,执行的task或test
- 取消正在执行的构建
- 将多个单独构建,组合与复合构建
- 下载合适的Gradle版本
- 轻量级的实现,可以非常方便的嵌入到应用中
在samples/toolingApi
中有示例
编写Gradle构建脚本
构建脚本基础
1). Projects and tasks
Projects
与 tasks
是Gradle最顶部的两个基本概念
每个构建包含一个或多个Projects
,一个Project
由一个或多个tasks
组成
2). Hello world
当执行gradle
命令时,将会在当前目录中查找一个叫build.gradle
的构建脚本
第一个构建脚本:执行gradle -q hello
(-q
的作用是不输出gradle的日志)
task hello {
doLast {
println 'Hello world!'
}
}
Gradle的task,与Ant的target很类似,但比target强大
3). 更简捷的书写方式
task hello << {
println 'Hello world!'
}
4). 构建脚本,本身就是编程
通过强大的Groovy
进行编写Gradle
构建脚本
下面为在Task中使用Groovy的示例
task upper << {
String someString = 'mY_nAmE'
println "Original: " + someString
println "Upper case: " + someString.toUpperCase()
}
示例2
task count << {
4.times { print "$it " }
}
5). Task之间的依赖
示例1:
task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {
println "I'm Gradle"
}
在示例1中,执行gradle -q intro
,将输出如下:
D:\Learning\gradle\hello>gradle -q intro
Hello world!
I'm Gradle
示例2:延迟依赖,所依赖task,在当前task之后
task taskX(dependsOn: 'taskY') << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
示例2将输出:
D:\Learning\gradle\hello>gradle -q taskX
taskY
taskX
6). 动态tasks
利用功能强大的Groovy,可以动态的创建tasks
示例:
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
在示例中,执行task0
、task1
、task2
与task3
都是正常的
7). 调整已存在的tasks
当tasks被创建后,就可以通过一此API进行访问。通过这个特性,可以动态的实现task之间的依赖。Ant是不允许这么做的
示例1:
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
task0.dependsOn task2, task3
输出如下:
D:\Learning\gradle\hello>gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0
示例2:添加behaviour
task hello << {
println 'Hello Earth'
}
hello.doFirst {
println 'Hello Venus'
}
hello.doLast {
println 'Hello Mars'
}
hello << {
println 'Hello Jupiter'
}
输出如下:
D:\Learning\gradle\hello>gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
doFirst
与doLast
可以被调用多次,表示在一个action之前或之后执行。
他们是依赖执行,操作符<<
就类似于doLast
的别名
8). 快捷符号
像在之前的示例中,可以通过一个快捷符号来访问已经存在的任务
task hello << {
println 'Hello world!'
}
hello.doLast {
println "Greetings from the $hello.name task."
}
这使用得代码更具可读性,特别是其它插件提供的tasks,比如compile
9). task的全局属性
在task中,可在属性中添加ext.
前缀,并赋值,这样在其它的task中,就可读取到这个属性值了
示例:
task myTask {
ext.myProperty = "myValue"
}
task printTaskProperties << {
println myTask.myProperty
}
10). 编写Ant Tasks
Ant tasks are first-class citizens in Gradle.
Using Ant tasks from Gradle is as convenient and more powerful than using Ant tasks from a build.xml file.
下面示例如何访问Ant tasks及访问Ant properties
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]}"
}
}
}
执行这个脚本,需要在当前脚本父目录中,创建文件夹antLoadfileResources
,并在其下创建几个文件
更多关于Gradle中使用Ant的教程:Using Ant from Gradle
11). 使用公共方法
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()
}
在后面将有章节,专门说明如果组织脚本代码的 Organizing Build Logic
12). 定义默认tasks
如果没有指定tasks,将执行默认的tasks
定义默认tasks示例:
defaultTasks 'clean', 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
如果只执行命令gradle -q
,由于没有指定tasks,就会执行默认的clean
与run
,相当于gradle -q clean run
如果子项目中没有指定默认tasks,则将执行父项目中的默认tasks
13). 通过DAG配置
在后面的构建生命周期中将有讲到,Gradle有一个配置阶段与一个执行阶段
配置阶段之后,Gradle就知道了所有需要被执行的tasks。此时,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
命令时,将输出:
D:\Learning\gradle\hello>gradle -q distribution
We build the zip with version=1.0-SNAPSHOT
当执行gradle -q release
命令时,将输出:
D:\Learning\gradle\hello>gradle -q release
We build the zip with version=1.0
We release now
非常重要的whenReady
,它是在relese
这个task执行之前起使用。
构建初始化插件
这个构建初始化插件正在不断完善中,在以后的版本中,DSL及其他配置可能会改变
这个构建初始化插件可以引导Gradle项目的创建。支持创建各种类型的Gradle项目,同时支持将其它构建方式转化为Gradle项目。
通常,Gradle插件是应用中项目。这个构建初始化插件是会自动应用于项目的,所以不需要特别配置。只需要在准备创建Gradle项目的地方,执行init这个task。
当使用这个构建初始化插件时,Gradle Wrapper
也会自动被安装到当前项目中。
1). 插件包含的tasks
Task name | depends on | Type | Description |
---|---|---|---|
init | wrapper | InitBuild | Generates a Gradle project. |
wrapper | - | Wrapper | Generates Gradle wrapper files. |
2). 初始设定
可以通过--type
参数,指定构建的项目类型
如:创建一个java项目 gradle init --type java-library
若没有设定type
参数,则Gradle将根据当前环境做出适当的判断,比如,当发现有pom.xml
文件时,就会将type
设定为pom
,即将maven项目转换为gradle项目
如果没有指定或判断出type
值,则将使用默认的basic
3). 初始化的项目类型
由于这个功能还在孵化中,所以只提供几种类型,更多的类型将在后续的版本中提供。
pom
在当前路径中查找文件pom.xml
,并将其转化为gradle项目java-library
创建java项目scala-library
groovy-library
basic
编写Gradle构建脚本
Gradle构建脚本语言
Gradle为构建脚本提供了一个领域特定语言(DSL)。基于Groovy,并添加了一些更易于描述脚本的语法。
Gradle构建脚本可以包含任何Groovy语言标识。默认UTF-8编码。
API: Project
- 调用当前脚本中没有的任何方法,都将委托给
Project
这个对象。 - 调用当前脚本中没有的任何属性,都将委托给
Project
这个对象。
println name
println project.name
第一行,是由于当前脚本未定义name
属性,则委托给project
这个对象,所以第一行与第二行输出是一样的
标准的项目属性
Project
这个对象,提供了几个标准的属性,可以构建脚本中直接使用,下面列出常用的几个
Name | Type | Default Value |
---|---|---|
project | Project | The Project instance |
name | String | The name of the project directory. |
path | String | The absolute path of the project. |
description | String | A description for the project. |
projectDir | File | The directory containing the build script. |
buildDir | File | projectDir/build |
group | Object | unspecified |
version | Object | unspecified |
ant | AntBuilder | An AntBuilder instance |
API: Script
当Gradle执行构建脚本时,会将这个脚本编译成实现接口Script
的类。也就是说,接口Script
中的所有属性和方法,在构建脚本中都可以调用。
Script
的官方文档: https://docs.gradle.org/current/dsl/org.gradle.api.Script.html
声明变更
在构建脚本中,有两种方式声明变更。本地变更(Local variables)和全局变量(Extra properties)
使用关键字def
来进行声明本地变量(只在所声明范围有效)。这是Groovy的语法。
def
示例:
def dest = "dest"
task copy(type: Copy) {
from "source"
into dest
}
使用关键字ext.
作为前缀来声明全局变量。 这种变量,在子项目中,也是可见的。
包括但不限于,projects
、tasks
与source
都可以定义、改变及使用这种全局变量
ext.
示例:
apply plugin: "java"
ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "build@master.org"
}
sourceSets.all { ext.purpose = null }
sourceSets {
main {
purpose = "production"
}
test {
purpose = "test"
}
plugin {
purpose = "production"
}
}
task printProperties << {
println springVersion
println emailNotification
sourceSets.matching { it.purpose == "production" }.each { println it.name }
}
对上面的脚本,执行命令gradle -q printProperties
,将输出:
D:\Learning\gradle\Extra properties>gradle -q printProperties
3.1.0.RELEASE
build@master.org
main
plugin
关于ext.
的更多用法,参考: https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
配置对象
可以使用如下示例的方式,配置任意对象,这样的脚本具有非常高的可读性。
task configure << {
def pos = configure(new java.text.FieldPosition(10)) {
beginIndex = 1
endIndex = 5
}
println pos.beginIndex
println pos.endIndex
}
执行命令gradle -q configure
,将输出:
D:\Learning\gradle\Configuring arbitrary objects>gradle -q configure
1
5
使用外部脚本配置对象
示例,使用外部的other.gradle来对build.gradle的pos对象进行配置
build.gradle
task configure << {
def pos = new java.text.FieldPosition(10)
// Apply the script
apply from: 'other.gradle', to: pos
println pos.beginIndex
println pos.endIndex
}
other.gradle
// Set properties.
beginIndex = 1
endIndex = 5
Groovy简单入门
Groovy提供了非常的DSL特性,而Gradle也继承了这些特性。懂得构建语言对编写脚本,特别是自定义插件和tasks时,是非常有用的。
1). Groovy JDK
在java的基础上,groovy添加了许多有用的方法。如,迭代(Iterable),在Groovy中,可以直接使用each
方法。
// Iterable gets an each() method
configurations.runtime.each { File f -> println f }
在 http://groovy-lang.org/gdk.html 在详细的说明。
2). Property accessors
Groovy会自动将对属性的调用,转换为getter或setter方法。
// Using a getter method
println project.buildDir
println getProject().getBuildDir()
// Using a setter method
project.buildDir = 'target'
getProject().setBuildDir('target')
3). 方法调用可省略圆括号
test.systemProperty 'some.prop', 'value'
test.systemProperty('some.prop', 'value')
4). List与map集合
Groovy提供了简捷的List与map的实例化方式。
// List literal
test.includes = ['org/gradle/api/**', 'org/gradle/internal/**']
List<String> list = new ArrayList<String>()
list.add('org/gradle/api/**')
list.add('org/gradle/internal/**')
test.includes = list
// Map literal.
Map<String, String> map = [key1:'value1', key2: 'value2']
// Groovy will coerce named arguments
// into a single map argument
apply plugin: 'java'
5). 闭包作为方法的最后参数
Gradle DSL 在很多地方都使用了闭包。
参考: http://docs.groovy-lang.org/latest/html/documentation/index.html#_closures
repositories {
println "in a closure"
}
repositories() { println "in a closure" }
repositories({ println "in a closure" })
6). 闭包委派
每个闭包,都会委派一个用于查找变量及方法的对象。
示例: 闭包委派
dependencies {
assert delegate == project.dependencies
testCompile('junit:junit:4.12')
delegate.testCompile('junit:junit:4.12')
}
默认导入
为了使用脚本更简捷,Gradle自动导入一系列重要的声明。
主要是import org.gradle.*
及这个包下的子包
深入tasks
区别于Ant的target,Gradle支持增强的tasks,它可以有自己的属性和方法。
定义task
示例1: 定义task
task(hello) << {
println "hello"
}
task(copy, type: Copy) {
from(file('srcDir'))
into(buildDir)
}
示例2:使用strings作为task名字
task('hello') <<
{
println "hello"
}
task('copy', type: Copy) {
from(file('srcDir'))
into(buildDir)
}
示例3:对示例2的替代语法
tasks.create(name: 'hello') << {
println "hello"
}
tasks.create(name: 'copy', type: Copy) {
from(file('srcDir'))
into(buildDir)
}
对于task的create方法,参考: https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskContainer.html
定位tasks
示例1:通过tasks的属性访问task
task hello
println hello.name
println project.hello.name
示例2:通过tasks集合访问task
task hello
println tasks.hello.name
println tasks['hello'].name
示例3:通过路径访问task
project(':projectA') {
task hello
}
task hello
println tasks.getByPath('hello').path
println tasks.getByPath(':hello').path
println tasks.getByPath('projectA:hello').path
println tasks.getByPath(':projectA:hello').path
对于示例3,需要在当前路径中,添加名为projectA
的文件夹,并在配置文件settings.gradle
中添加include 'projectA'
示例3的输出如下:
D:\Learning\gradle\Locating tasks>gradle -q hello
:hello
:hello
:projectA:hello
:projectA:hello
对于更多的定位tasks的介绍,访问 https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskContainer.html
配置tasks
首先来看一下Gradle提供的Copy task
。可以如下定义一个Copy task
task myCopy(type: Copy)
这个myCopy
并没有定义默认的操作,但它可以使用Copy
的API了。下面会举几个例子,有不同的方式达到同样的目的。
Copy
API: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Copy.html
当然,这个myCopy
只是一个Copy
类型的task,同样还可以定义更多的Copy
类型的task。
示例1: 使用不同的方式配置task
Copy myCopy = task(myCopy, type: Copy)
myCopy.from 'resources'
myCopy.into 'target'
myCopy.include('**/*.txt', '**/*.xml', '**/*.properties')
对于示例1的方式,很类似于java。但这种方式比较冗余,而且代码可读性不强。
下面示例比较常用的方式。
示例2: 使用闭包配置task
task myCopy(type: Copy)
myCopy {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
也可以直接使用如下方式:
task myCopy(type: Copy) {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
为task添加依赖
示例1: 直接使用task名字关联
project('projectA') {
task taskX(dependsOn: ':projectB:taskY') << {
println 'taskX'
}
}
project('projectB') {
task taskY << {
println 'taskY'
}
}
执行gradle -q taskX
,将输出:
D:\Learning\gradle\Adding dependencies to a task>gradle -q taskX
taskY
taskX
示例2: 使用对应task对象关联
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
taskX.dependsOn taskY
执行gradle -q taskX
,也将输出:
D:\Learning\gradle\Adding dependencies to a task>gradle -q taskX
taskY
taskX
示例3: 使用闭包添加依赖
task taskX << {
println 'taskX'
}
taskX.dependsOn {
tasks.findAll { task -> task.name.startsWith('lib') }
}
task lib1 << {
println 'lib1'
}
task lib2 << {
println 'lib2'
}
task notALib << {
println 'notALib'
}
执行gradle -q taskX
,将输出:
D:\Learning\gradle\Adding dependencies to a task>gradle -q taskX
lib1
lib2
taskX
关于task的更多用法,参考: https://docs.gradle.org/current/dsl/org.gradle.api.Task.html
tasks排序
这是一个还在孵化中的特性,在以后的Gradle版本中可能变更。
排序与依赖的区别在于,排序并不会影响到task的执行,只是设定tasks的执行顺序。
排序,在下面情况下会很有用处:
- 有强制顺序的tasks排序:如
build
永远不会在clean
之前执行 - 在
build
之前执行构建校验:如校验是否有权限执行build
- 在耗时长的验证task之前,通过执行一个快速验证获得反馈:如在集成测试之前,应该先执行单元测试
- 一个收集所有特定类型task执行结果的task:如,测试报告task,它会收集所有测试task的运行结果。
只支持两排序方式: must run after
和should run after
示例1
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
taskY.mustRunAfter taskX
执行gradle -q taskY taskX
输出:
D:\Learning\gradle\Ordering tasks>gradle -q taskY taskX
taskX
taskY
示例2
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
taskY.shouldRunAfter taskX
执行gradle -q taskY taskX
输出:
D:\Learning\gradle\Ordering tasks>gradle -q taskY taskX
taskX
taskY
示例3
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
task taskZ << {
println 'taskZ'
}
taskX.dependsOn taskY
taskY.dependsOn taskZ
taskZ.shouldRunAfter taskX
执行gradle -q taskX
输出:
D:\Learning\gradle\Ordering tasks>gradle -q taskY taskX
taskZ
taskY
taskX
为task添加扫描信息
示例:
task copy(type: Copy) {
description 'Copies the resource directory to the target directory.'
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
tasks覆盖
使用overwrite
,示例:
task copy(type: Copy)
task copy(overwrite: true) << {
println('I am the new one.')
}
执行 gradle -q copy
,将输出
> gradle -q copy
I am the new one.
跳过task的执行
1). 使用断言
可以使用方式onlyIf()
为task添加断言。