Gradle構(gòu)建生命周期簡介和通用Maven打包腳本
Gradle構(gòu)建生命周期
Gradle構(gòu)建過程分為三個大的步驟:初始化昆淡、配置和執(zhí)行昂灵。
初始化
初始化階段的任務是根據(jù)settings.gradle
創(chuàng)建項目的層次結(jié)構(gòu),為每一個module
創(chuàng)建一個Project
實例管削。并且在初始化之前會構(gòu)造一個Settings對象撑螺,主要包含以下方法,可以直接在settings.gradle中訪問甘晤。
- findProject(File): ProjectDescriptor
- findProject(String): ProjectDescriptor
- getGradle(): Gradle
- getRootDir():File
- getRootProject(): ProjectDescriptor
- getSettings(): Settings
- project(File): ProjectDescriptor
- project(String): ProjectDescriptor
比如可以通過如下代碼向Gradle的構(gòu)建過程添加監(jiān)聽:
gradle.addBuildListener(new BuildListener() {
void buildStarted(Gradle var1) {
println '開始構(gòu)建'
}
void settingsEvaluated(Settings var1) {
println 'settings評估完成(settins.gradle中代碼執(zhí)行完畢)'
// var1.gradle.rootProject 這里訪問Project對象時會報錯线婚,還未完成Project的初始化
}
void projectsLoaded(Gradle var1) {
println '項目結(jié)構(gòu)加載完成(初始化階段結(jié)束)'
println '初始化結(jié)束,可訪問根項目:' + var1.gradle.rootProject
}
void projectsEvaluated(Gradle var1) {
println '所有項目評估完成(配置階段結(jié)束)'
}
void buildFinished(BuildResult var1) {
println '構(gòu)建結(jié)束 '
}
})
執(zhí)行結(jié)果如下:
settings評估完成(settins.gradle中代碼執(zhí)行完畢)
項目結(jié)構(gòu)加載完成(初始化階段結(jié)束)
初始化結(jié)束漱逸,可訪問根項目:root project 'GradleTest'
所有項目評估完成(配置階段結(jié)束)
:buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
No dependencies
BUILD SUCCESSFUL
Total time: 0.959 secs
構(gòu)建結(jié)束
配置
配置階段的任務是執(zhí)行各項目下的build.gradle
腳本虹脯,完成Project
的配置奏候,并且構(gòu)造Task任務依賴關(guān)系圖以便在執(zhí)行階段按照依賴關(guān)系執(zhí)行Task。該階段也是我們最常接觸到的構(gòu)建階段咒彤,比如應用外部構(gòu)建插件apply plugin: 'com.android.application'
咒精,配置插件的屬性android{...}等。每個build.gralde
腳本文件對應一個Project
對象歇拆,在初始化階段創(chuàng)建,Project
的接口文檔厂庇。配置階段執(zhí)行的代碼包括build.gralde
中的各種語句输吏、閉包以及Task中的配置段語句。
println 'build.gradle的配置階段'
// 調(diào)用Project的dependencies(Closure c)聲明項目依賴
dependencies {
// 閉包中執(zhí)行的代碼
println 'dependencies中執(zhí)行的代碼'
}
// 創(chuàng)建一個Task
task test() {
println 'Task中的配置代碼'
// 定義一個閉包
def a = {
println 'Task中的配置代碼2'
}
// 執(zhí)行閉包
a()
doFirst {
println '這段代碼配置階段不執(zhí)行'
}
}
println '我是順序執(zhí)行的'
調(diào)用gradle build拄氯,得到如下結(jié)果:
build.gradle的配置階段
dependencies中執(zhí)行的代碼
Task中的配置代碼
Task中的配置代碼2
我是順序執(zhí)行的
:buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
No dependencies
BUILD SUCCESSFUL
Total time: 1.144 secs
一定要注意它浅,配置階段不僅執(zhí)行build.gradle中的語句姐霍,還包括了Task中的配置語句。**從上面執(zhí)行結(jié)果中可以看到邮弹,在執(zhí)行了dependencies的閉包后腌乡,直接執(zhí)行的是任務test中的配置段代碼(Task中除了Action外的代碼段都在配置階段執(zhí)行)夜牡。
另外一點,無論執(zhí)行Gradle的任何命令急迂,初始化階段和配置階段的代碼都會被執(zhí)行蹦肴。
同樣是上面那段Gradle腳本,我們執(zhí)行幫助任務gradle help勺阐,任然會打印出上面的執(zhí)行結(jié)果矛双。我們在排查構(gòu)建速度問題的時候可以留意,是否部分代碼可以寫成任務Task懒闷,從而減少配置階段消耗的時間。
執(zhí)行
在配置階段結(jié)束后愤估,Gradle會根據(jù)任務Task的依賴關(guān)系創(chuàng)建一個有向無環(huán)圖,可以通過Gradle對象的getTaskGraph方法訪問织阅,對應的類為TaskExecutionGraph震捣,然后通過調(diào)用gradle <任務名>執(zhí)行對應任務蒿赢。
通用Maven打包上傳腳本
通常我們在開發(fā)中遇到的情況是lib模塊開發(fā)階段和需要打包階段的腳本配置方面有很大差別,所以一般的做法多為開發(fā)階段的lib模塊在需要上傳到Maven倉庫的時候羡棵,會有另外一個專用的項目來打包目標模塊和上傳皂冰,這個專用的模塊一般情況下是一個殼子,而且可能因為lib模塊在改動manifest文件或者BuildConfig參數(shù)的時候赂蕴,需要對應要做出修改
但是這樣做舶胀,往往意味著修改起來很麻煩,而且容易忘走贪。所以我們需要一個通用的打包腳本來處理這些情況。
所以思路就是不使用殼module,直接使用開發(fā)的lib模塊上傳到maven庫嗤瞎。而且考慮到歷史原因及其兼容啸盏,不能直接在lib模塊修改耿导,那么就只能在rootProject這個層級考慮做一些事情。
上面有講到Gradle在各個階段的任務醋火,同時,Gradle也提供了非常多的鉤子給開發(fā)者自定義構(gòu)建行為
由此可以看到柿冲,我們的目標很明確假抄,就是在lib模塊配置階段為我們注入一些我們需要的操作:移除開發(fā)階段的本地依賴丽猬、移除maven配置文件的本地依賴、添加本地依賴的maven版本依賴谬以。
//跟項目.gradle
allprojects {
repositories {
jcenter()
google()
afterEvaluate { project ->
if (project.name == 'gisdk') {
println '依賴maven插件:apply plugin maven for ' + project
project.apply from: "${rootProject.projectDir}/maven.gradle"
println "取消發(fā)布時debug版本的編譯"
project.android.publishNonDefault false
project.dependencies {
println '依賴現(xiàn)網(wǎng)模塊'
compile "xxx.xxx:xxx:${version}"
}
project.configurations {
println '排除本地依賴'
all*.exclude group: '${root_project_name}'
}
project.tasks.create(name: 'deleteKeepProguardRules') {
doFirst {
def path = "${project.projectDir}/build/intermediates/exploded-aar/com.xxx/xxx/${rootProject.ext.gtc.version}/proguard.txt"
def bFile = new File(path)
if (bFile.exists()) {
bFile.delete()
println '刪除keep文件成功'
} else {
println '文件不存在:' + path
}
}
}
project.tasks.whenTaskAdded { task ->
if (task.name == 'transformClassesAndResourcesWithProguardForRelease') {
task.dependsOn deleteKeepProguardRules
}
}
}
}
}
}
//maven.gradle
apply plugin: 'maven'
def mavenProps = rootProject.ext.maven // 配置
def getProjectVersion() {
def sdkProps = rootProject.ext.sdk // 配置
return sdkProps.version
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: mavenProps.url) {
authentication(userName: mavenProps.userName, password: mavenProps.pwd)
}
pom.groupId = mavenProps.groupId
pom.artifactId = project.name
pom.version = getProjectVersion() + mavenProps.snapshot
println '上傳的包:' + "${pom.groupId}:${pom.artifactId}:${pom.version}"
pom.whenConfigured { pom ->
def dependencies = []
pom.dependencies.each { dep ->
if (dep.version == 'unspecified') {
println "無效的依賴:${dep.groupId}:${dep.artifactId}:${dep.version}"
} else {
dependencies.add(dep)
}
}
pom.dependencies = dependencies
pom.dependencies.each { dep ->
println "最終的依賴:${dep.groupId}:${dep.artifactId}:${dep.version}"
}
}
}
}
}
至此,lib模塊就可以實現(xiàn)無侵入式的maven打包上傳能力