在語法上是基於Groovy語言的(Groovy 是一種基於JVM的敏捷開發語言,能夠簡單的理解爲強類型語言java的弱類型版本),在項目管理上是基於Ant和Maven概念的項目自動化建構工具。html
Java基礎,命令行使用基礎
官方文檔:https://docs.gradle.org/current/dsl/
** Gradle使用指南:** https://gradle.org/docs/current/userguide/userguide
Android插件文檔:https://github.com/google/android-gradle...
AndroidGradle使用文檔:http://tools.android.com/tech-docs/new-build-system/user-guide
Groovy基礎: http://attis-wong-163-com.iteye.com/blog/1239819
Groovy閉包的Delegate機制:http://www.cnblogs.com/davenkin/p/gradle-learning-3.htmljava
MacOS 下配置。在~/.bash_profile
中添加以下代碼linux
#gradle 注意gradle-2.14.1是本身解壓的路徑 export GRADLE_HOME=${HOME}/gradle-2.14.1 PATH=${PATH}:${GRADLE_HOME}/bin export PATH
保存後在終端輸入source ~/.bash_profile
回車執行讓剛剛的配置生效。而後命令行輸入gradle -v
查看是否安裝成功。android
$ gradle -v ------------------------------------------------------------ Gradle 2.14.1 ------------------------------------------------------------ Build time: 2016-07-18 06:38:37 UTC Revision: d9e2113d9fb05a5caabba61798bdb8dfdca83719 Groovy: 2.4.4 Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015 JVM: 1.8.0_111 (Oracle Corporation 25.111-b14) OS: Mac OS X 10.12.2 x86_64
建立一個test_gralde
文件夾。而後在文件夾裏面建立一個build.gradle
文件。注意文件名不要亂起。在build.gradle
中添加以下代碼:git
task helloworld{ doLast{ println'Hello World!' } } #後者等同於下面的代碼, task helloworld2 <<{ println "Hello World!" }
而後來運行一下:程序員
liuqiangs-MacBook-Pro:test_gralde liuqiang$ gradle helloworld :helloworld Hello World! BUILD SUCCESSFUL Total time: 1.52 secs This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.14.1/userguide/gradle_daemon.html
咱們分析一下執行步驟。build.gradle是Gradle默認的構建腳本文件,執行Gradle命令的時候,會默認加載當前目錄下的build.gradle腳本文件,固然你也能夠經過 -b 參數指定想要加載執行的文件。這只是個最簡單的task例子,後面詳細介紹task的常見定義。github
這個構建腳本定義一個任務(Task),任務名字叫helloworld,而且給任務helloworld添加了一個動做,官方名字是Action,閱讀Gradle源代碼你會處處見到它,其實他就是一段Groovy語言實現的閉包,doLast就意味着在Task執行完畢以後要回調doLast的這部分閉包的代碼實現。第二個方法中的「<<」表示向helloworld中加入執行代碼。至於語法部分,基本是Groovy語法(包括一些語法糖,也就是寫簡寫方式,若是寫個JavaScript或者Python會好理解一些,可是仍是建議去讀一下groovy的基本語法),加上一些DSL(domain specific language)的約定。shell
和Maven同樣,Gradle只是提供了構建項目的一個框架,真正起做用的是Plugin。Gradle在默認狀況下爲咱們提供了許多經常使用的Plugin,其中包括有構建Java項目的Plugin,還有Android等。與Maven不一樣的是,Gradle不提供內建的項目生命週期管理,只是java Plugin向Project中添加了許多Task,這些Task依次執行,爲咱們營造了一種如同Maven般項目構建週期。bash
Gradle是一種聲明式的構建工具。在執行時,Gradle並不會一開始便順序執行build.gradle文件中的內容,而是分爲兩個階段,第一個階段是配置階段,而後纔是實際的執行階段。
配置階段,Gradle將讀取全部build.gradle文件的全部內容來配置Project和Task等,好比設置Project和Task的Property,處理Task之間的依賴關係等。閉包
看一個基本結構的Android多Moudule(也就是gradle中的多Project Multi-Projects Build)的基本項目結構。
├── app #Android App目錄 │ ├── app.iml │ ├── build #構建輸出目錄 │ ├── build.gradle #構建腳本 │ ├── libs #so相關庫 │ ├── proguard-rules.pro #proguard混淆配置 │ └── src #源代碼,資源等 ├── module #Android 另一個module目錄 │ ├── module.iml │ ├── build #構建輸出目錄 │ ├── build.gradle #構建腳本 │ ├── libs #so相關庫 │ ├── proguard-rules.pro #proguard混淆配置 │ └── src #源代碼,資源等 ├── build │ └── intermediates ├── build.gradle #工程構建文件 ├── gradle │ └── wrapper ├── gradle.properties #gradle的配置 ├── gradlew #gradle wrapper linux shell腳本 ├── gradlew.bat ├── LibSqlite.iml ├── local.properties #配置Androod SDK位置文件 └── settings.gradle #工程配置
上面的是完整的AndroidStudio中的項目結構,咱們抽象成Gradle多個Project的樣子
├── app │ ├── build.gradle #構建腳本 ├── module │ ├── build.gradle #構建腳本 ├── build.gradle #工程構建文件 ├── gradle │ └── wrapper #先不去管它 ├── gradle.properties #gradle的配置 ├── gradlew #gradle wrapper linux shell腳本 ├── gradlew.bat └── settings.gradle #工程配置
Gradle向咱們提供了一整套DSL,因此在不少時候咱們寫的代碼彷佛已經脫離了groovy,可是在底層依然是執行的groovy因此不少語法仍是Groovy的語法規則。
看一個AndroidStudio中app下的build.gradle的配置
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.0" defaultConfig { applicationId "me.febsky.demo" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.1.0' }
apply plugin: 'com.android.application'
這句實際上是Groovy語法糖,像Ruby和Js都有這種語法糖,apply其實是個方法,補上括號後的腳本:apply (plugin: 'com.android.application')
,看起來仍是有點彆扭是不?還有個語法糖,若是方法參數是個map類型,那麼方括號能夠省略,進一步還原apply([ plugin: 'com.android.application'])
,不理解的能夠去看下Groovy的map的寫法,和js同樣。因此這行的意思是:apply實際上是個方法,接收一個Map類型的參數。
總結兩點:1. 方法調用,圓括號能夠省略 2. 若是方法參數是個Map,方括號能夠省略。
看上面的dependencies
這實際上是個方法調用。調用了Project的dependencies方法。只不過參數是個閉包,閉包的用法在文章開始給出了連接。咱們對其進行還原一下:
#方法調用省略了()咱們加上 dependencies ({ compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.1.0' })
提示一點:若是閉包是方法的最後一個參數,那麼閉包能夠放在圓括號外面
#因此代碼還能寫成這樣 dependencies (){ compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.1.0' }
Groovy語言中的兩個概念,一個是Groovy中的Bean概念,一個是Groovy閉包的Delegate機制。
Java程序員對JavaBeans和Getter/Setter方法確定不陌生,被設計用來獲取/設置類的屬性。但在Groovy中就不用那些沒用的方法了。即Groovy動態的爲每個字段都會自動生成getter和setter,而且咱們能夠經過像訪問字段自己同樣調用getter和setter。好比Gradle的Project對象有個version屬性(Property)下面這兩行代碼執行結果是同樣的:
println project.version // Groovy println(project.getVersion()) // Java
Gradle的Project之間的依賴關係是基於Task的,而不是整個Project的。
Project:是Gradle最重要的一個領域對象,咱們寫的build.gradle腳本的所有做用,其實就是配置一個Project實例。在build.gradle腳本里,咱們能夠隱式的操縱Project實例,好比,apply插件、聲明依賴、定義Task等,如上面build.gradle
所示。apply、dependencies、task等其實是Project的方法,參數是一個代碼塊。若是須要,也能夠顯示的操縱Project實例,好比:project.ext.myProp = 'myValue'
Task:被組織成了一個有向無環圖(DAG)。Gradle中的Task要麼是由不一樣的Plugin引入的,要麼是咱們本身在build.gradle文件中直接建立的。Gradle保證Task按照依賴順序執行,而且每一個Task最多隻被執行一次。
Gradle在默認狀況下爲咱們提供了幾個經常使用的Task,好比查看Project的Properties、顯示當前Project中定義的全部Task等。能夠經過一下命令行查看Project中全部的Task:$ gradle tasks
(具體log再也不貼出來)。能夠看到,Gradle默認爲咱們提供了dependencies、projects和properties
等Task。dependencies用於顯示Project的依賴信息,projects用於顯示全部Project,包括根Project和子Project,而properties則用於顯示一個Project所包含的全部Property。
**Tips: **查看Project中全部的Task:
$ gradle tasks
查看Project中全部的properties:$ gradle properties
在上面的build.gradle
中加入以下代碼:
task myTask { doFirst { println 'hello' } doLast { println 'world' } }
這段代碼的含義:給Project添加一個名爲「myTask」的任務
用一個閉包來配置這個任務,Task提供了doFirst和doLast方法來給本身添加Action。
其實build.gradle腳本的真正做用,就是配置一個Project實例。在執行build腳本以前,Gradle會爲咱們準備好一個Project實例,執行完腳本以後,Gradle會按照DAG依次執行任務。
看下面代碼文件路徑~/Test/build.gradle
:
#1 task helloWorld << { println "Hello World" } #2 Test文件夾下建一個src目錄,建一個dst目錄,src目錄下創建一個文件,命名爲test.txt task copyFile(type: Copy){ from "src" into "dst" }
第一個這裏的helloWorld是一個DefaultTask類型的對象,這也是定義一個Task時的默認類型,固然咱們也能夠顯式地聲明Task的類型,甚至能夠自定義一個Task類型。
第二個代碼中(type:Copy)就是「顯式地聲明Task的類型」,執行gradle copyFile
test.txt也跑到dst中去了。
若是task聲明在根Project的build.gradle中的allprojects()方法中,那麼這個Task會應用於全部的Project。
Gradle不提供內建的項目生命週期管理,只是java Plugin向Project中添加了許多Task,這些Task依次執行,爲咱們營造了一種如同Maven般項目構建週期。那麼這些task是如何依次執行的這就用到聲明的依賴關係taskA.dependsOn taskB
看下面代碼:
task taskA << { println 'this is taskA from project 1' } task taskB << { println 'this is taskB from project 1' } taskA.dependsOn taskB
而後咱們在命令行運行:
$ gradle taskA
運行結果會先執行taskB的打印,而後執行taskA的打印
若是是Muliti-Project的模式,依賴關係要帶着所屬的Project,如
taskA.dependsOn ':other-project:taskC'
其中taskC位於和taskA不一樣的Project中,相對於AndroidStudio來講,就是位於不一樣的Module下的build.gradle
中,而other-project爲Module名字。
沒有深刻研究,給出一個網上的例子:
apply plugin: DateAndTimePlugin dateAndTime { timeFormat = 'HH:mm:ss.SSS' dateFormat = 'MM/dd/yyyy' } class DateAndTimePlugin implements Plugin<Project> { //該接口定義了一個apply()方法,在該方法中,咱們能夠操做Project, //好比向其中加入Task,定義額外的Property等。 void apply(Project project) { project.extensions.create("dateAndTime", DateAndTimePluginExtension) project.task('showTime') << { println "Current time is " + new Date().format(project.dateAndTime.timeFormat) } project.tasks.create('showDate') << { println "Current date is " + new Date().format(project.dateAndTime.dateFormat) } } } //每一個Gradle的Project都維護了一個ExtenionContainer, //咱們能夠經過project.extentions進行訪問 //好比讀取額外的Property和定義額外的Property等。 //向Project中定義了一個名爲dateAndTime的extension //並向其中加入了2個Property,分別爲timeFormat和dateFormat class DateAndTimePluginExtension { String timeFormat = "MM/dd/yyyyHH:mm:ss.SSS" String dateFormat = "yyyy-MM-dd" }
每個自定義的Plugin都須要實現Plugin接口,除了給Project編寫Plugin以外,咱們還能夠爲其餘Gradle類編寫Plugin。該接口定義了一個apply()方法,在該方法中,咱們能夠操做Project,好比向其中加入Task,定義額外的Property等。
Wrapper,顧名思義,其實就是對Gradle的一層包裝,便於在團隊開發過程當中統一Gradle構建的版本,而後提交到git上,而後別人能夠下載下來,這樣你們均可以使用統一的Gradle版本進行構建,避免由於Gradle版本不統一帶來的沒必要要的問題。(因此要明白這個東西能夠沒有,有了只是爲了統一管理,更加方便)
gradle 內置了生成wrapper的task,咱們能夠命令行下執行:
$ gradle wrapper
生成後的目錄結構以下(用過AndroidStudio的很熟悉了):
├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew └── gradlew.bat
$ ./gradlew myTask
#Sat Jan 21 14:02:40 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
從上面內容和文件的名稱均可以看出,這就是個java的配置文件,上面看到的是自動生成的,咱們也能夠手動修改。而後看下各個字段的含義:
gradle wrapper –gradle-version 2.14
這樣,這樣就意味着咱們配置wrapper使用2.14版本的gradle,它會影響gradle-wrapper.properties中的distributionUrl的值,該值的規則是http://services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip【參考文章】
http://www.infoq.com/cn/articles/android-in-depth-gradle/
http://blog.csdn.net/innost/article/details/48228651
做者:奮鬥der小鳥 連接:https://www.jianshu.com/p/001abe1d8e95 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。