全面理解Gradle - 執行時序
什么是Gradle?
一個像 Ant 一樣的非常靈活的通用構建工具
一種可切換的, 像 maven 一樣的基于合約構建的框架
支持強大的多工程構建
支持強大的依賴管理(基于 ApacheIvy )
支持已有的 maven 和 ivy 倉庫
支持傳遞性依賴管理, 而不需要遠程倉庫或者 pom.xml 或者 ivy 配置文件
優先支持 Ant 式的任務和構建
基于 groovy 的構建腳本
有豐富的領域模型來描述你的構建
如何學習Gradle?
- 學習 Groovy( http://docs.groovy-lang.org/ )
- 學習 Gradle DSL( https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html )
- 學習 Android DSL和Task( http://google.github.io/android-gradle-dsl/current/index.html )
使用Gradle wrapper
如果你本地安裝了Gradle,那么你就可以使用gradle命令來直接構建。如果本地沒有安裝,那么可以通過gradle wrapper來構建,Linux和MAC使用./gradlew,而Windows上面則使用gradlew,還可以在 gradle/gradle-wrapper.properties 中配置 Gradle 版本。
Gradle腳本的執行時序
Gradle腳本的執行分為三個過程:
-
初始化
分析有哪些module將要被構建,為每個module創建對應的 project實例。這個時候settings.gradle文件會被解析。
-
配置:處理所有的模塊的 build 腳本,處理依賴,屬性等。這個時候每個模塊的build.gradle文件會被解析并配置,這個時候會構建整個task的鏈表(這里的鏈表僅僅指存在依賴關系的task的集合,不是數據結構的鏈表)。
-
執行:根據task鏈表來執行某一個特定的task,這個task所依賴的其他task都將會被提前執行。
下面我們根據一個實際的例子來詳細說明。這里我們仍然采用VirtualAPK這個開源項目來做演示,它的地址是: https://github.com/didi/VirtualAPK 。
我們以它的宿主端為例,宿主端有如下幾個模塊:

其實buildSrc是virtualapk-gradle-plugin,為了便于調試我將其重命名為buildSrc。他們的依賴關系如下:

解釋一下,app模塊依賴CoreLibrary和buildSrc,CoreLibrary又依賴AndroidStub。為了大家更好理解,下面加一下log。
/* Settings.gradle */
println "settings start"
include ':app'
include ':CoreLibrary'
include ':AndroidStub'
println "settings end"</code></pre>
/* VirtualAPK.gradle */
println "virtualapk start"
allprojects {
repositories {
mavenCentral()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
println "virtualapk end"</code></pre>
/* app.gradle */
println "app config start"
apply plugin: 'com.android.application'
apply plugin: 'com.didi.virtualapk.host'
dependencies {
compile project (":CoreLibrary")
}
project.afterEvaluate {
println "app evaluate start"
println "app evaluate end"
}
println "app config end"</code></pre>
/* CoreLibrary.gradle */
apply plugin: 'com.android.library'
println "corelib config start"
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
provided project(':AndroidStub')
}
apply from: 'upload.gradle'
println "corelib config end"</code></pre>
/* AndroidStub.gradle */
println "androidstub config start"
dependencies {
compile 'com.android.support:support-annotations:22.2.0'
}
println "androidstub config end"</code></pre>
/* buildSrc */
public class VAHostPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
println "VAHostPlugin config start"
project.afterEvaluate {
println "VAHostPlugin evaluate start"
project.android.applicationVariants.each { ApplicationVariant variant ->
generateDependencies(variant)
backupHostR(variant)
backupProguardMapping(variant)
}
println "VAHostPlugin evaluate end"
}
println "VAHostPlugin config end"
}
}</code></pre>
現在隨便執行一個task,比如 ./gradlew clean ,那么將會輸出如下日志,大家對比著日志,應該能明白Gradle腳本的執行順序了吧。
VirtualAPK renyugang$ ./gradlew clean
settings start
settings end
virtualapk start
virtualapk end
androidstub config start
androidstub config end
Incremental java compilation is an incubating feature.
corelib config start
corelib config end
app config start
VAHostPlugin config start
VAHostPlugin config end
app config end
VAHostPlugin evaluate start
VAHostPlugin evaluate end
app evaluate start
app evaluate end
:clean
:AndroidStub:clean
:CoreLibrary:clean
:app:clean
BUILD SUCCESSFUL
Total time: 12.381 secs</code></pre>
可以看到,Gradle執行的時候遵循如下順序:
1. 首先解析settings.gradle來獲取模塊信息,這是初始化階段;
2. 然后配置每個模塊,配置的時候并不會執行task;
3. 配置完了以后,有一個重要的回調 project.afterEvaluate ,它表示所有的模塊都已經配置完了,可以準備執行task了;
4. 執行指定的task。
備注:如果注冊了多個 project.afterEvaluate 回調,那么執行順序等同于注冊順序。在上面的例子中,由于buildSrc中的回調注冊較早,所以它也先執行。
來自:http://blog.csdn.net/singwhatiwanna/article/details/78797506