Gradle系列(二):Gradle初步

Gradle簡介

Gradle是一個構建工具,同時它也是一個編程框架凰荚。

  • 當你把Gradle當構建工具看的時候,我們只想著如何用好它褒脯。會寫便瑟、寫好配置腳本就OK。

構建番川,叫build也好到涂,叫make也行脊框。反正就是根據(jù)輸入信息然后干一堆事情,最后得到幾個產(chǎn)出物(Artifact)践啄。
最最簡單的構建工具就是make了浇雹。make就是根據(jù)Makefile文件中寫的規(guī)則,執(zhí)行對應的命令屿讽,然后得到目標產(chǎn)物昭灵。
日常生活中,和構建最類似的一個場景就是做菜伐谈。輸入各種食材烂完,然后按固定的工序,最后得到一盤菜诵棵。當然窜护,做同樣一道菜,由于需求不同非春,做出來的東西也不盡相同柱徙。比如,宮保雞丁這道菜奇昙,回民要求不能放大油护侮、口淡的要求少放鹽和各種油、辣不怕的男女漢子們可以要求多放辣子....總之储耐,做菜包含固定的工序羊初,但是對于不同條件或需求,需要做不同的處理什湘。
在Gradle爆紅之前长赞,常用的構建工具是ANT,然后又進化到Maven闽撤。ANT和Maven這兩個工具其實也還算方便得哆,現(xiàn)在還有很多地方在使用。但是二者都有一些缺點哟旗,所以讓更懶得人覺得不是那么方便贩据。比如,Maven編譯規(guī)則是用XML來編寫的闸餐。XML雖然通俗易懂饱亮,但是很難在xml中描述if{某條件成立,編譯某文件}/else{編譯其他文件}這樣有不同條件的任務舍沙。
Gradle中近上,每一個待編譯的工程都叫一個Project。
每一個Project在構建的時候都包含一系列的Task拂铡。比如一個Android APK的編譯可能包含:Java源碼編譯Task壹无、資源編譯Task葱绒、JNI編譯Task、lint檢查Task格遭、打包生成APK的Task哈街、簽名Task等

  • 當你把Gradle當做編程框架看的時候拒迅,你可能需要學習很多更深入的內(nèi)容骚秦。

Gradle作為框架,負責定義流程和規(guī)則璧微。而具體的編譯工作則是通過插件(Plugin)的方式來完成的作箍,插件就是用來定義Task,并具體執(zhí)行這些Task的東西前硫。
比如編譯Java有Java插件胞得,編譯Groovy有Groovy插件,編譯Android APP有Android APP插件屹电,編譯Android Library有Android Library插件阶剑。

Gradle編程框架的問題放在最后講解,在此之前危号,先講以下內(nèi)容:

Android Plugin for Gradle—— 應用于Gradle的Android插件

Reference:
https://developer.android.com/studio/releases/gradle-plugin.html?hl=zh-cn#updating-plugin
首先牧愁,根據(jù)以上鏈接中對Android插件的介紹,做一個簡要的翻譯:

Android Studio的構建系統(tǒng)基于Gradle外莲,同時猪半,應?用于Gradle的Android插件又專門為構建Android App增加了若干特性。雖然Android插件與Android Studio保持同步更新偷线,但是該插件依然能夠獨立于Android Studio使用磨确,且可獨立更新。

對于Android項目声邦,在項目的根目錄的build.gradle 文件(即乏奥,Application級別的build.gradle文件),里面有這么一句代碼:

classpath 'com.android.tools.build:gradle:2.2.0'

這行代碼就表示翔忽,該Android項目構建過程本身需要依賴Android Plugin for Gradle英融,后面的版本號代表就是需依賴該插件的2.2.0這個版本。
注意歇式,不是 Gradle 的版本喲,這個插件是 Google 搞的胡野,跟 Gradle 官方?jīng)]關系材失。

Gradle Wrapper

  • Google 推出的 Gradle Wrapper ,它會在你的每個項目中都配置一個指定版本的 Gradle硫豆,你可以理解為每個 Android 項目本地都有一個小型的 Gradle 龙巨,通過Gradle Wrapper來支持每個項目可以用不同的 Gradle 版本來進行構建笼呆。

  • Gradle is a tool that is under constant development, and new versions could potentially break backward compatibility.

  • Using the Gradle Wrapper is a good way to avoid issues and to make sure builds are reproducible.

  • The Gradle Wrapper provides a batch file on Microsoft Windows and a shell script on other operating systems. When you run the script, the required version of Gradle is downloaded (if it is not present yet) and used automatically for the build.

  • The idea behind this is that every developer or automated system that needs to build the app can just run the wrapper, which will then take care of the rest.This way, it is not required to manually install the correct version of Gradle on a developer machine or build server.

  • Therefore, it is also recommended to add the wrapper files to your version control system.

  • 輸出Gradle版本號和其他信息。

./gradlew -v
./gradlew -v

tasks

  • 列出所有可用的tasks
    This will print out a list of all the available tasks. If you add the --all parameter, you will get a more detailed overview with the dependencies for every task.
./gradlew tasks
./gradlew tasks
  • assemble task with the debug configuration
    This task will create an APK with the debug version of the app. By default, the Android plugin for Gradle saves the APK in the directory MyApp/app/build/ outputs/apk.
./gradlew assembleDebug

這里要強調(diào)一點:Task和Task之間往往是有關系的旨别,這就是所謂的依賴關系诗赌。
比如,assemble task就依賴其他task先執(zhí)行秸弛,assemble才能完成最終的輸出铭若。

settings.gradle

settings.gradle中的內(nèi)容,最關鍵的就是告訴Gradle這個multi-projects包含哪些子projects递览。
如果你確實只有一個Project需要編譯叼屠,也建議你在目錄下添加一個settings.gradle,然后include對應的project名字绞铃。
另外镜雨,settings.gradle除了可以include外,還可以設置一些函數(shù)儿捧。這些函數(shù)會在gradle構建整個工程任務的時候執(zhí)行荚坞,所以,可以在settings做一些初始化的工作菲盾。比如:

//定義一個名為initMinshengGradleEnvironment的函數(shù)颓影。該函數(shù)內(nèi)部完成一些初始化操作
//比如創(chuàng)建特定的目錄,設置特定的參數(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' 

The settings file is executed during the initialization phase, and defines which modules should be included in the build. In this example, the app module is included. Single module projects do not necessarily require a settings file, but multi-module projects do; otherwise, Gradle does not know which modules to include.

build.gradle

每一個Library和每一個App都是單獨的Project瞭空。根據(jù)Gradle的要求,每一個Project在其根目錄下都需要有一個build.gradle疗我。
build.gradle文件就是該Project的編譯腳本咆畏,類似于Makefile。

  • The top-level build.gradle file is where you can configure options that need to be applied to all the modules in the project. It contains two blocks by default:
buildscript { 
  repositories {
    jcenter()
  }
  dependencies { 
    classpath 'com.android.tools.build:gradle:1.2.3'
  }
}
allprojects { 
  repositories {
     jcenter()
  }
}

基本的Gradle命令

gradle projects #查看工程信息吴裤,比如想看一個multi-projects到底包含多少個子Project旧找,跟settings.gradle中include的project有關
 gradle tasks #查看任務信息
gradle task-name #執(zhí)行名為task-name的任務,
#比如:gradle clean執(zhí)行清理任務麦牺,gradle properites查看所有屬性信息

先順便寫這么幾個吧钮蛛,之后再不斷補充....

構建的生命周期(Build Lifecycle)

執(zhí)行Gradle build,就是在task上執(zhí)行各種actions剖膳,而一個task可能又依賴其他task魏颓,task的執(zhí)行流程是有向非循環(huán)圖
Gradle build有三個階段:

  1. 初始化階段 Initialization
    Gradle有一個初始化流程吱晒,這個時候settings.gradle會執(zhí)行甸饱。
    This is where the Project instance is created. If there are multiple modules, each with their own build.gradle file, multiple projects will be created.
  2. 配置階段 Configuration
    在配置階段,每個Project都會被解析,其內(nèi)部的task也會被添加到一個有向圖里叹话,用于解決執(zhí)行過程中的依賴關系偷遗。
    Configuration階段完了后,整個build的project以及內(nèi)部的Task關系就確定了驼壶。
    一個Project包含很多Task氏豌,每個Task之間有依賴關系。Configuration會建立一個有向圖來描述Task之間的依賴關系热凹。
    In this phase, the build scripts are executed, creating and configuring all the tasks for every project object.
  3. 執(zhí)行階段 Execution
    你在gradle xxx中指定了xxx任務泵喘,gradle就會將這個xxx任務鏈上的所有任務全部按依賴順序執(zhí)行一遍。
    This is the phase where Gradle determines which tasks should be executed. Which tasks should be executed depends on the arguments passed for starting the build and what the current directory is.

好碌嘀,接下來將Gradle作為一種編程框架來講解:

Gradle框架與常用API

Gradle基于Groovy涣旨,Groovy又基于Java。所以股冗,Gradle執(zhí)行的時候和Groovy一樣,會把腳本轉換成Java對象止状。

基本

Gradle主要有三種對象烹棉,這三種對象和三種不同的腳本文件對應,在gradle執(zhí)行的時候怯疤,會將腳本轉換成對應的對象:

Type of script Delegates to instance of
init script Gradle
build script Project
settings script Settings
  • Gradle對象:當我們執(zhí)行gradle xxx的時候浆洗,gradle會從默認的配置腳本中構造出一個Gradle對象。在整個執(zhí)行過程中集峦,只有這么一個對象伏社。Gradle對象的數(shù)據(jù)類型就是Gradle。我們一般很少去定制這個默認的配置腳本塔淤。
  • Project對象:每一個build.gradle會轉換成一個Project對象摘昌。
    apply是一個函數(shù)。
    注意高蜂,Groovy支持函數(shù)調(diào)用的時候通過
參數(shù)名1:參數(shù)值2, 參數(shù)名2:參數(shù)值2 

的方式來傳遞參數(shù)聪黎,比如:

apply plugin: 'com.android.library'    #如果是編譯Library,則加載此插件
apply plugin: 'com.android.application'  #如果是編譯Android APP备恤,則加載此插件

除了加載二進制的插件(上面的插件其實都是下載了對應的jar包稿饰,這也是通常意義上我們所理解的插件),還可以加載一個gradle文件露泊。為什么要加載gradle文件呢喉镰?

  • Settings對象:每一個settings.gradle都會轉換成一個Settings對象。
  • Script:除了以上三個對象之外惭笑,每個Gradle腳本都實現(xiàn)Script接口梧喷。

build script

A build script is made up of zero or more statements and script blocks.
Statements can include method calls, property assignments, and local variable definitions.
A script block is a method call which takes a closure as a parameter. The closure is treated as a configuration closure which configures some delegate object as it executes.
The top level script blocks are listed below.

allprojects { }

Configures this project and each of its sub-projects.

artifacts { }

Configures the published artifacts for this project.

buildscript { }

Configures the build script classpath for this project.

configurations { }

Configures the dependency configurations for this project.

dependencies { }

Configures the dependencies for this project.

repositories { }

Configures the repositories for this project.

sourceSets { }

Configures the source sets of this project.

subprojects { }

Configures the sub-projects of this project.

publishing { }

Configures the PublishingExtension
added by the publishing plugin.

舉個栗子

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {    //為整個Project配置build script的classpath,旭神:項目編譯需要的
  repositories {       
    jcenter()   
  }    
  dependencies {        
    classpath 'com.android.tools.build:gradle:2.2.0'     //gradle plugin的版本  
      // NOTE: Do not place your application dependencies here; they belong        
     // in the individual module build.gradle files    
  }
}

allprojects {   //Configures this project and each of its sub-projects. 
  repositories {        
    jcenter()    
  }
}

task clean(type: Delete) {    //創(chuàng)建名為clean的task,并且這個clean task是從Delete這個task派生出來的
  delete rootProject.buildDir
}

在以上栗子中脖咐,關于task做幾點說明:
1.Task是Gradle中的一種數(shù)據(jù)類型铺敌,它代表了一些要執(zhí)行或者要干的工作。不同的插件可以添加不同的Task屁擅。每一個Task都需要和一個Project關聯(lián)偿凭。
2.Task的API文檔位于:
https://docs.gradle.org/current/dsl/org.gradle.api.Task.html
3.語法方面:利用Project的task()函數(shù)新建一個task派歌,這個task的名字叫clean弯囊,關于task的創(chuàng)建,有如下幾種形式:

//Task是和Project關聯(lián)的胶果,所以匾嘱,我們要利用Project的task函數(shù)來創(chuàng)建一個Task  
task myTask  //myTask是新建Task的名字  
task myTask { configure closure }  
task myType << { task action }  //注意,<<符號是doLast的縮寫 
task myTask(type: SomeType)  
task myTask(type: SomeType) { configure closure } 

在上面幾種形式中:

  • 一個Task包含若干Action早抠。所以霎烙,Task有doFirst和doLast兩個函數(shù),用于添加需要最先執(zhí)行的Action蕊连,和需要最后執(zhí)行的Action悬垃。Action就是一個閉包。
  • Task創(chuàng)建的時候可以指定Type甘苍,通過type:名字表達尝蠕。這是什么意思呢?其實就是告訴Gradle载庭,這個新建的Task對象會從哪個基類Task派生看彼。比如,Gradle本身提供了一些通用的Task囚聚,?比如Delete靖榕,Delete是Gradle中的一個類。當我們:task myTask(type:Delete)的時候靡挥,創(chuàng)建的Task就是一個Delete Task序矩。
  • 當我們使用 task myTask{xxx}的時候“掀疲花括號是一個closure簸淀。這會導致gradle在創(chuàng)建這個Task之后,返回給用戶之前毒返,會先執(zhí)行closure的內(nèi)容租幕。
  • 當我們使用task myTask << {xxx}的時候,我們創(chuàng)建了一個Task對象拧簸,同時把closure做為一個action加到這個Task的action隊列中劲绪,并且告訴它“最后才執(zhí)行這個closure”(注意,<<符號是doLast的代表)。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贾富,一起剝皮案震驚了整個濱河市歉眷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颤枪,老刑警劉巖汗捡,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異畏纲,居然都是意外死亡扇住,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門盗胀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艘蹋,“玉大人,你說我怎么就攤上這事票灰∨В” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵米间,是天一觀的道長强品。 經(jīng)常有香客問我灿椅,道長愉耙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任谨究,我火速辦了婚禮逻锐,結果婚禮上夫晌,老公的妹妹穿的比我還像新娘。我一直安慰自己昧诱,他們只是感情好晓淀,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盏档,像睡著了一般凶掰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜈亩,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天懦窘,我揣著相機與錄音,去河邊找鬼稚配。 笑死畅涂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的道川。 我是一名探鬼主播午衰,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼立宜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了臊岸?” 一聲冷哼從身側響起橙数,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扇单,沒想到半個月后商模,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蜘澜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了响疚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鄙信。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖忿晕,靈堂內(nèi)的尸體忽然破棺而出装诡,到底是詐尸還是另有隱情,我是刑警寧澤践盼,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布鸦采,位于F島的核電站,受9級特大地震影響咕幻,放射性物質(zhì)發(fā)生泄漏渔伯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一肄程、第九天 我趴在偏房一處隱蔽的房頂上張望锣吼。 院中可真熱鬧,春花似錦蓝厌、人聲如沸玄叠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽读恃。三九已至,卻和暖如春代态,著一層夾襖步出監(jiān)牢的瞬間寺惫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工胆数, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肌蜻,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓必尼,卻偏偏與公主長得像蒋搜,于是被迫代替她去往敵國和親篡撵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,777評論 25 707
  • afinalAfinal是一個android的ioc豆挽,orm框架 https://github.com/yangf...
    passiontim閱讀 15,410評論 2 45
  • Gradle是基于Groovy的動態(tài)DSL育谬,而Groovy是基于JVM的,Groovy的語法和Java很類似帮哈。 C...
    HoooChan閱讀 7,452評論 0 7
  • 在西安待的這幾天真是長見識了娘侍,以前我對西安的了解就是黃土高坡咖刃,每天刮黃沙,很破很舊憾筏,我來了后發(fā)現(xiàn)自己孤陋寡聞啦……...
    Anna娜閱讀 316評論 0 1
  • 小劉同學是一個重點大學的一年級生嚎杨,初入大學,感受到了很大的自由空間氧腰,可以做很多自己喜歡的事情枫浙。于是她參加社團、...
    刀刀超幸運閱讀 351評論 0 8