Gradle 是一個框架,它定義一套自己的游戲規(guī)則。我們要玩轉(zhuǎn) Gradle,必須要遵守它設(shè)計的規(guī)則。下面我們來講講 Gradle 的基本組件:
Gradle 中,每一個待編譯的工程都叫一個 Project。每一個 Project 在構(gòu)建的時候都包含一系列的 Task。比如一個 Android APK 的編譯可能包含:Java 源碼編譯 Task、資源編譯 Task、JNI 編譯 Task、lint 檢查 Task、打包生成 APK 的 Task、簽名 Task 等。
一個 Project 到底包含多少個 Task,其實是由編譯腳本指定的插件決定。插件是什么呢?插件就是用來定義 Task,并具體執(zhí)行這些 Task 的東西。
剛才說了,Gradle 是一個框架,作為框架,它負(fù)責(zé)定義流程和規(guī)則。而具體的編譯工作則是通過插件的方式來完成的。比如編譯 Java 有 Java 插件,編譯 Groovy 有 Groovy 插件,編譯 Android APP 有 Android APP 插件,編譯 Android Library 有 Android Library 插件
好了。到現(xiàn)在為止,你知道 Gradle 中每一個待編譯的工程都是一個 Project,一個具體的編譯過程是由一個一個的 Task 來定義和執(zhí)行的。
下面我們來看一個實際的例子。這個例子非常有代表意義。圖 22 是一個名為 posdevice 的目錄。這個目錄里包含 3 個 Android Library 工程,2 個 Android APP 工程。
http://wiki.jikexueyuan.com/project/deep-android-gradle/images/23.jpg" alt="" />
在圖 22 的例子中:
請回答問題,在上面這個例子中,有多少個 Project?
請回答問題,在上面這個例子中,有多少個 Project?
請回答問題,在上面這個例子中,有多少個 Project?
答案是:每一個 Library 和每一個 App 都是單獨(dú)的 Project。根據(jù) Gradle 的要求,每一個 Project 在其根目錄下都需要有一個 build.gradle。build.gradle 文件就是該 Project 的編譯腳本,類似于 Makefile。
看起來好像很簡單,但是請注意:posdevice 雖然包含 5 個獨(dú)立的 Project,但是要獨(dú)立編譯他們的話,得:
這很麻煩啊,有 10 個獨(dú)立 Project,就得重復(fù)執(zhí)行 10 次這樣的命令。更有甚者,所謂的獨(dú)立 Project 其實有依賴關(guān)系的。比如我們這個例子。
那么,我想在 posdevice 目錄下,直接執(zhí)行 gradle assemble,是否能把這 5 個 Project 的東西都編譯出來呢?
答案自然是可以。在 Gradle 中,這叫 Multi-Projects Build。把 posdevice 改造成支持 Gradle 的 Multi-Projects Build 很容易,需要:
來看 settings.gradle 的內(nèi)容,最關(guān)鍵的內(nèi)容就是告訴 Gradle 這個 multiprojects 包含哪些子 projects:
[settings.gradle]
//通過 include 函數(shù),將子 Project 的名字(其文件夾名)包含進(jìn)來
include 'CPosSystemSdk' , 'CPosDeviceSdk' ,
'CPosSdkDemo','CPosDeviceServerApk', 'CPosSystemSdkWizarPosImpl'
強(qiáng)烈建議:
如果你確實只有一個 Project 需要編譯,我也建議你在目錄下添加一個 settings.gradle。我們團(tuán)隊內(nèi)部的所有單個 Project 都已經(jīng)改成支持 Multiple-Project Build 了。改得方法就是添加 settings.gradle,然后 include 對應(yīng)的 project 名字。
另外,settings.gradle 除了可以 include 外,還可以設(shè)置一些函數(shù)。這些函數(shù)會在 gradle 構(gòu)建整個工程任務(wù)的時候執(zhí)行,所以,可以在 settings 做一些初始化的工作。比如:我的 settings.gradle 的內(nèi)容:
//定義一個名為 initMinshengGradleEnvironment 的函數(shù)。該函數(shù)內(nèi)部完成一些初始化操作
//比如創(chuàng)建特定的目錄,設(shè)置特定的參數(shù)等
def initMinshengGradleEnvironment(){
println "initialize Minsheng Gradle Environment ....."
......//干一些 special 的私活....
println "initialize Minsheng Gradle Environment completes..."
}
//settings.gradle 加載的時候,會執(zhí)行 initMinshengGradleEnvironment
initMinshengGradleEnvironment()
//include 也是一個函數(shù):
include 'CPosSystemSdk' , 'CPosDeviceSdk' ,
'CPosSdkDemo','CPosDeviceServerApk', 'CPosSystemSdkWizarPosImpl'
1.gradle projects 查看工程信息
到目前為止,我們了解了 Gradle 什么呢?
gradle 提供一些方便命令來查看和 Project,Task 相關(guān)的信息。比如在 posdevice 中,我想看這個 multi projects 到底包含多少個子 Project:
執(zhí)行 gradle projects,得到圖 23:
http://wiki.jikexueyuan.com/project/deep-android-gradle/images/24.jpg" alt="" />
你看,multi projects 的情況下,posdevice 這個目錄對應(yīng)的 build.gradle 叫 Root Project,它包含 5 個子 Project。
如果你修改 settings.gradle,使得 include 只有一個參數(shù),則 gradle projects 的子 project 也會變少,比如圖 24:
http://wiki.jikexueyuan.com/project/deep-android-gradle/images/25.jpg" alt="" />
2.gradle tasks 查看任務(wù)信息
查看了 Project 信息,這個還比較簡單,直接看 settings.gradle 也知道。那么 Project 包含哪些 Task 信息,怎么看呢?圖 23,24 中最后的輸出也告訴你了,想看某個 Project 包含哪些 Task 信息,只要執(zhí)行:
gradle project-path:tasks 就行。注意,project-path 是目錄名,后面必須跟冒號。
對于 Multi-project,在根目錄中,需要指定你想看哪個 poject 的任務(wù)。不過你要是已經(jīng) cd 到某個 Project 的目錄了,則不需指定 Project-path。
來看圖 25:
http://wiki.jikexueyuan.com/project/deep-android-gradle/images/26.jpg" alt="" />
圖 25 是 gradle CPosSystemSdk:tasks 的結(jié)果。
cd CPossystemSdk
gradle tasks 得到同樣的結(jié)果
CPosSystemSdk 是一個 Android Library 工程,Android Library 對應(yīng)的插件定義了好多 Task。每種插件定義的 Task 都不盡相同,這就是所謂的 Domain Specific,需要我們對相關(guān)領(lǐng)域有比較多的了解。
這些都是后話,我們以后會詳細(xì)介紹。
3.gradle task-name 執(zhí)行任務(wù)
圖 25 中列出了好多任務(wù),這時候就可以通過 gradle 任務(wù)名來執(zhí)行某個任務(wù)。這和 make xxx 很像。比如:
gradle clean 是執(zhí)行清理任務(wù),和 make clean 類似。
gradle tasks 會列出每個任務(wù)的描述,通過描述,我們大概能知道這些任務(wù)是干什么的.....。然后 gradle task-name 執(zhí)行它就好。
這里要強(qiáng)調(diào)一點(diǎn):Task 和 Task 之間往往是有關(guān)系的,這就是所謂的依賴關(guān)系。比如,assemble task 就依賴其他 task 先執(zhí)行,assemble 才能完成最終的輸出。
依賴關(guān)系對我們使用 gradle 有什么意義呢?
如果知道 Task 之間的依賴關(guān)系,那么開發(fā)者就可以添加一些定制化的 Task。比如我為 assemble 添加一個 SpecialTest 任務(wù),并指定 assemble 依賴于 SpecialTest。當(dāng) assemble 執(zhí)行的時候,就會先處理完它依賴的 task。自然,SpecialTest 就會得到執(zhí)行了... 大家先了解這么多,等后面介紹如何寫 gradle 腳本的時候,這就是調(diào)用幾個函數(shù)的事情,Nothing Special!