在本系列的上篇文章中,我們學習了多Project構建,在本篇文章中,我們將學到如何自定義Task類型。
請通過以下方式下載本系列文章的Github示例代碼:
git clone https://github.com/davenkin/gradle-learning.git
在前面的文章中我們講到,Gradle本身只是一個架子,真正起作用的是Task和Plugin。要真正了解Task和Plugin的工作機制並熟練運用,學會自定義Task類型和Plugin是大有裨益的。
Gradle中的Task要么是由不同的Plugin引入的,要么是我們自己在build.gradle文件中直接創建的。在默認情況下,我們所創建的Task是DefaultTask類型,該類型是一個非常通用的Task類型,而在有些時候,我們希望創建一些具有特定功能的Task,比如Copy和Jar等。還有時候,我們希望定義自己創建的Task類型,在本文中,我們以定義一個簡單的HelloWorldTask為例,講解如何自定義一個Task類型,並且如何對其進行配置。
在Gradle中,我們有3種方法可以自定義Task類型。
(一)在build.gradle文件中直接定義
我們知道,Gradle其實就是groovy代碼,所以在build.gradle文件中,我們便可以定義Task類。
class HelloWorldTask extends DefaultTask { @Optional String message = 'I am davenkin' @TaskAction def hello(){ println "hello world $message" } } task hello(type:HelloWorldTask) task hello1(type:HelloWorldTask){ message ="I am a programmer" }
在上例中,我們定義了一個名為HelloWorldTask的Task,它需要繼承自DefaultTask,它的作用是向命令行輸出一個字符串。@TaskAction表示該Task要執行的動作,即在調用該Task時,hello()方法將被執行。另外,message被標記為@Optional,表示在配置該Task時,message是可選的。在定義好HelloWorldTask后,我們創建了兩個Task實例,第一個hello使用了默認的message值,而第二個hello1在創建時重新設置了message的值。
在執行hello時,命令行輸出如下:
:hello hello world I am davenkin BUILD SUCCESSFUL Total time: 2.139 secs
在執行hello1時,命令行輸出如下:
:hello1
hello world I am a programmer
BUILD SUCCESSFUL
(二)在當前工程中定義Task類型
在(一)中,我們在build.gradle中直接定義了Task的類型,這樣將Task的定義和使用混在一起。在需要定義的Task類型不多時,我們可以采用這種方法,但是在項目中存在大量的自定義Task類型時,這就不見得是中好的做法了。一種改進方法是在另外的一個gradle文件中定義這些Task,然后再apply到build.gradle文件中。這里,我們將使用另一種方法:在buildSrc目錄下定義Task類型,Gradle在執行時,會自動地查找該目錄下所定義的Task類型,並首先編譯該目錄下的groovy代碼以供build.gradle文件使用。
在當前工程的buildSrc/src/main/groovy/davenkin目錄下創建HelloWorldTask.groovy文件,將(1)中對HelloWorldTask的定義轉移到該文件中:
package davenkin import org.gradle.api.*
import org.gradle.api.tasks.*
class HelloWorldTask extends DefaultTask { @Optional String message = 'I am davenkin' @TaskAction def hello(){ println "hello world $message" } }
這里,我們將HelloWorldTask定義在了davenkin包下,因此在build.gradle文件中引用該Task時,我們需要它的全名稱:
task hello(type:davenkin.HelloWorldTask) task hello1(type:davenkin.HelloWorldTask){ message ="I am a programmer" }
以上的hello和hello1與(1)中的hello和hello1完成的功能相同。
(三)在單獨的項目中定義Task類型
雖然(2)中的Task定義與build.gradle分離開了,但是它依然只能應用在當前工程中。如果我們希望所定義的Task能夠用在另外的項目中,那么(2)中的方法便不可行的,此時我們可以將Task的定義放在單獨的工程中,然后在所有使用Task的工程中通過聲明依賴的方式引入這些Task。
創建另外一個項目,將(2)中buildSrc目錄下的內容考到新建項目中,由於該項目定義Task的文件是用groovy寫的,因此我們需要在該項目的build.gradle文件中引入groovy Plugin。另外,由於該項目的輸出需要被其他項目所使用,因此我們還需要將其上傳到repository中,在本例中,我們將該項目生成的包含了Task定義的jar文件上傳到了本地的文件系統中。最終的build.gradle文件如下:
apply plugin: 'groovy' apply plugin: 'maven' version = '1.0' group = 'davenkin' archivesBaseName = 'hellotask' repositories.mavenCentral() dependencies { compile gradleApi() groovy localGroovy() } uploadArchives { repositories.mavenDeployer { repository(url: 'file:../lib') } }
執行“gradle uploadArchives”,所生成的jar文件將被上傳到上級目錄的lib(../lib)文件夾中。
在使用該HelloWorldTask時,客戶端的build.gradle文件可以做以下配置:
buildscript { repositories { maven { url 'file:../lib' } } dependencies { classpath group: 'davenkin', name: 'hellotask', version: '1.0' } } task hello(type: davenkin.HelloWorldTask)
首先,我們需要告訴Gradle到何處去取得依賴,即配置repository。另外,我們需要聲明對HelloWorldTask的依賴,該依賴用於當前build文件。之后,對hello的創建與(2)中一樣。
在下一篇文章中,我們將講到如何自定義Plugin。