Gradle 学习

近来准备学习gradle, 参考书籍Mastering Gradle。 然此书中有些代码语法与现在的gradle版本相比较老,需要进行遗弃与更改。虽然语法更新较快, 但其中的精髓还是值得让人学习。本文是基于Gradle 6.8.1 写的代码。篇幅可能过长,尽量简洁,如有需要,直接搜索关键字阅读相关主题。

1 Gradle 入门

第一行代码:

建立文件命令为build.gradle, 并写以下代码:

task helloGradle {
    doLast{
        println 'Hello Gradle World!'
    }
}

代码中println的意思是打印输出。 敲以下命令:

gradle helloGradle

运行结果:
在这里插入图片描述
书中原来的代码是

task helloGradle << {
        println 'Hello Gradle World!'
}

但这种方式运行会导致失败,原因是符号 << 早已被gradle弃用。

敲击命令后gradle默认运行当前目录下的build.gradle文件,并可以指定某个task运行。如果不想默认运行build.gradle文件,可以加上-b参数,如下:

gradle -b <buildfile_name> helloGradle

有些task执行过程中可能会抛出异常执行失败,这将会导致后续的task无法继续执行。那么此时我们可以加上–continue参数,表明继续执行后续的task。

gradle  helloGradle --continue

有些task不想被执行,可以加入-x参数。

gradle  helloGradle -x helloGradle

不想多余信息被打印显示出来,加-q参数

gradle  helloGradle -q

其实在我们每次运行gradle的时候,JVM会被运行起来,很多gradle的库会被加载进来。如果启动很频繁,库每次被加载,势必会耗费性能。为了节省时间,可以加上–daemon

gradle  helloGradle -q --daemon

如果task之间有依赖关系,可以利用dependsOn参数

task helloGradle {
    doLast{
        println 'Hello Gradle World!'
    }
}

task test(dependsOn: helloGradle){
    doLast{
        println 'Test case executed!'
    }
}

这样运行的时候会先运行helloGradle, 再运行test。

Gradle的运行分为三个阶段

  1. 初始化阶段(initialization): 决定运行哪个project(因为可能会有多个project在配置文件中),并且为project创建运行实例(project instance) 。
  2. 配置阶段(configuration): 任何写于task之外的语句都会在这个阶段被执行,task不会被执行,在这个阶段里,task的依赖关系会被形成。
  3. 执行阶段(execution): 执行task。

Cache管理

Gradle自动去下载所有在build文件里的依赖并将其保存在一个缓存区中,这样的好处是下回在build的时候不需要重新下载。cache的文件地址通常是在<USER_HOME>/.gradle/caches。

2: Groovy 入门

建立第一个groovy文件, 名为GroovyTest.groovy:

println "Hello Groovy"

然后运行命令

groovy GroovyTest.groovy

对于groovy文件,也可以将其预先编译,以后如果需要多次运行这个文件将省去编译时间。敲以下命令进行groovy的编译:

groovyc GroovyTest.groovy

在我本地环境中,将形成GroovyTest.class文件,如果想要运行这个文件,找到groovy-all-*.jar包,执行以下命令:

java -cp %GROOVY_HOME%/embeddable/groovy-all-2.3.1.jar; GroovyTest

命令将会顺利执行。 注意有个";", 千万不要省略,不然会忘记。

关于groovy大部分语法与java相同,容易掌握,不在此赘述,有问题可以找度娘或者google。然有些概念可能需要解释下:

闭包(Closure):

经常能遇见这个概念,可以粗略的将这个概念理解为将某个不在当前范围作用域而在上层范围作用域的变量包裹起来,如下代码:

class ClosurePrint {
    def printClosure = {
        println value + 10
    }
}

def closureFunc = new ClosurePrint().printClosure
def value = 10

closureFunc.delegate = value

closureFunc();

在上面的代码中,变量closureFunc指向类ClosurePrint的函数变量printClosure, 在调用closureFunc()之前, 将value赋值给closureFunc.delegate,这样在调用closureFunc()的时候,类ClosurePrint的函数printClosure()先寻找当前范围是否存在名为value的变量,如果不存在,就在delegate中去寻找,找到后并输出。

Builder

利用groovy的功能builder可以产生复杂的XML树形结构,举个例子,代码如下:

class School {
    Student student
    String description
}

class Student{
    String name
    String email
}

School school = new School()
school.student = new Student(name: "Student1",email: "Student1@email.com")
school.setDescription("This is student 1")

def schoolList = school

def builder = new groovy.xml.MarkupBuilder(new FileWriter("schoolList.xml"))

builder.SchoolList{ //SchoolList为根标签节点的名称
    for(i in schoolList){
        School{ //School为xml标签节点名称
            description(i.description)//description为xml标签节点名称
            student{//student为xml标签节点名称
                name(firstname : i.student.name) //name为xml标签节点名称, firstname为name标签的属性
                email(i.student.email)//email为xml标签节点名称
            }
        }
    }
}

利用此代码生成的xml文件如下:

<SchoolList>
  <School>
    <description>This is student 1</description>
    <student>
      <name firstname='Student1' />
      <email>Student1@email.com</email>
    </student>
  </School>
</SchoolList>

具体的解析请看代码注释。

3:任务(Task)

一个project由task组成,每个project都有一些自带的property,例如name。还可以利用 ext 关键字给project加上自定义的property。具体请看下面代码:

println name

ext {
    start="This is start 1"
}

ext.end = "This is end 1"

task test {
    doLast{
        println start
        println end 
    }
}

输出结果如下
在这里插入图片描述
在上个章节讲过,Gradle的运行分为三个阶段:

  1. 初始化阶段(initialization): 决定运行哪个project(因为可能会有多个project在配置文件中),并且为project创建运行实例(project instance) 。
  2. 配置阶段(configuration): 任何写于task之外的语句都会在这个阶段被执行,task不会被执行,在这个阶段里,task的依赖关系会被形成。
  3. 执行阶段(execution): 执行task。

gradle运行时会按照以上这个顺序执行,举个例子

task test {
    doLast{
        println "This is execution part"
    }
}

println "this is configuration part"

输出为
在这里插入图片描述
当我们不想执行task而时可以利用参数–dry-run, 这个不会有执行阶段. 同样-m参数也会起到同样的效果。

gradle test --dry-run

在这里插入图片描述
在执行阶段时,在task中引入一个关键字doLast,同时我们还可以引入相应的关键字doFirst, 这个关键字将会doLast前进行执行。举例:

task test {
    doLast{
        println "do Last"
    }
}
test.doFirst {
    println "do First"
}

输出
在这里插入图片描述
Task的执行顺序,在前面的章节中利用过关键字dependsOn参数,这个参数可以建立起task之间的依赖关系并且确定执行顺序。还有三个参数值得关注:

  1. shouldRunAfter: 应该在某一个task运行完毕后在运行当前task。
  2. mustRunAfter: 当同时运行多个task的时候,必须在后一个task运行完毕后在运行当前task, 比关键字shouldRunAfter更加严格些。
  3. finalyzedBy: 运行完当前task后在运行后一个task。

下面的例子为这三个关键字的用法:

(1..3).each {
    task "Task$it" {
        doLast {
            println "Executing $name"
        }
    }
}

Task1.dependsOn Task2
Task2.dependsOn Task3
Task3.shouldRunAfter Task1

代码中创建了三个task并且每个task都打印一条语句,三个task的依赖关系是Task1依赖Task2,Task2依赖Task3,Task3 shouldRunAfter Task1. 这里面的关键字用的是shouldRunAfter 而不是mustRunAfter,因此不会像mustRunAfter那样严格,因此这个依赖关系也就没有形成一个环状,当运行:

gradle Task1

输出:
在这里插入图片描述
若将shouldRunAfter改为mustRunAfter,

(1..3).each {
    task "Task$it" {
        doLast {
            println "Executing $name"
        }
    }
}

Task1.dependsOn Task2
Task2.dependsOn Task3
Task3.mustRunAfterTask1

运行结果则不通过:
在这里插入图片描述
改变代码:

(1..3).each {
    task "Task$it" {
        doLast {
            println "Executing $name"
        }
    }
}

Task1.mustRunAfter Task3

运行"gradle Task1"和 "gradle Task1 Task3"的结果如下:
在这里插入图片描述
在这里插入图片描述
可以发现单独运行Task1的时候不会去运行Task3, 而同时运行Task1和Task3的时候会优先运行Task3。

gradle中也有条件执行语句:onlyIf, 当这个语句中的判断条件为true时才执行相应的task。例如:

ext {
    flag = 2
}

task Task1{
    doLast{
        println "This is task 1"
    }
}

Task1.onlyIf {
    project.hasProperty('flag') && project.flag==1
}

task Task2{
    doLast{
        println "This is task 2"
    }
}

Task2.onlyIf {
    project.hasProperty('flag') && project.flag==2
}

输出:
在这里插入图片描述从这里可以看出,执行Task1还是Task2依赖于project.flag,只有Task2的条件语句满足,所以只有Task2被执行。同时你也可以运行时通过加参数(-P)的方式设置该flag, 例如:

task Task1{
    doLast{
        println "This is task 1"
    }
}

Task1.onlyIf {
    project.hasProperty('flag') && project.flag=="1"
}

task Task2{
    doLast{
        println "This is task 2"
    }
}

Task2.onlyIf {
    project.hasProperty('flag') && project.flag=="2"
}

在这里插入图片描述这里要记住-Pflag=2 在代码中要用字符串的方式进行匹配,例如:project.flag==“2”, 不要写成project.flag==2

还有一个关键字enable去控制task是否被执行,代码如下:

task Task1{
    doLast{
        println "This is task 1"
    }
}

task Task2{
    doLast{
        println "This is task 2"
    }
}

Task2.enabled = false

在这里插入图片描述
Task2.enabled被设置为false, 所以执行gradle的时候Task2不会被触发。

增量构建(incremental build)
默认情况下,gradle build的时候会默认使用增量构建,即有的时候某个task的输入和输出没有发成任何变化(比如读取文件和生成文件),那么这个task不会再次运行,并会显示up-to-date信息。如果想要强制运行,可以加上–rerun-tasks参数。

Gradle内置一些task,例:

  1. task copyTaskExample(type: Copy)
  2. task copyWithRenameExample(type: Copy)
  3. task zipTaskExample(type: Zip)
    还有很多类似的task,不在这里一一介绍,举个简单的例子如何应用:
task copyTaskExample(type: Copy) {
    from "."
    into "./abc"
    include('*.xml')
}

当执行完这个task后,当前目录下的所有xml会被赋值到当前目录下名为abc的文件里。还可以自定义task的方式,具体不在这赘述。

4:管理插件(plugin)

插件包含一堆task, property和配置信息。有两种类型的插件

  1. 脚本插件(script plugin):就是gradle文件,
  2. 二进制插件(binary plugin): 相当于class文件,这些class文件有一个标识。

脚本插件
想要利用脚本插件需要"apply from:"语法:例如:
在同一个目录下创建两个gradle文件:
build.gradle

apply from: 'anotherbuild.gradle'
task buildTask {
    doLast{
        println "This is build task"
    }
}

anotherbuild.gradle

task anotherBuildTask {
    doLast{
        println "This is another build task"
    }
}

运行:
在这里插入图片描述
二进制插件
直接举例:

apply plugin: 'java'
task buildTask {
    doLast{
        println "This is build task"
    }
}

如果想要看这个plugin的所有task,可以输入:

gradle tasks --all

还有许多第三方plugin, 不在此赘述,有需求可以上网搜。这里简单罗列关于java plugin的常用的指令:

gradle classes			 // 编译在src/main/java下的文件
gradle testClasses   	 // 编译在src/test/java的文件
gradle test				 // 编译/src/test/java文件并且生成test报告结果
gradle assemble   		 // 生成jar包
gradle build			 // 执行完整的task,包含上述几个
gradle clean 			 // 清除所有生成的结果

未完待续·······

参考书籍

【1】 Mastering Gradle

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值