Gradle系列之构建脚本基础

Posted jzmanu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle系列之构建脚本基础相关的知识,希望对你有一定的参考价值。

原文发于微信公众号 jzman-blog,欢迎关注交流。

前面两篇文章分别介绍了 Gradle 基础知识以及 Groovy 相关基础知识,这也是学习 Gradle 所必需了解的,文章链接如下::

本文将对 Gradle 整体进行了介绍和学习,了解了 Task、Project 等相关概念以及对使用 Gradle 来构建项目的一些常用操作,主要内容如下:

  1. Setting 文件
  2. Build 文件
  3. Project 和 Tasks
  4. 任务的创建
  5. 任务依赖
  6. 任务间的交互
  7. 自定义属性
  8. 总结

Setting 文件

说一下 Gradle 构建项目的 Setting 文件,该文件主要用来配置当前工程,比如 android 开发中一个项目中可能有多个子 Module,当不需要某个子 Module 时,可以取消该 Module 在配置文件 Setting 中的配置即可,当然只有在 Setting 文件中配置的子 Module 才会被构建,当然不只是 Android 开发,只要使用 Gradle 构建的项目都一样,Setting 是 Gradle 构建项目默认的配置文件名,下面简单测试一下 Setting.gradle 文件的使用,测试工程目录如下:

├─GradleSetting
│  ├─.gradle
│  │  ├─4.1
│  │  │  ├─fileChanges
│  │  │  ├─fileHashes
│  │  │  └─taskHistory
│  │  └─buildOutputCleanup
│  └─test
│      └─Method
│          └─.gradle
│              ├─4.1
│              │  ├─fileChanges
│              │  ├─fileHashes
│              │  └─taskHistory
│              └─buildOutputCleanup
│ build.gradle
│ setting.gradle

在工程名为 GradleSetting 的工程中 test 文件夹下有一个 Method 的子项目,这里会通过配置 setting.gradle 文件将子项目 Method 构建到 GradleSetting 中,setting.gradle 文件内容如下:

println "---------test----Setting.gradle----------"
//输出当前工程目录
println(rootDir)
//指定要参与构建的子项目
include ‘:Method‘
project(‘:Method‘).projectDir = new File(rootDir,‘test/Method‘)

来看一下输出结果:

PS E:GradlestudyGradleSetting> gradle testGradleSetting
---------test----Setting.gradle----------
E:GradlestudyGradleSetting

> Configure project :
testGradleSetting

> Configure project :Method
3
3
30
获取方法返回的结果:30
1
2
3
4
5


BUILD SUCCESSFUL in 2s

因为在 setting.gradle 文件中配置了 Method,从输出结果看 Method 确实参与了构建,取消在 setting.gradle 文件中的配置,则不会构建 Method,最好自己验证一下。

上面配置了子项目 Method 所在的位置,如果不指定则默认是与 setting.gradle 同级的目录。

Build 文件

如果选择使用 Gradle 构建项目,则每个项目都有一个 build.gradle 文件,该文件是项目构建的入口,对整个项目的配置生效,可以在根项目配置子项目的一下通用配置,比如配置子项目的仓库为 jcenter,这样子项目中所有的依赖就指向 jcenter 中心库下载,下面是参考代码:

//配置子项目依赖的仓库
subprojects{
	repositories{
		jcenter()
	}
}

//配置全部项目
allprojects{
	
}

...

通过本小节主要了解 build.gradle 文件的作用即可,实际开发中针对不同类型的项目会有更详细的相应配置策略。

Project 和 Tasks

在 Gradle 中有很多 Project,可将某个 Project 打包成 jar 提供给另一个 Project 使用,每个 Project 都是根据其业务需求抽象出来的一个子模块,最终通过 Gradle 构建成完整的项目。

每个 Project 允许有多个 task,Task 理解为任务,task 主要 完成某个具体的功能点,比如 wrapper task 主要就是完成 wrapper 文件的创建。

任务的创建

对于任务的创建已经比较熟悉了,下面使用 task 声明一个任务:

//1. 创建一个任务
task createTask{
	doFirst{
		println ‘doFirst‘
	}

	doLast{
		println ‘doLast‘
	}
}

//2. 使用TaskContainer创建一个任务,Project已经定义的TaskContainer,即tasks
tasks.create("createTask1"){
	doFirst{
		println ‘doFirst‘
	}

	doLast{
		println ‘doLast‘
	}
}

task 可以理解为创建任务的关键字,实际上 task 是 Project 里面的一个方法,在 Groovy 中可以省略方法参数上的括号,花括号里的内容是一个闭包,主要是对 task 进行相关配置,doFirst 和 doLast 是 Task 中常用的两个方法,分别会在该 task 开始和结束时执行。

任务依赖

任务之间可以相互依赖,可以控制某个任务执行的先后顺序,比如在运行 A 之前必须先运行 B,此时任务 A 依赖任务 B,具体参考如下代码:

//单任务依赖:通过dependsOn指定要依赖的任务
task B(dependsOn: A){
	doFirst{
		println ‘B‘
	}
}

task C{
	doFirst{
		println ‘C‘
	}
}

//多任务依赖
task D{
	dependsOn A, C
	doFirst{
		println ‘D‘
	}
}

下面看一下执行多依赖任务 gradle D 的执行结果:

PS E:GradlestudyGradleSetting> gradle D

> Task :A
A

> Task :C
C

> Task :D
D

BUILD SUCCESSFUL in 2s

显然,执行任务 D,其依赖的其他两个任务先执行,控制了任务执行的先后顺序。

注意:脚本是按照顺序执行,如果任务任务 A 和 C 在任务 D 的后面定义,当执行任务 D 的时候肯定会出错。

任务间的交互

创建的任务都有自己的名称,其类型是 Task,那么我们就可以通过 Task API 来控制控制任务的执行,使用任务名操作任务的原理是:Project 在创建任务的时候,已经将该任务对应的任务声明为 Project 对象的一个类型为 Task 的一个属性,测试代码如下:

//任务之间的交互
task E{
	println ‘hello e‘
	println "E是不是Project的属性:"+project.hasProperty(‘E‘)
}

E.doFirst{
	println ‘doFirst‘
}

E.doLast{
	println ‘doLast‘
}

上述代码的执行结果如下:

PS E:GradlestudyGradleSetting> gradle E

> Configure project :
hello e
E是不是Project的属性:true

> Task :E
doFirst
doLast


BUILD SUCCESSFUL in 1s

自定义属性

Project 和 Task 都允许用户添加额外的自定义属性,通过应用所属对应的 ext 属性来实现,添加之后可以通过 ext 属性对自定义的属性进行读取和设置,如果要同时添加多个自定义属性,可以通过 ext 代码块,参考如下代码定义自定义属性:

apply plugin:"java"

//自定义单个属性
ext.name1 = "Gradle"
//自定义多个属性
ext{
	age = 10
	score = 100
}

//在SourceSet中使用自定义属性
sourceSets.all{
	ext.resourceDir = null
}

//配置自定义属性
sourceSets{
	main{
		resourceDir = "main/res"
	}
	test{
		resourceDir = "test/res"
	}
}

task customProperty{
	println "name=${name1}"
	println "age=${age}"
	println "score=${score}"

	sourceSets.each {
		println "${it.name} resourceDir is ${it.resourceDir}"
	}
}

上述代码的执行结果:

PS E:GradlestudyGradleSetting> gradle customProperty

> Configure project :

name=Gradle
age=10
score=100
main resourceDir is main/res
test resourceDir is test/res

BUILD SUCCESSFUL in 2s

自定义属性相较局部变量作用域更加广泛,可以跨 Task、Project 访问自定义属性,只要能访问这些属性所属的对象,那么这些属性就可以被访问到, Android 开发中可以使用自定义属性单独定义版本号、版本名称以及用到的第三方库的版本,将其同意在单独的 gradle 文件中,各 Module 直接获取即可,不仅方便管理依赖库的版本,还在一定程度上提高工作效率。

总结

Gradle 脚本基于 Grooy ,而 Groovy 完全兼容 Java 语法,Gradle 脚本本质上还是代码,在 Gradle 中可以利用相关语法来完成相关功能。可以关注公众号:躬行之(jzman-blog),一起交流学习。
技术图片


以上是关于Gradle系列之构建脚本基础的主要内容,如果未能解决你的问题,请参考以下文章

Android Gradle 插件Gradle 基础配置 ② ( Gradle 空白项目构建示例演示 )

Android知识要点整理(15)----Gradle 之Groovy语言基础

Android知识要点整理(16)----Gradle 之项目结构

Gradle系列之初识Gradle

Gradle系列学习:初识Gradle之Groovy基础Gradle从入门到实战 - Groovy基础

Gradle 与 AGP 构建 API: 如何编写插件