gradle版本
假设你的本地gradle已经安装配置完成。没有安装配置的,可以参考 gradle安装
C:\Users\yueling.DANGDANG>gradle -v
------------------------------------------------------------
Gradle 4.5.1
------------------------------------------------------------
官网文档参考 https://docs.gradle.org/4.5.1/userguide/tutorial_using_tasks.html#sec:projects_and_tasks
组成
Gradle构建,是由一个或多个projects组成。project由ask列表组成。task由动作列表组成。
- Project指用Gradle做什么,如构建一个jar包,构建web应用。Project也不单指构建操作,如部署应用。
一个project由多个task组成。 - 每个task代表了构建过程当中的一个原子性操作,比如编译,打包,生成javadoc,发布等等这些操作
- 一个 Task 包含若干 Action。Action 就是一个闭包。Task 有 doFirst 和 doLast 两个函数,用于添加需要最先执行的 Action 和需要和需要最后执行的 Action。
闭包:闭包在groovy中是一个处于代码上下文中的开放的,匿名代码块。它可以访问到其外部的变量或方法。
语法:{ [closureParameters -> ] statements }
入门实例
gradle 命令会在当前目录中(或者参数-b指定的目录中)查找一个叫 build.gradle 的文件. build.gradle 文件为一个构建脚本 (build script), 但是严格来说它是一个构建配置脚本 (build configuration script). 这个脚本定义project和tasks
build.gradle
例子用到的配置如下
/*
* This build file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java Library project to get you started.
* For more details take a look at the Java Libraries chapter in the Gradle
* user guide available at https://docs.gradle.org/4.3/userguide/java_library_plugin.html
*/
// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:23.0'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
}
task extend(dependsOn: "base"){
doLast{
println 'extend!'
}
}
task base {
doLast{
println 'base!'
}
}
4.times { counter ->
task "task$counter" {
doLast {
println "I'm task number $counter"
}
}
}
task0.dependsOn task0,task1,task2, task3
task hello {
doLast {
println 'Hello Earth'
}
}
hello.doFirst {
println 'Hello Venus'
}
hello.doLast {
println 'Hello Mars'
}
hello {
doLast {
println 'Hello Jupiter'
}
}
task myTask {
ext.myProperty = "myValue"
}
task printTaskProperties() {
doLast {
println myTask.myProperty
}
}
defaultTasks 'init', 'run'
task init << {
println 'Default init!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
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'
}
}
task loadfile << {
def files = file('cfg').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
task loadfileexp << {
fileList('cfg').each { File file ->
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
File[] fileList(String dir) {
file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}
/*
//有依赖
task base {
doLast {
println "i'm base!"
}
}
task extend(dependsOn: base) {
doLast {
println "I'm extend!"
}
}
base.doLast {
println "addtion end......"
}
base.doFirst {
println "addtion start......"
}
//使用<<代替dolast
task dolast <<{
println "show me! dolast"
println ("show me! dolast")
println ("show me! dolast");
}
//多字节名称使用间歇eEE
task extendExpExp() {
doLast {
println "I'm extendExpExp"
}
}
*/
Gradle 任务里使用 Groovy
官网给出例子我就直接引用了
Example 57. Using Groovy in Gradle’s tasks
build.gradle
task upper {
doLast {
String someString = 'mY_nAmE'
println "Original: " + someString
println "Upper case: " + someString.toUpperCase()
}
}
task count {
doLast {
4.times { print "$it " }
}
}
简单解释下,任务upper在doLast中使用了简单的groovy语句,包括调用String的内建函数;任务count使用了groovy的循环
插播:groovy循环方式比较多
对于while:while (condition) {}
对于for循环:除了传统三表达式的for循环和用于迭代的for each循环外,Groovy允许for循环遍历一个范围(Range),例如 for (i in 1..10),表示循环10次,i在1至10之间取值;
对于整数,Groovy增加了如下几个方法来进行循环:
upto:n.upto(m) 函数,表示循环 m- n 次,并且会有一个循环变量it,从n开始,每次循环增加1,直到m。循环体写在upto方法之后大括号中,表示一个闭包,在闭包中,it作为循环变量,值从a增长到n;
times:n.times 函数,表示循环n次,循环变量it从0开始到n结束。
step:n.step(x, y) 函数,表示循环变量从n开始到x结束,每次循环后循环变量增加y,所以整个循环次数为 (x - n) / y 次;
for ( i in 0..4 ) {
println("test")
}
4.times {
println("test")
}
0.upto(3) {
println("test")
}
0.step(6, 2) {
print it + " "
}
List list = ["test", "test", "test", "test"]
list.each {
element->println(element)
}
任务依赖
任务之间互相依赖~,定义非常简单只需要在任务定义的时候指明即可
task base {
doLast{
println 'base!'
}
}
task extend(dependsOn: base){
doLast{
println 'extend!'
}
}
d:\eclipsWS\gradleWS\gradleDemo>gradle extend
Starting a Gradle Daemon (subsequent builds will be faster)
:base
base!
:extend
extend!
BUILD SUCCESSFUL in 24s
2 actionable tasks: 2 executed
d:\eclipsWS\gradleWS\gradleDemo>
注意任务extend定义的时候使用了dependsOn,执行任务extend的时候会优先执行base(类似类的继承)
提示:doLast有简写方式为<< 在前面的文章中有介绍
定义任务依赖:可以先定义依赖再定义被依赖的任务
task extend(dependsOn: 'base'){
doLast{
println 'extend!'
}
}
task base {
doLast{
println 'base!'
}
}
此案例中在任务base没有定义的时候就被任务extend引用。
有个坑,没有搞太懂,知道的可以回复一下
在上述的例子中,如果dependsOn:base 中的base没有加入引号(单引号或者双引号),运行失败;任务名加上引号,能够正常执行
d:\eclipsWS\gradleWS\gradleDemo>gradle -q extend
base!
extend!
d:\eclipsWS\gradleWS\gradleDemo>gradle -q extend
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\eclipsWS\gradleWS\gradleDemo\build.gradle' line: 30
* What went wrong:
A problem occurred evaluating root project 'gradleDemo'.
> Could not get unknown property 'base' for root project 'gradleDemo' of type org.gradle.api.Project.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
d:\eclipsWS\gradleWS\gradleDemo>
动态任务
Groovy的强大功能不仅可以用来定义任务的功能。例如,您还可以使用它来动态地创建任务,顾名思义,定义任务的时候没有具体指明任务的名称,名称是可以变化的。
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
这里使用了groovy的循环特性,循环4次(0-3)分别创建了task0、task1、task2、task3。可以在使用gradle运行它们,如
d:\eclipsWS\gradleWS\gradleDemo>gradle -q task0
I'm task number 0
d:\eclipsWS\gradleWS\gradleDemo>gradle -q task1
yesI'm task number 1
d:\eclipsWS\gradleWS\gradleDemo>gradle -q task2
I'm task number 2
d:\eclipsWS\gradleWS\gradleDemo>gradle -q task3
I'm task number 3
d:\eclipsWS\gradleWS\gradleDemo>
复用已经存在的任务
一旦创建了任务,就可以通过API访问它们。例如,在运行时,可以使用它动态地向任务添加依赖项。ant不允许这样的操作~
4.times { counter ->
task "task$counter" {
doLast {
println "I'm task number $counter"
}
}
}
task0.dependsOn task1,task2, task3
d:\eclipsWS\gradleWS\gradleDemo>gradle -q task0
I'm task number 1
I'm task number 2
I'm task number 3
I'm task number 0
注意,使用这种方式做依赖时不要配置时出现自身依赖自身的情况
另外可以使用doFirst和doLast两个函数进行行为控制,多次执行~
task hello {
doLast {
println 'Hello Earth'
}
}
hello.doFirst {
println 'Hello Venus'
}
hello.doLast {
println 'Hello Mars'
}
hello {
doLast {
println 'Hello Jupiter'
}
}
d:\eclipsWS\gradleWS\gradleDemo>gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
d:\eclipsWS\gradleWS\gradleDemo>
任务操作快捷方式
有一个方便的符号来访问现有的任务。每个任务都可以作为构建脚本的属性来使用。可以通过“$”这种短标记法来访问任务
task hello << {
println 'Hello, Gradle!'
}
hello.doLast {
println "Greetings from the $hello.name task."
}
额外配置任务属性
可以将自定义的属性添加到任务中。要添加一个名为myProperty的属性,将ext.myProperty设置为初始值。从这一点开始,可以读取和设置属性,就像预定义的任务属性一样
task myTask {
ext.myProperty = "myValue"
}
task printTaskProperties << {
println myTask.myProperty
}
d:\eclipsWS\gradleWS\gradleDemo>gradle printTaskProperties
:printTaskProperties
myValue
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
d:\eclipsWS\gradleWS\gradleDemo>
调用Ant任务
比如利用AntBuilder执行ant.loadfiile。为演示说明我们在项目的根目录下建一个文件夹命名为cfg,分别建立文件如下
antTest.xml
<?xml version="1.0" encoding="GB2312"?>
<project name="SQLscript" default="default">
<property name="FILE_NAME_RESOURCE" value="resource_tmrpt.sql" />
<property name="FILE_NAME_INIT" value="init_tmrpt.sql" />
</project>
textTest.txt
user=lilei
passwd=******
编写任务如下
task loadfile << {
def files = file('cfg').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
执行结果:
d:\eclipsWS\gradleWS\gradleDemo>gradle -q loadfile
*** antTest.xml ***
<?xml version="1.0" encoding="GB2312"?>
<project name="SQLscript" default="default">
<property name="FILE_NAME_RESOURCE" value="resource_tmrpt.sql" />
<property name="FILE_NAME_INIT" value="init_tmrpt.sql" />
</project>
*** textTest.txt ***
user=yueling
passwd=******
方法抽取
在上面的脚本中,我们可以把部分代码抽取出来方便演示我们新加一个任务loadfileexp,如下:
task loadfileexp << {
fileList('cfg').each { File file ->
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
File[] fileList(String dir) {
file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}
执行结果一样
d:\eclipsWS\gradleWS\gradleDemo>gradle -q loadfileexp
*** antTest.xml ***
<?xml version="1.0" encoding="GB2312"?>
<project name="SQLscript" default="default">
<property name="FILE_NAME_RESOURCE" value="resource_tmrpt.sql" />
<property name="FILE_NAME_INIT" value="init_tmrpt.sql" />
</project>
*** textTest.txt ***
user=yueling
passwd=******
d:\eclipsWS\gradleWS\gradleDemo>
设置默认任务
gradle 允许在脚本中定义一个或多个默认任务,方式如下
defaultTasks 'init', 'run'
task init << {
println 'Default init!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
d:\eclipsWS\gradleWS\gradleDemo>gradle
:init
Default init!
:run
Default Running!
通过 DAG 配置
DAG意思是有向无环图,所谓有向无环图是指任意一条边有方向,且不存在环路的图。
gradle 有一个配置阶段和执行阶段. 在配置阶段后, Gradle 将会知道应执行的所有任务. Gradle 为你提供一个”钩子”, 以便利用这些信息. 举个例子, 判断发布的任务是否在要被执行的任务当中. 根据这一点, 你可以给一些变量指定不同的值.
在接下来的例子中, distribution 任务和 release 任务将根据变量的版本产生不同的值
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'
}
}
d:\eclipsWS\gradleWS\gradleDemo>gradle -q release
We build the zip with version=1.0
We release now
d:\eclipsWS\gradleWS\gradleDemo>gradle -q distribution
We build the zip with version=1.0-SNAPSHOT
d:\eclipsWS\gradleWS\gradleDemo>
最重要的是 whenReady 在 release 任务执行之前就已经影响了 release 任务. 甚至 release 任务不是首要任务 (i.e., 首要任务是指通过 gradle 命令的任务)