gradle构建脚本

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) {}

扫描二维码关注公众号,回复: 959168 查看本文章

对于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 命令的任务)

猜你喜欢

转载自blog.csdn.net/yue530tomtom/article/details/79362648