項目與腳本文件html
當咱們執行gradle
命令的時候,Gradle會在你執行命令的目錄下尋找一個名爲build.gradle
的文件,這個文件就是Gradle的腳本文件,咱們全部的腳本、配置信息都寫在這裏面,而且一個目錄下只能有一個腳本文件。java
腳本塊android
一個build.gradle文件由若干個指定的腳本塊組成,每個腳本塊都表明着不一樣的功能,Gradle內置了好幾種腳本塊供咱們使用,而且腳本塊能夠嵌套使用,詳情能夠查看官方文檔,咱們來看一段腳本:網絡
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' } } allprojects { repositories { jcenter() } }
buildscripte
腳本塊指定腳本文件所使用的插件來源和遠程倉庫app
repositories
腳本塊指定了所使用的遠程倉庫框架
dependencies
指定了相關的依賴關係maven
allprojects
腳本塊爲全部子項目指定配置信息。ide
在Gradle中,每個項目都會有個名爲project
的實例與之對應,而以前咱們說過一個腳本文件就表明着一個項目,因此實際上咱們在腳本文件中編寫的腳本最後都是委託給project
對象處理的,即project
和build.gradle
是一對一的關係。咱們能夠在腳本文件中經過該實例訪問項目腳本的屬性、方法和任務,例如project.name
能夠訪問項目的名稱、project.version
能夠訪問項目的版本名稱、project.rootProject
能夠訪問該項目的父項目等,總之project
幾乎包含了全部腳本的內容。測試
在編寫腳本的時候,雖然在腳本中直接寫屬性名稱是能夠的,可是經過
project
引用屬性名稱可以讓你的腳本更加清晰易懂,例如project.name
會比name
更容易讓人知道這是一個項目的名稱。gradle
在Gradle中,屬性分爲兩種,一種是系統屬性,它能夠被JVM使用,而另外一種咱們姑且稱之爲項目屬性,它用於項目的配置。
系統屬性是能夠直接被JVM所使用的,咱們能夠用它來設置JVM的相關參數,下面按照讀取屬性的優先級由高到低的方式列出來全部定義方式:
經過命令行執行gradle -D name=value
方式定義系統屬性,例如gradle -D org.gradle.java.home=/jdk
定義了Gradle運行時所依賴的Java路徑。
在用戶目錄下建立gradle.properties
文件,而後以systemProp.name=value
方式定義系統屬性,例如用戶目錄爲/home/jerry
,那麼咱們就在該目錄下建立gradle.properties
文件,而且在文件內定義org.gradle.java.home=/jdk
,這樣Gradle因此需的Java路徑就被定義了。
在項目目錄下建立gradle.properties
文件,而後以systemProp.name=value
方式定義系統屬性,例如項目目錄爲/HelloGradle
,那麼咱們就在該目錄下建立gradle.properties
文件,而且在文件內定義org.gradle.java.home=/jdk
,這樣Gradle因此需的Java路徑就被定義了。
在開發項目的時候咱們常常會遇到各類項目屬性的配置,例如項目名稱、項目版本、打包路徑、渠道名稱等等,對於這些屬性,Gradle爲咱們提供了多種方式來定義,下面按照讀取屬性的優先級由高到低列出來全部定義方式:
經過project.ext.name=value
方式定義屬性,例如project.ext.channel='360'
定義渠道名稱爲360。
經過命令行執行gradle -P name=value
方式定義屬性,例如gradle -P channel=360
定義渠道名稱爲360。
在用戶目錄下建立gradle.properties
文件,而後以name=value
方式定義系統屬性,例如用戶目錄爲/home/jerry
,那麼咱們就在該目錄下建立gradle.properties
文件,而且在文件內定義channel=360
,這樣就定義了渠道名爲360。
在項目目錄下建立gradle.properties
文件,而後以name=value
方式定義系統屬性,例如項目目錄爲/HelloGradle
,那麼咱們就在該目錄下建立gradle.properties
文件,而且在文件內定義channel=360
,這樣就定義了渠道名爲360。
在腳本中讀取屬性十分容易,對於系統屬性,咱們能夠經過System.properties['name']
方式讀取,對於項目屬性則經過project.name
方式讀取:
build.gradle:
println System.properties['org.gradle.java.home'] println project.channel
在構建項目的時候,咱們若是對整個構建過程進行分解的話,大概能夠分解成編譯代碼、打包、生成文檔等過程,Gradle用task來表明這些構建過程,每一個步驟對應一個task。若是把項目比喻成一個類,那麼task就是類中的方法,咱們也能夠認爲task就是構建項目的原子操做,再細分下去就沒有意義了。
Hello world
首先咱們來定義一個打印Hello world
的task,在build.gradle
中編寫以下腳本:
build.gradle:
task Hello { doFirst { println 'Hello world' } }
而後咱們執行gradle -q Hello
命令,-q
參數用於過濾多餘信息而已,並非必須的,執行命令後咱們會看到以下輸出:
> gradle -q Hello Hello world
執行順序
經過doFirst
和doLast
來控制task內部腳本的執行順序
task MyTask { doLast { println 'Execute doLast A' } doFirst { println 'Execute doFirst A' } } MyTask.doFirst { println 'Execute doFrist B' } MyTask.doLast { println 'Execute doLast B' }
執行gradle -q MyTask
命令,咱們會看到以下輸出:
> gradle -q MyTask Execute doFrist B Execute doFirst A Execute doLast A Execute doLast B
從執行結果,咱們能夠看出MyTask的行爲被咱們修改了,也就是說Gradle容許你在定義完task以後動態添加更多的行爲,其中MyTask.doFirst {...}
新增的doFrist
會被添加到執行隊列的頭部,而MyTask.doLast {...}
新增的doLast
會被添加到執行隊列的尾部,因此咱們會看到先打印Execute doFirst again
,最後打印Execute doLast again
。
若是咱們不關心腳本的執行順序,咱們能夠用<<
來快速定義task,<<
等價於doLast
,也就是說下面的兩種定義方式是等價的:
task Task1 << { println 'Hello' }
task Task2 { doLast { println 'Hello' } }
動態定義
3.times { i -> task "MyTask$i" << { println "My task $i" } }
> 提示:這段代碼是Groovy的語法,它的做用至關於Java的`for(int i = 0; i < 3; i++)`。
執行`gradle -q MyTask0 MyTask1 MyTask2`命令,咱們會看到以下輸出: ~~~ > gradle -q MyTask0 MyTask1 MyTask2 My task 0 My task 1 My task 2 ~~~
task之間能夠經過關鍵字dependsOn
指定依賴關係,好比負責打包的task A依賴於編譯class文件的task B,這時候當咱們容許task A的時候,task B會被先執行,而後才執行task A。
單個依賴
首先咱們來看一個最簡單的依賴關係,咱們稱他爲單個依賴,由於一個task的運行只依賴於另外一個依賴:
task task2 << { println 'Execute task2' } task task1(dependsOn: task2) << { println 'Execute task1' }
執行gradle -q task1
命令,咱們會看到以下輸出:
> gradle -q task1 Execute task2 Execute task1
多個依賴
若是咱們想指定更多的依賴關係的話,能夠用」[ ] 「定義多個task,看以下腳本:
task task2 << { println 'Execute task2' } task task3 << { println 'Execute task3' } task task4 << { println 'Execute task4' } task task1(dependsOn: [task2, task3, task4]) << { println 'Execute task1' }
執行gradle -q task1
命令,咱們會看到以下輸出:
> gradle -q task1 Execute task2 Execute task3 Execute task4 Execute task1
在定義task的時候,咱們能夠經過關鍵字type
爲task指定一種類型,task會根據不一樣類型具備不一樣的功能,而且Gradle內置了不少實用的task類型,好比Copy
類型讓task具備拷貝文件的功能,task的類型指定有點像繼承的關係:
task copyFile(type: Copy) { from '/home/xxx/' into '/home/yyy/' include 'file1.txt' rename 'file1.txt', 'file2.txt' }
執行gradle copyFile
命令,而後該task就會從/home/xxx/
目錄下將file1.txt
文件複製到/home/yyy/
目錄下,而且重命名爲file2.txt
。更多的task類型能夠查看Gradle的官方文檔。
最後你能夠經過gradle tasks
命令查看有多少的task可用,而且父項目能夠直接操做子項目的task,反過來卻不行
不少時候咱們的項目會依賴到一些第三方庫,Gradle爲咱們提供了3種方式配置依賴項。
1.依賴本地文件
假設咱們在項目的libs
目錄下有個庫叫作mylib.jar
,咱們能夠經過如下方式讓項目依賴這個庫:
dependencies { compile files('libs/mylib.jar') }
經過上面的腳本,咱們的項目在編譯的時候會自動依賴mylib.jar
庫。
若是你的libs
下面有好幾個文件須要依賴,能夠經過如下方式讓項目一次性依賴全部庫文件:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) }
2.依賴網絡庫
咱們能夠經過Gradle依賴網絡上的第三方庫,這些庫通常都會保存在一個網絡倉庫中,例如maven
或jcenter
,使用網絡上的庫帶來的好處就是咱們能夠簡單修改版本號就能夠更新到最新版的庫,而且也省去了咱們手動去複製文件。
想要依賴網絡倉庫裏面的第三方庫,咱們須要知道3個信息:group、name和version。
group:第三方庫的組織名稱。
name:第三方庫的名稱。
version:第三方庫的版本。
如今假設咱們有一個第三方庫在maven
倉庫下,它的信息以下:
group: com.hjdzone.lib name: mylib version: 1.0.0
想要使用這個第三方庫,咱們能夠編寫以下腳本:
repositories { mavenCentral() } dependencies { compile 'com.hjdzone.lib:mylib:1.0.0' }
嚴格上來講Gradle只是一個構建框架,並無提供任何真正的構建功能,構建任務實際上是經過插件實現的,不一樣的插件會根據不一樣構建需求定義各類task供咱們使用,而且Gradle已經提供了大量的插件,大多數狀況下咱們無需本身重寫plugin,只須要簡單地指定plugin就可使用了。其實在前面的例子中咱們就用到了名爲java
的插件,接下來咱們就繼續以以前的HelloGradle
項目爲例,介紹插件的用法。
首先你必須在build.gradle
中聲明使用java
插件:
apply plugin: 'java'
Gradle遵循約定優於配置
的原則,因此你的項目結構必須符合插件的要求才可以被插件所識別,例如java
插件要求咱們的代碼必須放在src/main/java
目錄下,資源文件必須放在src/main/resources
目錄下,測試代碼必須放在src/test/java
目錄下,測試資源必須放在src/test/resources
目錄下:
HelloGradle build.gradle src/main/java/Main.java src/main/resources/logo.png src/test/java/TestMain.java src/test/resources/logo.png
java
插件提供了各類腳本塊用於配置項目,例如你能夠經過插件提供的腳本塊sourceSets
修改項目的結構:
sourceSets { main { java './java' resources './resources' } }
該腳本把代碼目錄指定到了./java
目錄下,把資源文件目錄指定到了./resources
目錄下。
java
插件爲咱們提供了一套完整的構建任務,咱們能夠經過執行gradle tasks
命令查看可用的task:
參考:Gradle 快速入門