博客逐步遷移至 極客兔兔的小站
這是一篇Java Gradle入門級的隨筆,主要介紹Gradle的安裝與基本語法,這些內容是理解和創建build.gradle
的基礎,關於Gradle各種插件的使用將會在其他隨筆中介紹。
有什么疑問歡迎在文末關注留言,如果本文對你有用,那在右下角點個推薦吧~
1.Gradle簡介與安裝
1.1 簡介
- Gradle是一個基於Apache Ant和Apache Maven概念的項目自動化建構工具。它使用一種基於Groovy的特定領域語言(DSL)來聲明項目設置,拋棄了基於XML的各種繁瑣配置。面向Java應用為主。
- Gradle支持多工程構建,提供強大的依賴管理,支持傳遞性依賴管理(無需配置XML);自動化Java開發中的編譯、打包、執行測試案例等過程;同時Gradle支持豐富的插件,例如Java Web自動化部署的war、gretty插件等。
1.2 安裝
- Windows:下載安裝包,安裝之后,將
GRADLE_HOME/bin
添加到環境變量。 - Linux:安裝Gradle之后,配置
PATH
(1) 在~/.profile中加入GRADLE_HOME = YOUR_INSTALLATION_DIR
(2) 在~/.profile中加入PATH=$PATH:$GRADLE_HOME/bin
(3) 執行source ~/.profile重新加載profile文件
- 命令行下執行
gradle -v
可測試配置是否正確,更多命令行用法可執行gradle -h
。 - 本文代碼測試版本為Gradle 2.11
2.任務(task)管理
一個腳本是一系列待執行操作(action)、屬性的集合,有時,我們只想執行其中的某幾個操作,那這幾個操作及其相關的屬性構成了一個任務(task),任務是gradle中的執行單元。比任務更大的是項目(project),往往包括多個任務。
2.1 創建第一個task
task hello << {
println "Hello World!" + project.name // => Test
// 或 println "Hello World!$project.name" // =>Test
}
- 在某個目錄下(例如~/Test)新建文件build.gradle,文件內寫入上述代碼
- 切換到該目錄,執行gradle hello,執行結果為Hello World!Test,若沒有單獨配置,項目名一般與當前文件夾名稱相同。
- 執行這個腳本時,gradle調用org.gradle.api.Project創建一個實例project ,你可以用project.XX(在字符串中用$project.XX)去使用這個實例
- project有四個屬性,name(只讀),parent(只讀),version,description
2.2 設置屬性與任務執行
//已存在屬性直接賦值即可
version = "1.0"
description = "I Am A Gradle Test!"
// 新增屬性需要使用 ext
ext {
createDate = "Mar 2016"
}
ext.creator = "呆尐兔兔"
// task hello1
task hello1 {
doFirst {
// name為task的內置屬性,值為task名稱
println "1. My Name is " + name // ==> hello
println "2. I Belong To Project $project.name" //=>Test
}
doLast {
println "3. The Version Is " + project.version
println "4. I Am Created On " + project.createDate
}
}
// task hello2
task hello2 << {
ext { nickname = "excited"}
println "Step 2: $nickname" //=> excited
}
hello2.doFirst { println "Step 1" }
hello2.doLast { println "Step 3 " }
執行結果如下
C:\Users\gzd\Desktop\Test>gradle hello1 hello2
:hello1
1. My Name is hello1
2. I Belong To Project Test
3. The Version Is 1.0
4. I Am Created On Mar 2016
:hello2
Step 1
Step 2: excited
Step 3
- gradle [task1] [task2] [...],執行多個任務
- hello是Task對象一個實例,同樣繼承了一些屬性,例如name、description等,可在task中使用ext新增屬性
- doFirst和doLast方法為task內置方法,先后執行, << 操作符在Groovy中作用是添加元素,三者一起使用,順序
doFirst
-><<
->doLast
。<< 常用來開速添加任務。
2.3 任務依賴
// 單任務依賴
// 該任務依賴的其他任務將先執行
task hello1 << {
println "Step 1"
}
task hello2(dependsOn:hello1) << {
println "Step 2"
}
// 等價於 task hello2 << { println "Step 2" }
// hello2.dependsOn hello1
// 多任務依賴
task hello2 << {
// ...
}
hello2.dependsOn hello1, hello3
// 等價於 task hello2(dependsOn: [hello1,hello3]) << { ... }
2.4 任務執行順序與動態任務
task hello1 << {
println "Step 1"
}
task hello0 << {
println "Step 0"
}
task hello2(dependsOn:[hello1,hello0]) << {
println "Step 2"
}
task hello3 << {
println "Step 3"
}
以下是執行結果
C:\Users\gzd\Desktop\Test>gradle hello2 hello3
Step 0
Step 1
Step 2
Step 3
- 上述代碼存在任務1,2,3,4,任務2依賴於任務1與任務0,執行gradle hello2 hello3,將依次執行任務0,1,2,最后執行3。
- 盡管任務1定義在任務0前面,依賴時順序也是 1,0,對於依賴的任務,gradle的執行順序按照
字母表
。 - gradle 提供了
shouldRunAfter
、mustRunAfter
、finalizedBy
三個選項幫助定義任務執行順序。
// 使用groovy語法動態構建任務
(1..6).each {
task "hello$it" << {
println "Executing $name" //=>hello(1..6) 見2.2
}
}
hello1.dependsOn hello2
hello3.dependsOn hello2
hello5.finalizedBy hello6
hello5.mustRunAfter hello4
依次執行下列命令
gradle hello1 ==> 2->1
gradle hello1,hello3 ==> 2->1->3
gradle hello5 ==> 5->6
gradle hello5,hello4 ==> 4->5->6
- shouldRunAfter表示應該但不強制,mustRunAfter表示強制
// 考慮以下代碼,執行gradle hello1將會報錯
// 換為shouldRunAfter則不會報錯,執行順序為3->2->1
hello1.dependsOn hello2
hello2.dependsOn hello3
hello3.mustRunAfter hello1
- 另一個例子
// 以下代碼將構建出hello0,hello1,hello2,hello3
// 下標從0開始
4.times { counter ->
task "hello$counter" << {
println "I'm $name" //=> hello[0..3]
}
}
- 使用addRule動態創建任務
// 以下代碼將匹配以clean開頭的任務
// 例如gradle cleanTest => Task is cleanTest
// gradle cleanHello => Task is cleanHello
tasks.addRule("Pattern:clean<fileName>") { String taskName ->
if(taskName.startsWith("clean")) {
task(taskName) << {
println "Task is $name";
}
}
}
2.5 任務名稱簡寫
- gradle支持在執行命令時使用任務的簡寫(每個單詞第一個字母)
- 例如執行gradle hello1, 可以簡寫為gradle h1
- 例如執行gradle helloWorld1,helloWorld2,可簡寫為gradle hW1,hW2
2.6 條件執行
2.6.1 onlyIf
// gradle hello => hello:SKIPPED(條件不滿足,不執行)
// onlyIf 常用於判斷當前環境是否滿足執行條件
version = '1.0'
ext {
createYear = '2015'
}
task hello << {
println 'I was Created in ' + createYear
}
hello.onlyIf { project.hasProperty('createYear') &&
project.createYear == '2016'}
2.6.2 enabled
// gradle h2 => :hello1 SKIPPED :hello2 Step 2
// 即使2依賴1,1被禁用,2仍能執行
// 常用於測試,更換舊代碼
task hello1 << {
println 'Step 1'
}
task hello2(dependsOn:hello1) << {
println 'Step 2'
}
hello1.enabled = false
- 由於
enabled
是task的一個屬性,hello1 可以寫為
task hello1 {
enabled = false;
doLast { println 'Step 1' }
}
2.7 編譯優化
task hello {
ext {
testFile = file('in.txt')
}
String outFileName = 'out.txt'
File outFile = new File(outFileName)
inputs.file testFile
outputs.file outFile
doLast {
def property = new XmlParser().parse(testFile)
def key = property.key[0].text()
def value = property.value[0].text()
def destFile = new File(outFileName)
destFile.text = "$key = $value"
}
}
第一次執行
gradle hello => :hello BUILD SUCCESSFUL
第二次執行
gradle hello => :hello UP-TO-DATE
- gradle會自動對輸入輸出操作的task進行編譯優化,例如上面的例子,第一次執行時,需要打開輸入文件,創建輸出文件,當第二次這個命令時,gradle發現輸入輸出文件並沒有發生變化,因此顯示UP-TO-DATE,即沒有必要執行這個命令了,這在實際項目開發過程中,將節省大量的時間
- 當輸入輸出文件發生改變(例如刪除out.txt),任務將重新編譯執行
- 如果需要強制執行,及時輸入輸出沒有發生改變,可以使用
--rerun-tasks
參數
gradle hello --rerun-tasks
// gradle -b build.gradle hello --rerun-tasks