Gradle是一款非常优秀的构建系统工具,它的DSL是基于Groovy实现。可以方便通过代码控制这些DSL达到构建目的,Gradle构建大部分功能是通过插件方式来实现。
Wrappe是对Gradle的一层包装,便于团队在开发过程中统一Gradle构建版本,避免因为Gradle构建版本不同意带来的不必要麻烦。
distributionBase=GRADLE_USER_HOME //下载Gradle压缩包解压后存储的主目录
distributionPath=wrapper/dists //相对于distributionBase解压后Gradle压缩包路径
zipStoreBase=GRADLE_USER_HOME //同distributionBase,只不过存放zip压缩包
zipStorePath=wrapper/dists //同distributionPath,只不过存放zip压缩包
//Gradle发行版压缩包的下载地址
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
gradle-wrapper.properties是由Wrapper Task生成的,可以自定义配置Wrapper Task来达到配置gradle-wrapper.properties。在build.gradle构建文件中录入脚本:
task Wrapper(type: Wrapper){
gradleVersion = '5.4.2'
distributionBase='GRADLE_USER_HOME'
distributionPath= 'wrapper/dists'
zipStoreBase= 'GRADLE_USER_HOME'
zipStorePath= 'wrapper/dists'
distributionUrl= 'https://services.gradle.org/distributions/gradle-5.4.1-all.zip'
}
Groovy是基于JVM虚拟机的一种动态语言,它的语法与Java非常相似,由Java入门Groovy基本没有任何障碍。Groovy完全兼容Java,又在此基础上增加了很多动态类型和灵活特性,比如闭包,支持DSL,是一门非常灵活的动态脚本语言。
task printStringClass << {
def str1 = '单引号字符串'
def str2 = "双引号字符串"
}
task printList << {
def numList = [1,2,3,4]
println numList.getClass().getName()
println numList[2] //访问第三个元素
println numList[-1] //访问最后一个元素
numList.each {
println it //遍历访问
}
}
task printMap << {
def map1 = ['width':1920,'height':1080]
println map1.getClass().getName()
println map1['width']
map1.each {
println("key:${it.key},value:${it.value}")
}
}
task invokeMethod << {
method1 1,2
method2(3,4)
}
def method1(int a,int b) {
println(a+b)
}
def method2(int a,int b) {
if (a > b) {
a
}else {
b
}
}
task helloClosure << {
//使用自定义的闭包
customEeach {
print it
}
}
def customEeach(closure) {
for (int i = 0; i < 10; i++) {
closure(i)
}
}
task helloClosure << {
//使用自定义的闭包
eachMap {
// -> 用于把参数和主体区分开来
k,v ->
println("${k} is ${v}")
}
}
def eachMap(closure) {
def map1 = ["name":"王麻子","age":"18"]
map1.each {
closure(it.key,it.value)
}
}
task helloClosure << {
new Delegate().test {
println("thisObject:${thisObject.getClass()}")
}
}
class Delegate {
def test(Closure closure){
closure(this)
}
}
设置的大多的作用都是为了配置子工程,在Gradle中多个工程是通过工程树表示的。相当于Android Studio看到Project和Module概念一样。根目录相当于Android Studio的Project,一个根目录可以有很多子工程,也就是有很多Module。
subprojects {
apply plugin:'java'
repositories{
jcenter()
}
}
在Gradle中可以有很多Project,可以定义创建一个Project用于生成jar/也可以定义另外一个Project生成war包等;一个Project就是在业务范围内,被抽象出来的一个个独立模块可以根据项目情况抽象归类,最后一个个Project组成整个Gradle;
一个Project中又包含很多Tasks,Tasks就是一个操作,一个原子性的操作。
task helloClosure{
}
task helloClosure <<{
new Delegate().test {
println("thisObject:${thisObject.getClass()}")
}
}
task sayHello(dependsOn:helloClosure){
}
创建一个任务和定义一个变量是一样的,变量名就是定义的任务名,可以使用任务名通过Tasks中API访问方法/属性/或对任务重新配置。
//自定义一个project的属性
ext age = 18
//自定义一个project的代码块属性
ext {
name = '王麻子'
age = 18
}
第一种直接以任务名创建任务的方式:
def Task taskOne = task(taskOne)
第二种以任务名字+一个该任务配置的Map对象来创建任务:
def Task taskTwo = task(taskTwo,group: BasePlugin.BUILD_GROUP)
Task参数中Map的可配置项:
配置项 | 描述 | 默认值 |
type | 基于存在的Task来创建,和继承类似 | DefultTask |
overwrite | 是否替换存在的Task,和type配合用 | false |
dependOn | 用于配置任务的依赖 | [] |
action | 添加到任务的一个action或闭包 | null |
decription | 用配置任务的描述 | null |
group | 用于配置任务的分组 | null |
第三种方式以任务名字+闭包配置的方式:
第一种直接通过任务名称访问和操作该任务;
第二种通过访问集合的方式访问创建的任务;
task["taskOne"].properties{
}
第三种通过名称访问,有get和find两种方式:
tasks.findByName("taskOne")
def Task taskOne = task(taskOne)
taskOne.group = BasePlugin.BUILD_GROUP
taskOne.description = "任务的描述"
可以添加任务到项目中,帮忙完成一些事,如测试/编译/打包等;
可以添加依赖配置到项目中,如依赖的第三方库;
可以向项目中现有的对象类型添加新的扩展属性/方法等,有助于配置/优化构建;
可以对项目进行一些约定。
应用二进制插件,二进制插件就是实现了org.gradle.api.Plugin的插件:
apply plugin: 'org.gradle.api.plugins.JavaPlugin'
apply form: 'version.gradle'
void apply(Closure closure);
void apply(Action super ObjectConfigurationAction> action);
void apply(Map options);
apply {
plugin 'java'
}
buildscript {
repositories {
google()
jcenter() //构建脚本引入jcenter
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
class mySelfPlugin implements Plugin {
@Override
void apply(Project target) {
}
}
apply plugin:'java'
通过以上脚本的应用之后,Java插件会为工程添加很多有用的默认设置和约定,如源代码的位置/单元测试代码的位置/资源文件的位置等。一般情况下最好遵循它的默认设置。
默认情况下,Java插件约定src/main/java为我们项目源代码存放目录;src/main/resources为要打包的文件存放目录如一些Properties配置文件和图片等;src/test/java为我们单元测试存放目录;src/test/resources为存放单元测试中使用的文件。
也可以新建一个源集,目录用于存放其他结构的代码资源,如下:
sourceSets {
vip{
}
}
repositories {
//配置仓库
mavenCentral()
maven {
url'http://www.mavenurl.com/'
}
}
//配置依赖
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.0.1'
}
Gradle提供的配置依赖:
名称 | 继承于 | 被哪个任务使用 | 意义 |
compile | _ | compileJava | 编译时依赖 |
runtime | compile | _ | 运行时依赖 |
testCompile | compile | compileTestJava | 编译测试用例时依赖 |
testRuntime | runtime testCompile | test | 仅在测试用例运行时依赖 |
archive | —— | uploadArchive | 该项目发布构建(jar包等)依赖 |
default | runtime | _ | 默认依赖配置 |
Java插件可以为不同源集在编译时和运行时指定不同的依赖。
dependencies {
mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
VIPCompile 'com.squareup.okhttp3:okhttp:2.5.1'
}
依赖通用使用格式:
名称 | 继承于 | 被哪个任务使用 | 意义 |
sourceSetCompile | _ | sourceSetCompileJava | 为指定源集提供编译时依赖 |
sourceSetRuntime | sourceSetCompile | _ | 为指定源集提供运行时依赖 |
项目依赖:
dependencies {
compile project('项目名称') //项目名在同一目录下
compile files('lib/项目名称') //项目名在同一下lib目录下
compile fileTree(dir:'libs',include:'*.jar') //包含所有libs,后缀为.jar文件
}
Java插件在Project下为我们提供了一个sourceSet属性以及一个sourceSet{}闭包来访问和配置源集。
常用源集属性:
属性名 | 类型 | 描述 |
name | String | 它是只读的,如main |
output.classesDir | File | 该源集编译后的class文件目录 |
output.resourcesDir | File | 编译后生成的资源目录 |
compileClasspath | FileCollection | 编译该源集时所需的classpath |
java | SourceDirectorySet | 该源集的Java源文件 |
java.srcDir | Set | 该源集Java源文件所在目录 |
resources | SourceDirectorySet | 该源集的资源文件 |
resources.srcDir | Set | 该源集的资源文件所在目录 |
Java插件添加的通用任务:
任务名称 | 类型 | 描述 |
compileJava | JavaCompile | 使用javac编译Java源文件 |
processResources | Copy | 把资源文件拷贝到生产的资源目录里 |
classes | Task | 组装生产的类和资源文件目录 |
compileTestJava | JavaCompile | 使用javac测试Java源文件 |
processTestResources | Copy | 把测试资源文件拷贝到生产的资源目录里 |
testClasses | Task | 组装生产的测试类和相关资源文件目录 |
jar | Jar | 组装Jar文件 |
test | Test | 使用JUnit或TestNG运行单元测试 |
uploadArchives | Upload | 上传包含jar的构建,使用archive{}闭包配置 |
clean | Delete | 清除构建生成的目录文件 |
cleanTaskName | Delete | 删除指定任务生成的文件, |
javacdoc | Jar | 使用javacdoc生成Java API文档 |
源集任务:
任务名称 | 类型 | 描述 |
compileSourcesJava | JavaCompile | 使用javac编译指定源集的Java源代码 |
processSourcesSetResources | Copy | 把指定源集的资源文件复制到生产文件下的资源目录中 |
sourceSetClasses | Task | 组装给定源集的类和资源文件目录 |
Java插件添加了很多常用的属性,这些属性都被添加到Project中,可以直接使用;
Java插件添加属性的源集属性:
属性名 | 类型 | 描述 |
sourcesSet | SourcesSetContainer | 该Java项目的源集,可以访问和配置源集 |
sourcesCompatibility | JavaVersion | 编译Java源文件使用的Java版本 |
targetCompatibility | JavaVersion | 编译生成的类的Java版本 |
archiveBaseName | String | 打包jar或zip文件的名称 |
manifest | Manifest | 用于访问或配置的manifest清单文件 |
libDir | File | 存放生成的类库目录 |
distsDir | File | 存放生成的发布的文件的目录 |
多项目构建,其实就是多个Gradle项目一起构建,一起通过Settings.gradle配置管理。每个项目下都有一个build文件对该项目进行配置,然后采用项目依赖就可以实现多个项目协作。
apply plugin: 'java'
task publishJar(type: Jar)
artifacts {
archives publishJar
}
uploadArchives{
repositories{
flatDir{
name 'libs'
dir '$projectDir/libs'
}
mavenCentral()
}
}