Gradle build
Gradle是一个基于Apache Ant和Apache Maven概念的自动化构建工具
(from Wikipedia)
既然说是构建肯定就会有一个执行顺序的问题,什么先执行,什么后执行,要想了解这个问题,就要先了解Gradle的生命周期。
build 的生命周期
build的生命周期分为3个阶段
- 初始化阶段
- 配置阶段
- 执行阶段
1. 初始化阶段
- Gradle 支持单个项目或者多个项目的构建,在初始化阶段,Gradle决定哪些project需要参与构建,同时为每一个Project创建实例。
rootProject.name = "project-name"
include(":app")
include(":app-common")
其中rootProject.name 是一个属性,这里指定了rootProject的名字
include方法则是指定那个模块(项目)需要参与构建,这里是:app
,:app-common
这两个模块需要参与构建。
使用命令./gradlew -q properties
可以查看rootProject里的属性。
查看子项目的属性需要加上子项目的项目名,./gradlew -q app:properties
/settings.gradle
rootProject.name="test"
结果
>>> ./gradlew -q properties
------------------------------------------------------------
Root project
------------------------------------------------------------
……
name: test
……
2. 配置阶段
- 在这个阶段所有的project实例都会被配置,所有的build脚本都会被执行,即
build.gradle
,rootProject先执行,再子project。
这个阶段是我们在日常开发的过程中接触的最多的一个,比如我们对插件的配置
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.test"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
}
}
每个project都包括一个build.gradle, 在配置阶段执行。
- Task中的配置内容也是在这个阶段执行的。
在一个task中也包括配置语句
task hello {
doFirst{
println("hello,do first.")
}
println("hello,task!")
doLast{
println("hello,do last.")
}
}
执行结果:
> Configure project :
hello,task!
> Task :hello
hello,do first.
hello,do last.
从结果可以看到println("hello,task!")
是在配置阶段执行的,只有在doFirst和doLast闭包中的代码才会在第三个阶段执行阶段完成。task里的语句执行顺序收到task的生命周期和doFirst,doLast影响。
3. 执行阶段
Gradle决定了任务的子集,在配置阶段创建和配置,并被执行。这个子集由传递给gradle命令和当前目录的任务名参数决定。然后Gradle执行每一个被选择的任务。
利用Task之间的依赖关系,会对所有的task生成一个有向无环图(Task执行图),这里决定了task的执行顺序。
taskx.dependOn(tasky)
//tasky 必须在 taskx 之前执行
Gradle Hook点
那我们知道了Gradle的生命周期之后有什么用呢?
Activity的生命周期相信大家都很熟悉,我们学习Activity的周期是想知道我们的代码应该卸载什么地方,Activity提供了一些回调方法使程序员可以参与到Activity的生命周期中,对Activity进行操作。
Gradle的生命周期也是一样,我们可以在生命周期的各个阶段来加入自己的逻辑来控制项目的构建。
我们可以利用这些hook点来写入自己的代码逻辑。
获取Manifest 举例
// 利用gradle build中的hook点,将代码逻辑放在配置结束的回调闭包中
project.afterEvaluate {
//获取配置中的applicationVariants变量并遍历
project.extensions.android.applicationVariants.all { variant ->
variant.outputs.all { output ->
//获取processManifestTask(对Manifest进行处理的task)
def processManifestTask = output.processManifestProvider.get()
processManifestTask.doFirst("precheck${variantName}Manifest") {
def manifestFiles = processManifestTask.manifests.files
// 在task之前处理manifest文件 ...
}
processManifestTask.doLast("postProcess${variantName}Manifest") {
File files = processManifestTask.manifestOutputDirectory.getAsFile().get()
// 在task之后处理Manifest文件 ...
}
}
}
}
这里利用了gradle生命周期的hook点来插入自己的代码。
这里是寻找Manifest文件,所以我们通过project对象找到了processManifestTask,从task在配置阶段已经确定的manifest文件路径,可以提前对manifest文件进行处理。也可以通过processManifestTask的实例方法获取已经合并过的manifest结果。(processManifestTask会将所有模块的Manifest文件进行合并)
理解Gradle的生命周期可以帮助我们更好的去理解gradle 的构建流程,实现自定义的项目构建,而hook点则是帮助我们的一个利器。
参考
Gradle官方文档:https://docs.gradle.org/current/userguide/build_lifecycle.html#sec:build_phases
Gradle基础 - 构建生命周期和Hook技术:https://www.jianshu.com/p/0acdb31eef2d
来源:oschina
链接:https://my.oschina.net/u/4386652/blog/4408096