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