在現有的基礎上工作
Gradle資料
Maven和Gradle對比: http://www.importnew.com/18008.html
Gradle官網的與Maven對比: https://gradle.org/maven_vs_gradle/
下載: https://services.gradle.org/distributions/gradle-3.0-all.zip
Gradle官方用戶指南文檔: https://docs.gradle.org/current/userguide/userguide.html
Gradle2用戶指南中文版: https://waylau.gitbooks.io/gradle-2-user-guide/content/
安裝
Gradle3.0后,需要java7或更高版本
Gradle會裝載自己的Groovy庫,所以,不需要安裝Groovy,就算安裝了Groovy也會被忽略掉。
下載
下載完整包后,里面會包含 Gradle、用戶指南、API文檔、示例
https://gradle.org/gradle-download/
配置環境變量
GRADLE_HOME=D:\resource\Gradle\gradle-3.0
path=%GRADLE_HOME%/bin
(linux: path=$GRADLE_HOME/bin
)
GRADLE_OPTS=-Xms256m -Xmx512m
(指定用於啟動JVM命令行參數,選擇配置)
GRADLE_USER_HOME=D:\resource\Gradle\repo
(配置本地倉庫的位置)
檢查是否安裝成功
執行命令 gradle -v
Gradle命令
- 執行多task(列出每個task):
gradle dist test
task compile << {
println 'compiling source'
}
task compileTest(dependsOn: compile) << {
println 'compiling unit tests'
}
task test(dependsOn: [compile, compileTest]) << {
println 'running unit tests'
}
task dist(dependsOn: [compile, test]) << {
println 'building the distribution'
}
-
排除task(
-x
):gradle dist -x test -x compile
-
當task執行失敗時,繼續執行不依賴這個task的其它task
gradle --continue dist
-
任務名稱縮寫(只需提供足夠的可以唯一區分出該 task 的字符):
gradle di
-
選擇需要執行的腳本:
C:\>gradle -q -b D:/empty/build.gradle hello
在多子項目時,應該使用-p
:gradle -q -p subdir hello
-
忽略新版本檢查(ignoring any up-to-date checks):
gradle --rerun-tasks di
-
查看構建信息
gradle -q projects
: 列出當前項目及其子項目(一並輸出description
)
gradle -q tasks
(gradle -q tasks --all
): 列出當前項目的所有task
gradle help --task task1 task2
: 顯示匹配到的task的詳細信息
gradle -q dependencies api:dependencies webapp:dependencies
: 列出指定項目的依賴
gradle -q api:dependencies --configuration testCompile
: 列出指定項目及指定階段的依賴
gradle buildEnvironment
: ?
gradle -q webapp:dependencyInsight --dependency groovy --configuration compile
: ? (對追蹤為何依賴出現的版本很有幫助)
gradle -q api:properties
: 列出當前項目的屬性 -
生成構建耗時報告
--profile
-
干跑(不真正執行,用來查看執行了哪些task)
gradle -m someTask1 someTask2
Gradle命令列表
https://docs.gradle.org/current/userguide/gradle_command_line.html
包括幾個環境變量的說明:GRADLE_OPTS
GRADLE_USER_HOME
JAVA_HOME
Gradle Wrapper
- Wrapper的使用
Gradle Wrapper
解決在未安裝Gradle
的情況下也能構建項目,並且避免用戶選擇了不正確的Gradle
版本
每個Gradle Wrapper
都會指定Gradle
版本,當首次使用Wrapper
時,將下載指定的Gradle
版本,並使用它進行構建
Wrapper
下載的Gradle
保存到目錄$USER_HOME/.gradle/wrapper/dists
中
- 為項目添加Wrapper
只需要項目根目錄下執行gradle wrapper --gradle-version 版本號
也可以在構建腳本build.gradle
中添加task
task wrapper(type: Wrapper) {
gradleVersion = '2.0'
}
執行命令后,將生成以下幾個文件
demo/
gradlew
gradlew.bat
gradle/
wrapper/
gradle-wrapper.jar
gradle-wrapper.properties
配置文件gradle-wrapper.properties
中的各項配置說明(一般不需要變更):
https://docs.gradle.org/current/dsl/org.gradle.api.tasks.wrapper.Wrapper.html
- 校驗Wrapper下載的Gradle文件
執行命令shasum -a 256 gradle-3.0-all.zip
生成hash碼
windows下可以使用Git Bash
來執行
將生成 的hash嗎,配置到gradle-wrapper.properties
中
distributionSha256Sum=9c8b7564ea6a911b5b9fcadd60f3a6cea4238413c8b1e1dd14400a50954aab99
- unix權限
在Unix系統中,如果遇到文件權限問題,可以這樣執行sh gradlew
Gradle Daemon
可以通過Gradle Daemon
來解決,Gradle
啟動會比較慢的問題
Gradle
啟動慢是因為,它運行中Java Virtual Machine (JVM)上,並還會依賴幾個比較耗時的支持庫
Gradle Daemon
,是一直存活的,避免了JVM的啟動耗時,並且緩存項目結構、文件、tasks等信息
在Gradle 3.0
中,Gradle Daemon
是默認啟動的,不需要作其它的變動
在低版本Gradle
中,可以使用--daemon
來啟用Gradle Daemon
使用了Gradle Daemon
,將會提升15-75%的構建速度
可以通過--profile
來生成耗時報告
可以通過命令gradle --status
來查看 Gradle Daemon
的狀態
如果安裝了JDK,可以使用jps
命令來查看
注意:目前,只有相同版本的Gradle
與Gradle Daemon
才能一起工作
禁用Gradle Daemon
可以通過配置文件,也可以直接使用命令gradle --stop
目前,建議,在持續集成服務器中禁用Gradle Daemon
,提高可靠性
https://docs.gradle.org/current/userguide/gradle_daemon.html
Gradle Daemon
,若存活時間超過3個小時,將會被回收
依賴管理基礎
- 聲明依賴
// java插件
apply plugin: 'java'
// 設定使用Maven中心倉庫
repositories {
mavenCentral()
}
dependencies {
// 聲明依賴hibernate-core版本為3.6.7.Final,在編譯及運行時依賴它
compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
// 聲明從倉庫中獲取版本>=4.0的junit,在test時依賴它
testCompile group: 'junit', name: 'junit', version: '4.+'
}
- 依賴配置
java插件中定義了以下幾個標准的依賴配置
compile
編譯時的依賴
runtime
程序運行時的依賴,默認包含compile
testCompile
單元測試編譯時的依賴,默認包含compile
testRuntime
單元測試程序運行時的依賴,默認包含compile
、runtime
和testCompile
- 依賴的聲明方式
依賴由group、name與version組成,除了上面的聲明方式,還可以寫成下面這樣
dependencies {
compile 'org.hibernate:hibernate-core:3.6.7.Final'
testCompile 'junit:junit:4.+'
}
- 倉庫
默認情況下,Gradle
不會定義依賴倉庫,如果構建時需要第三方依賴,必須定義依賴倉庫
如下設置倉庫為Maven中心倉庫
repositories {
mavenCentral()
}
如下設置倉庫為Maven遠程倉庫
repositories {
maven {
url "https://repo1.maven.org/maven2/"
}
}
- 發部項目
通過執行命令gradle uploadArchives
,Gradle將構建並上傳生成的jar包
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
repository(url: "D:/resource/maven/repo/")
}
}
}
多項目構建
共同點
- 在根項目中都有一個
settings.gradle
的文件 - 在根項目中都有一個
build.gradle
的構建文件 - 子項目中都有它們自己的
*.gradle
的構建文件
可以通過命令gradle -q projects
查詢項目列表
官方建議,每個項目都在settings.gradle
中配置根項目名,示例spring源碼中的rootProject.name = "spring"
不需要每個子項目都要有構建文件,但根項目中必須要有
子項目中構建文件的文件名不一定是build.gradle
,只要以.gradle
為后綴即可
在根項目中執行命令gradle test
,將都在各子項目中執行這個gradle test
命令
指定子項目的方法類似於路徑,但不是用/
或\\
,而是使用:
。
如 gradle :services:webservice:tasks
,首個:
表示根項目,其它的:
表示路徑分隔
持續構建
至目前3.0版本,這個特性尚未非常完善
通常,當前執行完所有指定的task后,就算是一次構建完畢,當下一次調用gradle命令時,才會進行下一次的構建動作
但持續構建時,Gradle會保持構建的功能,只有接收到停止命令時,才會停止。
如,對於編譯JAVA文件,每當java文件變更時,Gradle自動對這個文件進行再次編譯。
在一些情景下,持續構建能夠發揮很大作用。
- 啟動:添加參數
--continuous
或-t
。示例,gradle build --continuous
- 停止:如果是啟動是在終端命令中,可以通過CTRL+D之后再接ENTER來結束;否則,需要使用kill命令來結束進程;某些工具或許會提供這個功能
只有在當前持續構建中,命令所涉及到的文件(構建腳本不算),被更改時,才會觸發再次構建
當前構建腳本變更時,只有手動重啟持續構建后,新的構建方案才會生效
注意事項:
- 循環構建:在構建的過程中,構建腳本更改了被Gradle監視着的文件,就會形成循環構建
- java9的限制:在Mac OS X中,Gradle為每10秒檢測一遍文件的變更,而不是2秒;在Windows在,大項目可能運行不了持續構建
- 性能與穩定性:在Mac OS X中,由於依賴於它低效率的系統輪詢,所以對文件變更的感知會延遲;此外,在Mac OS X中,重負載情況下,可能會導致死鎖;在linux中,如使用的是OpenJDK,有可能會錯過文件變更的事件通知
- 刪除目標目錄,不會引起新的構建
復合構建
至目前3.0版本,這個特性也尚未非常完善
復合構建與多項目構建有許多類似的地方
gradle 圖形界面
使用命令gradle --gui
就可以彈出圖形界面
構建環境
通過gradle.properties
配置編譯環境
通過本地環境變量的配置,如GRADLE_OPTS
或JAVA_OPTS
等,會作用於所有項目構建
如果某個項目需要特殊配置時,可以使用gradle.properties
的配置來覆蓋環境變更的配置
在下面三個地方中,如果存在相同的配置,后一個覆蓋前一個
- 項目構建目錄中的
gradle.properties
- Gradle用戶目錄下的
gradle.properties
- 系統屬性,如,命令行輸入的
-Dsome.property
這個功能需要jdk7或以上版本
下面列出用於配置Gradle構建環境的配置
org.gradle.daemon
當設置為true
時,將使用Gradle daemon
去構建。本地是默認使用的,在CI持續構建時,建議為false
org.gradle.java.home
指定Gradle構建程序使用的Java路徑org.gradle.jvmargs
指定daemon
程序的jvm參數,這個設置是非常有用的,因為默認分配的daemon
內存是比較大的org.gradle.configureondemand
按需配置,只配置關聯項目,使用大型項目能夠快速構建 Configuration on demandorg.gradle.parallel
當配置了這個設置后,Gradle將以parallel模式執行org.gradle.workers.max
配置並發執行的最大數org.gradle.debug
當設置為true
時,以遠程(監聽端口5005)debug模式運行,相當於在jvm命令行中添加-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
org.gradle.daemon.performance.enable-monitoring
當設置為false
時,Gradle將不監控daemons
運行時的內存使用情況
可以在gradle.properties
配置文件中,配置http/https的訪問代理
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=userid
systemProp.http.proxyPassword=password
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost
gradle的嵌入式編程
Gradle提供Tooling API
,使用者可以自行調用。主要使用者是IDE、CI server等,但,API是開放的,任何人都可以在項目中使用
- Gradle TestKit
- Eclipse Buildship
- IntelliJ IDEA
API有如下特性
- 查詢構建明細,包括項目結構與依賴
- 執行構建,並監聽輸出日志
- 執行指定的測試類或測試方法
- 接收構建過程的事件,如項目配置,執行的task或test
- 取消正在執行的構建
- 將多個單獨構建,組合與復合構建
- 下載合適的Gradle版本
- 輕量級的實現,可以非常方便的嵌入到應用中
在samples/toolingApi
中有示例
編寫Gradle構建腳本
構建腳本基礎
1). Projects and tasks
Projects
與 tasks
是Gradle最頂部的兩個基本概念
每個構建包含一個或多個Projects
,一個Project
由一個或多個tasks
組成
2). Hello world
當執行gradle
命令時,將會在當前目錄中查找一個叫build.gradle
的構建腳本
第一個構建腳本:執行gradle -q hello
(-q
的作用是不輸出gradle的日志)
task hello {
doLast {
println 'Hello world!'
}
}
Gradle的task,與Ant的target很類似,但比target強大
3). 更簡捷的書寫方式
task hello << {
println 'Hello world!'
}
4). 構建腳本,本身就是編程
通過強大的Groovy
進行編寫Gradle
構建腳本
下面為在Task中使用Groovy的示例
task upper << {
String someString = 'mY_nAmE'
println "Original: " + someString
println "Upper case: " + someString.toUpperCase()
}
示例2
task count << {
4.times { print "$it " }
}
5). Task之間的依賴
示例1:
task hello << {
println 'Hello world!'
}
task intro(dependsOn: hello) << {
println "I'm Gradle"
}
在示例1中,執行gradle -q intro
,將輸出如下:
D:\Learning\gradle\hello>gradle -q intro
Hello world!
I'm Gradle
示例2:延遲依賴,所依賴task,在當前task之后
task taskX(dependsOn: 'taskY') << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
示例2將輸出:
D:\Learning\gradle\hello>gradle -q taskX
taskY
taskX
6). 動態tasks
利用功能強大的Groovy,可以動態的創建tasks
示例:
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
在示例中,執行task0
、task1
、task2
與task3
都是正常的
7). 調整已存在的tasks
當tasks被創建后,就可以通過一此API進行訪問。通過這個特性,可以動態的實現task之間的依賴。Ant是不允許這么做的
示例1:
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
task0.dependsOn task2, task3
輸出如下:
D:\Learning\gradle\hello>gradle -q task0
I'm task number 2
I'm task number 3
I'm task number 0
示例2:添加behaviour
task hello << {
println 'Hello Earth'
}
hello.doFirst {
println 'Hello Venus'
}
hello.doLast {
println 'Hello Mars'
}
hello << {
println 'Hello Jupiter'
}
輸出如下:
D:\Learning\gradle\hello>gradle -q hello
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
doFirst
與doLast
可以被調用多次,表示在一個action之前或之后執行。
他們是依賴執行,操作符<<
就類似於doLast
的別名
8). 快捷符號
像在之前的示例中,可以通過一個快捷符號來訪問已經存在的任務
task hello << {
println 'Hello world!'
}
hello.doLast {
println "Greetings from the $hello.name task."
}
這使用得代碼更具可讀性,特別是其它插件提供的tasks,比如compile
9). task的全局屬性
在task中,可在屬性中添加ext.
前綴,並賦值,這樣在其它的task中,就可讀取到這個屬性值了
示例:
task myTask {
ext.myProperty = "myValue"
}
task printTaskProperties << {
println myTask.myProperty
}
10). 編寫Ant Tasks
Ant tasks are first-class citizens in Gradle.
Using Ant tasks from Gradle is as convenient and more powerful than using Ant tasks from a build.xml file.
下面示例如何訪問Ant tasks及訪問Ant properties
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]}"
}
}
}
執行這個腳本,需要在當前腳本父目錄中,創建文件夾antLoadfileResources
,並在其下創建幾個文件
更多關於Gradle中使用Ant的教程:Using Ant from Gradle
11). 使用公共方法
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()
}
在后面將有章節,專門說明如果組織腳本代碼的 Organizing Build Logic
12). 定義默認tasks
如果沒有指定tasks,將執行默認的tasks
定義默認tasks示例:
defaultTasks 'clean', 'run'
task clean << {
println 'Default Cleaning!'
}
task run << {
println 'Default Running!'
}
task other << {
println "I'm not a default task!"
}
如果只執行命令gradle -q
,由於沒有指定tasks,就會執行默認的clean
與run
,相當於gradle -q clean run
如果子項目中沒有指定默認tasks,則將執行父項目中的默認tasks
13). 通過DAG配置
在后面的構建生命周期中將有講到,Gradle有一個配置階段與一個執行階段
配置階段之后,Gradle就知道了所有需要被執行的tasks。此時,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'
}
}
當執行gradle -q distribution
命令時,將輸出:
D:\Learning\gradle\hello>gradle -q distribution
We build the zip with version=1.0-SNAPSHOT
當執行gradle -q release
命令時,將輸出:
D:\Learning\gradle\hello>gradle -q release
We build the zip with version=1.0
We release now
非常重要的whenReady
,它是在relese
這個task執行之前起使用。
構建初始化插件
這個構建初始化插件正在不斷完善中,在以后的版本中,DSL及其他配置可能會改變
這個構建初始化插件可以引導Gradle項目的創建。支持創建各種類型的Gradle項目,同時支持將其它構建方式轉化為Gradle項目。
通常,Gradle插件是應用中項目。這個構建初始化插件是會自動應用於項目的,所以不需要特別配置。只需要在准備創建Gradle項目的地方,執行init這個task。
當使用這個構建初始化插件時,Gradle Wrapper
也會自動被安裝到當前項目中。
1). 插件包含的tasks
Task name | depends on | Type | Description |
---|---|---|---|
init | wrapper | InitBuild | Generates a Gradle project. |
wrapper | - | Wrapper | Generates Gradle wrapper files. |
2). 初始設定
可以通過--type
參數,指定構建的項目類型
如:創建一個java項目 gradle init --type java-library
若沒有設定type
參數,則Gradle將根據當前環境做出適當的判斷,比如,當發現有pom.xml
文件時,就會將type
設定為pom
,即將maven項目轉換為gradle項目
如果沒有指定或判斷出type
值,則將使用默認的basic
3). 初始化的項目類型
由於這個功能還在孵化中,所以只提供幾種類型,更多的類型將在后續的版本中提供。
pom
在當前路徑中查找文件pom.xml
,並將其轉化為gradle項目java-library
創建java項目scala-library
groovy-library
basic
編寫Gradle構建腳本
Gradle構建腳本語言
Gradle為構建腳本提供了一個領域特定語言(DSL)。基於Groovy,並添加了一些更易於描述腳本的語法。
Gradle構建腳本可以包含任何Groovy語言標識。默認UTF-8編碼。
API: Project
- 調用當前腳本中沒有的任何方法,都將委托給
Project
這個對象。 - 調用當前腳本中沒有的任何屬性,都將委托給
Project
這個對象。
println name
println project.name
第一行,是由於當前腳本未定義name
屬性,則委托給project
這個對象,所以第一行與第二行輸出是一樣的
標准的項目屬性
Project
這個對象,提供了幾個標准的屬性,可以構建腳本中直接使用,下面列出常用的幾個
Name | Type | Default Value |
---|---|---|
project | Project | The Project instance |
name | String | The name of the project directory. |
path | String | The absolute path of the project. |
description | String | A description for the project. |
projectDir | File | The directory containing the build script. |
buildDir | File | projectDir/build |
group | Object | unspecified |
version | Object | unspecified |
ant | AntBuilder | An AntBuilder instance |
API: Script
當Gradle執行構建腳本時,會將這個腳本編譯成實現接口Script
的類。也就是說,接口Script
中的所有屬性和方法,在構建腳本中都可以調用。
Script
的官方文檔: https://docs.gradle.org/current/dsl/org.gradle.api.Script.html
聲明變更
在構建腳本中,有兩種方式聲明變更。本地變更(Local variables)和全局變量(Extra properties)
使用關鍵字def
來進行聲明本地變量(只在所聲明范圍有效)。這是Groovy的語法。
def
示例:
def dest = "dest"
task copy(type: Copy) {
from "source"
into dest
}
使用關鍵字ext.
作為前綴來聲明全局變量。 這種變量,在子項目中,也是可見的。
包括但不限於,projects
、tasks
與source
都可以定義、改變及使用這種全局變量
ext.
示例:
apply plugin: "java"
ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "build@master.org"
}
sourceSets.all { ext.purpose = null }
sourceSets {
main {
purpose = "production"
}
test {
purpose = "test"
}
plugin {
purpose = "production"
}
}
task printProperties << {
println springVersion
println emailNotification
sourceSets.matching { it.purpose == "production" }.each { println it.name }
}
對上面的腳本,執行命令gradle -q printProperties
,將輸出:
D:\Learning\gradle\Extra properties>gradle -q printProperties
3.1.0.RELEASE
build@master.org
main
plugin
關於ext.
的更多用法,參考: https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
配置對象
可以使用如下示例的方式,配置任意對象,這樣的腳本具有非常高的可讀性。
task configure << {
def pos = configure(new java.text.FieldPosition(10)) {
beginIndex = 1
endIndex = 5
}
println pos.beginIndex
println pos.endIndex
}
執行命令gradle -q configure
,將輸出:
D:\Learning\gradle\Configuring arbitrary objects>gradle -q configure
1
5
使用外部腳本配置對象
示例,使用外部的other.gradle來對build.gradle的pos對象進行配置
build.gradle
task configure << {
def pos = new java.text.FieldPosition(10)
// Apply the script
apply from: 'other.gradle', to: pos
println pos.beginIndex
println pos.endIndex
}
other.gradle
// Set properties.
beginIndex = 1
endIndex = 5
Groovy簡單入門
Groovy提供了非常的DSL特性,而Gradle也繼承了這些特性。懂得構建語言對編寫腳本,特別是自定義插件和tasks時,是非常有用的。
1). Groovy JDK
在java的基礎上,groovy添加了許多有用的方法。如,迭代(Iterable),在Groovy中,可以直接使用each
方法。
// Iterable gets an each() method
configurations.runtime.each { File f -> println f }
在 http://groovy-lang.org/gdk.html 在詳細的說明。
2). Property accessors
Groovy會自動將對屬性的調用,轉換為getter或setter方法。
// Using a getter method
println project.buildDir
println getProject().getBuildDir()
// Using a setter method
project.buildDir = 'target'
getProject().setBuildDir('target')
3). 方法調用可省略圓括號
test.systemProperty 'some.prop', 'value'
test.systemProperty('some.prop', 'value')
4). List與map集合
Groovy提供了簡捷的List與map的實例化方式。
// List literal
test.includes = ['org/gradle/api/**', 'org/gradle/internal/**']
List<String> list = new ArrayList<String>()
list.add('org/gradle/api/**')
list.add('org/gradle/internal/**')
test.includes = list
// Map literal.
Map<String, String> map = [key1:'value1', key2: 'value2']
// Groovy will coerce named arguments
// into a single map argument
apply plugin: 'java'
5). 閉包作為方法的最后參數
Gradle DSL 在很多地方都使用了閉包。
參考: http://docs.groovy-lang.org/latest/html/documentation/index.html#_closures
repositories {
println "in a closure"
}
repositories() { println "in a closure" }
repositories({ println "in a closure" })
6). 閉包委派
每個閉包,都會委派一個用於查找變量及方法的對象。
示例: 閉包委派
dependencies {
assert delegate == project.dependencies
testCompile('junit:junit:4.12')
delegate.testCompile('junit:junit:4.12')
}
默認導入
為了使用腳本更簡捷,Gradle自動導入一系列重要的聲明。
主要是import org.gradle.*
及這個包下的子包
深入tasks
區別於Ant的target,Gradle支持增強的tasks,它可以有自己的屬性和方法。
定義task
示例1: 定義task
task(hello) << {
println "hello"
}
task(copy, type: Copy) {
from(file('srcDir'))
into(buildDir)
}
示例2:使用strings作為task名字
task('hello') <<
{
println "hello"
}
task('copy', type: Copy) {
from(file('srcDir'))
into(buildDir)
}
示例3:對示例2的替代語法
tasks.create(name: 'hello') << {
println "hello"
}
tasks.create(name: 'copy', type: Copy) {
from(file('srcDir'))
into(buildDir)
}
對於task的create方法,參考: https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskContainer.html
定位tasks
示例1:通過tasks的屬性訪問task
task hello
println hello.name
println project.hello.name
示例2:通過tasks集合訪問task
task hello
println tasks.hello.name
println tasks['hello'].name
示例3:通過路徑訪問task
project(':projectA') {
task hello
}
task hello
println tasks.getByPath('hello').path
println tasks.getByPath(':hello').path
println tasks.getByPath('projectA:hello').path
println tasks.getByPath(':projectA:hello').path
對於示例3,需要在當前路徑中,添加名為projectA
的文件夾,並在配置文件settings.gradle
中添加include 'projectA'
示例3的輸出如下:
D:\Learning\gradle\Locating tasks>gradle -q hello
:hello
:hello
:projectA:hello
:projectA:hello
對於更多的定位tasks的介紹,訪問 https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskContainer.html
配置tasks
首先來看一下Gradle提供的Copy task
。可以如下定義一個Copy task
task myCopy(type: Copy)
這個myCopy
並沒有定義默認的操作,但它可以使用Copy
的API了。下面會舉幾個例子,有不同的方式達到同樣的目的。
Copy
API: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Copy.html
當然,這個myCopy
只是一個Copy
類型的task,同樣還可以定義更多的Copy
類型的task。
示例1: 使用不同的方式配置task
Copy myCopy = task(myCopy, type: Copy)
myCopy.from 'resources'
myCopy.into 'target'
myCopy.include('**/*.txt', '**/*.xml', '**/*.properties')
對於示例1的方式,很類似於java。但這種方式比較冗余,而且代碼可讀性不強。
下面示例比較常用的方式。
示例2: 使用閉包配置task
task myCopy(type: Copy)
myCopy {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
也可以直接使用如下方式:
task myCopy(type: Copy) {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
為task添加依賴
示例1: 直接使用task名字關聯
project('projectA') {
task taskX(dependsOn: ':projectB:taskY') << {
println 'taskX'
}
}
project('projectB') {
task taskY << {
println 'taskY'
}
}
執行gradle -q taskX
,將輸出:
D:\Learning\gradle\Adding dependencies to a task>gradle -q taskX
taskY
taskX
示例2: 使用對應task對象關聯
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
taskX.dependsOn taskY
執行gradle -q taskX
,也將輸出:
D:\Learning\gradle\Adding dependencies to a task>gradle -q taskX
taskY
taskX
示例3: 使用閉包添加依賴
task taskX << {
println 'taskX'
}
taskX.dependsOn {
tasks.findAll { task -> task.name.startsWith('lib') }
}
task lib1 << {
println 'lib1'
}
task lib2 << {
println 'lib2'
}
task notALib << {
println 'notALib'
}
執行gradle -q taskX
,將輸出:
D:\Learning\gradle\Adding dependencies to a task>gradle -q taskX
lib1
lib2
taskX
關於task的更多用法,參考: https://docs.gradle.org/current/dsl/org.gradle.api.Task.html
tasks排序
這是一個還在孵化中的特性,在以后的Gradle版本中可能變更。
排序與依賴的區別在於,排序並不會影響到task的執行,只是設定tasks的執行順序。
排序,在下面情況下會很有用處:
- 有強制順序的tasks排序:如
build
永遠不會在clean
之前執行 - 在
build
之前執行構建校驗:如校驗是否有權限執行build
- 在耗時長的驗證task之前,通過執行一個快速驗證獲得反饋:如在集成測試之前,應該先執行單元測試
- 一個收集所有特定類型task執行結果的task:如,測試報告task,它會收集所有測試task的運行結果。
只支持兩排序方式: must run after
和should run after
示例1
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
taskY.mustRunAfter taskX
執行gradle -q taskY taskX
輸出:
D:\Learning\gradle\Ordering tasks>gradle -q taskY taskX
taskX
taskY
示例2
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
taskY.shouldRunAfter taskX
執行gradle -q taskY taskX
輸出:
D:\Learning\gradle\Ordering tasks>gradle -q taskY taskX
taskX
taskY
示例3
task taskX << {
println 'taskX'
}
task taskY << {
println 'taskY'
}
task taskZ << {
println 'taskZ'
}
taskX.dependsOn taskY
taskY.dependsOn taskZ
taskZ.shouldRunAfter taskX
執行gradle -q taskX
輸出:
D:\Learning\gradle\Ordering tasks>gradle -q taskY taskX
taskZ
taskY
taskX
為task添加掃描信息
示例:
task copy(type: Copy) {
description 'Copies the resource directory to the target directory.'
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
tasks覆蓋
使用overwrite
,示例:
task copy(type: Copy)
task copy(overwrite: true) << {
println('I am the new one.')
}
執行 gradle -q copy
,將輸出
> gradle -q copy
I am the new one.
跳過task的執行
1). 使用斷言
可以使用方式onlyIf()
為task添加斷言。