在 Gradle 中兩個頂級概念:project(項目)和 task (任務(wù))
所有 Gradle 都有一個或多個 project 構(gòu)成。project 的展現(xiàn)取決于 Gradle 所做的工作。舉例。 project 可以是一個 JAR 庫 或者是 web 應(yīng)用。它可以是由項目生產(chǎn) JAR 組成發(fā)布的 ZIP。一個 project 不一定 代表一個東西要構(gòu)建。它可能是一件要做的事,如將應(yīng)用程序部署到工作臺 或生產(chǎn)環(huán)境。如果這看起來有點模糊,現(xiàn)在不要擔(dān)心。Gradle 基于約定的構(gòu)建支持增加一個 更具體的定義的 project。
每個項目都是由一個或多個 task。一個 task 代表了一個構(gòu)建生成的原子的作品。這可能是編寫一些類,創(chuàng)建一個 JAR ,生成 Javadoc,或發(fā)布一些庫。
現(xiàn)在,我們將看看在構(gòu)建一個 project 時定義一些簡單的 task 。后面的章節(jié)將介紹多個 project 和更多的 task 。
運行 Gradle 是使用 gradle 命令行。命令行會尋找項目的根目錄下 build.gradle 的文件(有關(guān)命令行,詳見 Appendix D. Gradle Command Line 命令行),這個就是構(gòu)建的腳本,或者嚴格說是構(gòu)建的配置腳本。他定義了project(項目)和 task 任務(wù))。
嘗試輸出,創(chuàng)建一個 build.gradle 命名的文件:
build.gradle
task hello {
doLast {
println 'Hello world!'
}
}
命令行切換到包含 build.gradle 文件的目錄,執(zhí)行 gradle -q hello
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle601.jpg" alt="" />
輸出為:
> gradle -q hello
Hello world!
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle602.jpg" alt="" />
這個腳本定義了一個 名字是hello 的 task,并且添加了動作。當(dāng)運行 gradle hello ,Gradle 執(zhí)行這個 hello task,接著執(zhí)行里面的動作。這里的動作只是簡單的包含了一些可以執(zhí)行的 Groovy 代碼。
看上去很像 Ant ,不錯,Gradle task 是相當(dāng)于 Ant 的 target,但是你將看到,他們更強大。我們使用了跟 Ant 不同的術(shù)語,因為 task 比 target 更富表現(xiàn)力。
不幸的是,這一術(shù)語與 Ant 有沖突,Ant 調(diào)用它的命令行,如 javac 或copy 稱之為 task 。所以當(dāng)我們談?wù)摰?task ,默認說的是 Gradle task ,這是相當(dāng) Ant 的 target。如果我們談?wù)摰?Ant 的 task (Ant 命令),我們明確地說的 Ant task。
-q 的作用q 是 quiet 的簡寫,意思是要安靜、干凈的輸出。如果不加 -q 則會輸出日志。詳見日志.下面是對比
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle604.jpg" alt="" />
定義 task 可以使用快捷方式,這樣更簡明。
build.gradle
task hello << {
println 'Hello world!'
}
再次執(zhí)行,得到相同的輸出。在下面的文章中,我們都會采用這種定義方式。
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle605.jpg" alt="" />
工具的構(gòu)建腳本給你完整的 Groovy 的功能。作為開胃菜,看看這個:
build.gradle
task upper << {
String someString = 'mY_nAmE'
println "Original: " + someString
println "Upper case: " + someString.toUpperCase()
}
執(zhí)行 gradle -q upper 輸出
> gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle606.jpg" alt="" />
或者
build.gradle
task count << {
4.times { print "$it " }
}
執(zhí)行 gradle -q count 輸出
> gradle -q count
0 1 2 3
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle607.jpg" alt="" />
可以聲明 task 與 其他 task 的依賴
build.gradle
task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {
println "I'm Gradle"
}
執(zhí)行 gradle -q intro 輸出
> gradle -q intro
Hello world!
I'm Gradle
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle608.jpg" alt="" />
添加一個依賴,相應(yīng)的 task 不需要存在
build.gradle
task taskX(dependsOn: 'taskY') << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
執(zhí)行 gradle -q taskX輸出
> gradle -q taskX
taskY
taskX
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle609.jpg" alt="" />
taskX 的依賴 taskY 是在 taskY 定義之前 聲明的。這個在多 project 構(gòu)建時很重要。關(guān)于 task 的依賴詳見 更多關(guān)于任務(wù)
請注意不要使用快捷符號,當(dāng)引用的 task 還沒有定義的情況下。
Groovy 的能力不僅僅是定義一個 task。例如,你也可以用它來動態(tài)創(chuàng)建的 task。
build.gradle
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
執(zhí)行 gradle -q task1 輸出
> gradle -q task1
I'm task number 1
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle610.jpg" alt="" />
一旦 task 創(chuàng)建,他們可以通過一個 API 訪問。例如,在運行時您可以使用此動態(tài)添加依賴到 task 。Ant 不允許這樣的事情。
build.gradle
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
task0.dependsOn task2, task3
執(zhí)行 gradle -q task0 輸出
> gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0
或者 可以添加行為到一個已經(jīng)存在 task 中
build.gradle
task hello << {
println 'Hello Earth'
}
hello.doFirst {
println 'Hello Venus'
}
hello.doLast {
println 'Hello Mars'
}
hello << {
println 'Hello Jupiter'
}
執(zhí)行 gradle -q hello 輸出
> gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle611.jpg" alt="" />
doFirst 和 doLast 可以多次執(zhí)行調(diào)用。他們在開始或結(jié)束的 task 動作清單中添加動作。task 執(zhí)行時,按動作列表的順序執(zhí)行的動作。操作符 << 僅僅是 doLast 的別名。
在前面的示例中已經(jīng)注意到,有一個方便的符號訪問現(xiàn)有的 task 。每個 task 可以作為構(gòu)建腳本的一個屬性:
build.gradle
task hello << {
println 'Hello world!'
}
hello.doLast {
println "Greetings from the $hello.name task."
}
執(zhí)行 gradle -q hello輸出
> gradle -q hello
Hello world!
Greetings from the hello task.
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle612.jpg" alt="" />
這使得代碼可讀性增強,尤其是當(dāng)使用的插件提供的 task ,如 compile task
可以添加自己屬性到 task ,添加 myProperty屬性,設(shè)置 、ext.myProperty 初始值,從這一點上,該屬性可以讀取和設(shè)置就像一個預(yù)定義的任務(wù)屬性。
build.gradle
task myTask {
ext.myProperty = "myValue"
}
task printTaskProperties << {
println myTask.myProperty
}
執(zhí)行 gradle -q printTaskProperties輸出
> gradle -q printTaskProperties
myValue
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle613.jpg" alt="" />
task 不對額外屬性做限制,更多詳見編寫構(gòu)建腳本
Ant task 是 Gradle 一等公民。 Gradle 給 Ant task 提供了不錯的整合通過簡單依靠于 Gradle 。Groovy 被奇異的 AntBuilder 裝載。從 Gradle 使用 Ant task 比使用 build.xml 文件更方便和更強大。從下面的例子中,你可以學(xué)習(xí)如何執(zhí)行 Ant task 和如何訪問 Ant 屬性:
build.gradle
task loadfile << {
def files = file('antLoadfileResources').listFiles().sort()
files.each { File file ->
if (file.isFile()) {
ant.loadfile(srcFile: file, property: file.name)
println " *** $file.name ***"
println "${ant.properties[file.name]}"
}
}
}
執(zhí)行 gradle -q loadfile輸出
> gradle -q loadfile
*** agile.manifesto.txt ***
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
*** gradle.manifesto.txt ***
Make the impossible possible, make the possible easy and make the easy elegant.
(inspired by Moshe Feldenkrais)
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle614.jpg" alt="" />
更多關(guān)于 構(gòu)建腳本中使用 Ant ,詳見 從 Gradle 使用 Ant
Gradle 延伸取決你如何組織的建造邏輯。上面的例子中的第一級別的組織你的構(gòu)建邏輯,是提取方法。
build.gradle
task checksum << {
fileList('../antLoadfileResources').each {File file ->
ant.checksum(file: file, property: "cs_$file.name")
println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"
}
}
task loadfile << {
fileList('../antLoadfileResources').each {File file ->
ant.loadfile(srcFile: file, property: file.name)
println "I'm fond of $file.name"
}
}
File[] fileList(String dir) {
file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}
執(zhí)行 gradle -q loadfile輸出
> gradle -q loadfile
I'm fond of agile.manifesto.txt
I'm fond of gradle.manifesto.txt
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle615.jpg" alt="" />
以后你會發(fā)現(xiàn)這樣的方法可以在多 project 構(gòu)建的子 project 之間共享。如果你建立邏輯變得越來越復(fù)雜,Gradle 為您提供其他工具很方便的方式來組織它。
Gradle 允許你定義一個或多個默認 task 給你的構(gòu)建
build.gradle
defaultTasks 'clean', 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
執(zhí)行 gradle -q 輸出
> gradle -q
Default Cleaning!
Default Running!
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle617.jpg" alt="" />
這個等于執(zhí)行了 gradle clean run ,在多 project 中構(gòu)建所有的子 project 都可以有自己具體的默認 task 。如果 子 project 沒有明確的默認 task,則執(zhí)行父 project 的默認 task(如果定義的話)
以后會詳細描述,Gradle 有配置階段和執(zhí)行階段。配置階段后,Gradle 知道所有的 task 應(yīng)該執(zhí)行。Gradle 提供給你一個鉤子來利用這些信息。這個用例將檢查發(fā)布 的 task 是否是要執(zhí)行的 task?;诖?,你可以賦予不同的值到一些變量。
在下面的例子中,在不同 version 變量中的 distribution 和 release task 執(zhí)行結(jié)果不同。
build.gradle
task distribution << {
println "We build the zip with version=$version"
}
task release(dependsOn: 'distribution') << {
println 'We release now'
}
gradle.taskGraph.whenReady {taskGraph ->
if (taskGraph.hasTask(release)) {
version = '1.0'
} else {
version = '1.0-SNAPSHOT'
}
}
執(zhí)行 gradle -q distribution 輸出
> gradle -q distribution
We build the zip with version=1.0-SNAPSHOT
執(zhí)行 gradle -q release 輸出
> gradle -q release
We build the zip with version=1.0
We release now
http://wiki.jikexueyuan.com/project/gradle-2-user-guide/images/gradle618.jpg" alt="" />
whenReady影響了 release task 在 release task 被執(zhí)行之前。同樣適用于 release task 不是 主 task 的情況(比如,task 被 gradle 命令通過了)
本章,我們大概瀏覽了下 task ,但這不是 task 的全部,可以詳見更多關(guān)于任務(wù)
另外,繼續(xù)教程 快速開始 Java 和 依賴管理的基礎(chǔ)知識.md