学习Gradle的build脚本语言。该学习记录基于Gradle官方网站资料。本篇参考链接如下:
https://docs.gradle.org/current/userguide/writing_build_scripts.html
1.Gradle build脚本
Gradle提供了一种DSL(domain specific language)脚本语言来构建工程。这种脚本语言支持Groovy 和Kotlin两种写法。分别可以使用Groovy 和Kotlin语言的元素。
本学习记录使用的是Groovy编写方式。如果希望学习Kotlin,可以参照官网说明。
普遍意义上的build脚本就是最常用的*.gradle文件。
2.工程(project)API
构建脚本(*.gradle)通过配置来描述所要构建的工程。工程只是一个抽象的定义,可以认为它是一个java工程,一个lib包或者一个应用程序。每一个构建脚本都必须依赖一个工程对象。构建脚本的运行,就是对这个对象的配置。
下面的例子显示了在脚本中使用本工程的对象,及其属性。
这里的build.gradle脚本在projectA文件夹下,改文件夹被Gradle默认为工程。
task test { doLast { // 输出任务名 println(name) // 使用工程对象,输出项目名 println(project.name) } }
输出:
$ gradle -q test
test
projectA
※实际的输出结果和官网的结果不一样。官网相同的例子输出了两个工程名。但是在笔者环境里输出的是任务名和工程名。
几个常用的标准工程属性:
- project:工程的对象。类型是Project
- name:工程名,指向工程的根文件夹名。类型是String
- path:工程的绝对路径。类型是String
- description:工程的描述。类型是String
- projectDir:含有构建脚本的工程路径。类型是File
- buildDir:projectDir/build。类型是File
- group:定义基本与maven工程的group相同。类型是Object
- version:版本。类型是Object
3.脚本API
Gradle会把*.gradle脚本编译为实现了Script接口的类。所有Script接口定义的属性和方法都可以使用。
4.声明变量
- 本地变量
本地变量用def修饰。只能用于当前脚本中。
def outputString = "Local variable" task test { doLast { println outputString } }
输出:
$ gradle -q test
Local variable
- 额外的属性
在Gradle里,可以自定义一些属性,用于扩充对象。比如扩充工程,任务对象等。
额外属性需要ext属性的支持。可以使用ext.myProperty或者如例子中使用ext代码块。
plugins { id 'java' } // ext代码块,引入两个额外变量 ext { springVersion = "3.1.0.RELEASE" emailNotification = "build@master.org" } // 为sourceSets的每一个source引入额外变量purpose,赋值为null sourceSets.all { ext.purpose = null } // 重新为每一个source的purpose变量赋值 sourceSets { main { purpose = "production" } test { purpose = "test" } plugin { purpose = "production" } } // 输出 task printProperties { doLast { println springVersion println emailNotification // 在set中找到purpose为producion的所有source,并打印source的名字 sourceSets.matching { it.purpose == "production" }.each { println it.name } } }
输出:
$ gradle -q printProperties
3.1.0.RELEASE
build@master.org
main
plugin
关于plugin和sourceSets,后续会展开学习。
5.配置任意对象
- 在当前脚本内部配置任意对象
如例所示,FieldPosition类有beginIndex和endIndex属性,通过configure方法,可以直接访问这两个属性,并且赋值。
import java.text.FieldPosition task configure { doLast { def pos = configure(new FieldPosition(10)) { beginIndex = 1 endIndex = 5 } println pos.beginIndex println pos.endIndex } }
输出:
$ gradle -q configure
1
5
- 通过引入外部脚本来配置任意对象
build.gradle
task configure { doLast { def pos = new java.text.FieldPosition(10) // Apply the script apply from: 'other.gradle', to: pos println pos.beginIndex println pos.endIndex } }
other.gradle
beginIndex = 1 endIndex = 5
输出:
$ gradle -q configure
1
5
6.Groovy简介
使用Groovy方式编写脚本,需要了解一些Groovy的特性。
- Groovy的JDK追加了一些java所没有的方法,比如Iterable追加了一个each方法。
configurations.runtime.each { File f -> println f }
- 简化访问属性的方法,可以直接访问属性,而不需要getter和setter。
- 调用方法的时候,方法的参数可以不用括号
- 简化List和Map的
// List test.includes = ['org/gradle/api/**', 'org/gradle/internal/**'] // Map Map<String, String> map = [key1:'value1', key2: 'value2']
- 闭包可以作为方法的最后一个参数
repositories { println "in a closure" } repositories() { println "in a closure" } repositories({ println "in a closure" })
- 闭包代理(Closure delegate),每个闭包都可以使用代理来替代访问。Groovy主要用这个代理来访问闭包内的属性。※这里不太理解, 需要后续深入学习。
dependencies { assert delegate == project.dependencies testCompile('junit:junit:4.12') delegate.testCompile('junit:junit:4.12') }
构建脚本默认引入的类库
构建脚本中,默认引入很多类库。所以可以在脚本中直接访问引入的类。具体列表可以参照如下链接。在后续的学习中,会学到一些具体类库的使用方法。
https://docs.gradle.org/current/userguide/writing_build_scripts.html#script-default-imports