Gradle通關系列(四)-深入Task

深入Task

task作為Gradle構建的最小原子工作烙常,可以通過task之間的相互依賴靈活的定義一個項目的構建生闲。

task包含一下屬性

  • task自身的相關屬性成艘,包含所有的getter及舍、setter方法
  • extentsions屬性
  • conventions屬性
  • extra屬性

Task配置

定義Task

可以為Project定義一系列的任務項醉蚁,每個任務都會有自己一系列的Action,可以通過doFirst盒蟆、doLast添加action

//創(chuàng)建默認task
tasks.register("hello") {
    //配置階段的代碼
    group = "custiom"
    doLast {
        //執(zhí)行階段的代碼
        println("hello")
    }
}
//創(chuàng)建基于Task模板的task
tasks.register<Copy>("copy") {
    //配置拷貝源
    from(file("srcDir"))
    //配置拷貝目的
    into(buildDir)
}

獲取Task

可以獲取已經定義的task踏烙,獲取task的相關配置或者對其進行再次配置

//通過名稱獲取task
println(tasks.named("hello").get().name)
//通過名稱獲取指定類型的task
println(tasks.named<Copy>("copy").get().destinationDir)
//根據(jù)類型獲取task
tasks.withType<Copy>().configureEach {
    group = "customCopy"
}

我們可以在TaskContainer源碼中查看更多關于獲取task的api

Task依賴及排序

一個task可能有依賴另外一個task,也可能需要被放在某個task之后執(zhí)行历等,Gradle確保在執(zhí)行任務時遵守所有的任務依賴關系和排序規(guī)則讨惩,使用dependsOn來操作task的依賴,使用mustRunAfter寒屯、shouldRunAfter來操作task的執(zhí)行順序荐捻。

通過以下對象來指定task依賴或排序

  • task字符串路徑
  • Task對象
  • TaskDenpendcy對象
  • TaskRefrence對象
  • RegularFileProperty黍少、File、DirectoryProperty對象
  • 包含上述類型返回值的Provider對象
  • 包含上述類型的集合
  • 包含上述類型的閉包
  1. 依賴其他項目的task
project("project-a") {
    //依賴項目b的taskY
    tasks.register("taskX") {
        //task的路徑通過:分割
        dependsOn(":project-b:taskY")
        doLast {
            println("taskX")
        }
    }
}

project("project-b") {
    tasks.register("taskY") {
        doLast {
            println("taskY")
        }
    }
}

執(zhí)行taskX之前會執(zhí)行taskY

  1. 依賴一個閉包
val taskX by tasks.registering {
    doLast {
        println("taskX")
    }
}

//依賴一個閉包
taskX {
    dependsOn(provider {
        tasks.filter { task -> task.name.startsWith("lib") }
    })
}

tasks.register("lib1") {
    doLast {
        println("lib1")
    }
}

tasks.register("lib2") {
    doLast {
        println("lib2")
    }
}

tasks.register("notALib") {
    doLast {
        println("notALib")
    }
}

執(zhí)行taskX之前會執(zhí)行l(wèi)ib1处面、lib2

  1. 對task的執(zhí)行流程進行排序
val taskX by tasks.registering {
    doLast {
        println("taskX")
    }
}
val taskY by tasks.registering {
    doLast {
        println("taskY")
    }
}
taskY {
    mustRunAfter(taskX)
}

執(zhí)行以下命令的輸出情況

> gradle -q taskY taskX
taskX
taskY
> gradle -q taskY
taskY

可以看出來依賴與順序的區(qū)別

當一個task依賴其他task時厂置,會優(yōu)先執(zhí)行依賴的task

task的執(zhí)行順序,并不意味著作為參照的task將被執(zhí)行魂角,只是在需要一起執(zhí)行時昵济,按照約定的先后順序執(zhí)行

  1. 當task已經有依賴流程了,會忽略排序流程
val taskX by tasks.registering {
    doLast {
        println("taskX")
    }
}
val taskY by tasks.registering {
    doLast {
        println("taskY")
    }
}
val taskZ by tasks.registering {
    doLast {
        println("taskZ")
    }
}
taskX { dependsOn(taskY) }
taskY { dependsOn(taskZ) }
taskZ { shouldRunAfter(taskX) }
> gradle -q taskX
taskZ
taskY
taskX

跳過task

  1. 通過判斷條件

    val hello by tasks.registering {
        doLast {
            println("hello world")
        }
    }
    
    hello {
        onlyIf { !project.hasProperty("skipHello") }
    }
    
  2. 通過異常野揪,拋出StopExecutionException

  3. 設置不可用

    val disableMe by tasks.registering {
        doLast {
            println("This should not be printed if the task is disabled.")
        }
    }
    
    disableMe {
        enabled = false
    }
    
    
  4. 設置task超時時間

    tasks.register("hangingTask") {
        doLast {
            Thread.sleep(100000)
        }
        timeout.set(Duration.ofMillis(500))
    }
    

給TaskContainer添加Rule

TaskContainer繼承自NamedDomainObjectCollection访忿,它可以添加一個規(guī)則,當給定一個未知命名的domain object時囱挑,會應用改規(guī)則醉顽,你可以進行忽略,或者自行創(chuàng)建該命名的domain object

tasks.addRule("Pattern: ping<ID>") {
    val taskName = this
    if (startsWith("ping")) {
        task(taskName) {
            doLast {
                println("Pinging: " + (taskName.replace("ping", "")))
            }
        }
    }
}

自定義Task模版

定義簡單的task Class

open class GreetingTask : DefaultTask() {
    var greeting = "hello from GreetingTask"
        //TaskAction中寫task的具體執(zhí)行邏輯平挑,此方法是在執(zhí)行階段執(zhí)行
    @TaskAction
    fun greet() {
        println(greeting)
    }
}

tasks.register<GreetingTask>("hello")

通過setter方法配置task

tasks.register<GreetingTask>("greeting") {
    //配置greeting參數(shù)
    greeting = "greetings from GreetingTask"
}

通過構造方法配置task

open class GreetingTask() : DefaultTask() {
    var greeting = "hello from GreetingTask"

    @javax.inject.Inject
    constructor(greeting: String) : this() {
        this.greeting = greeting
    }

    @TaskAction
    fun greet() {
        println(greeting)
    }
}
//直接傳遞構造函數(shù)的參數(shù)
tasks.register<GreetingTask>("greeting", "hello gradle")

通過命令行選項配置task

open class GreetingTask() : DefaultTask() {
    @Option(option = "m", description = "配置greeting文本")
    var greeting = "hello from GreetingTask"

    @TaskAction
    fun greet() {
        println(greeting)
    }
}

tasks.register<GreetingTask>("greeting")
//執(zhí)行命令gradlew greeting -m hellogradle

增量構建

為了提升Gradle的構建效率游添,避免進行重復的工作,Gradle引入了增量構建的概念通熄。

在大多數(shù)情況下唆涝,task一般都會包含輸入和輸出,以Gradle通關系列(三)中的ZipResTask為例唇辨,資源文件就是輸入廊酣,打包的zip文件就是輸出。 如果多次執(zhí)行一個Task時的輸入和輸出是一樣的赏枚,那么我們便可以認為這樣的Task是沒有必要重復執(zhí)行的 亡驰。 每個Task都擁有inputs和outputs屬性,他們的類型分別為TaskInputs和TaskOutputs饿幅。 在增量式構建中凡辱,我們可以為每個Task定義輸入(inputs)和輸入(outputs),如果在執(zhí)行一個Task時栗恩,如果它的輸入和輸出與前一次執(zhí)行時沒有發(fā)生變化透乾,那么Gradle便會認為該Task是最新的(UP-TO-DATE),因此Gradle將不予執(zhí)行磕秤。一個Task的inputs和outputs可以是一個或多個文件乳乌,可以是文件夾,還可以是Project的某個Property市咆,甚至可以是某個閉包所定義的條件 汉操。

改造ZipResTask為增量構建

//custom_build.gradle.kts
import org.gradle.kotlin.dsl.support.zipTo

open class ZipResExtensions {
    var resPath: String = ""
    var outputPath: String = ""
}

extensions.create<ZipResExtensions>("zipRes")

abstract class ZipResTask : DefaultTask() {
    @get:InputDirectory
    abstract val resDir: Property<File>

    @get:OutputFile
    abstract val outputFile: Property<File>

    @TaskAction
    fun zipRes() {
        zipTo(outputFile.get(), resDir.get())
    }
}

tasks.register("zipRes", ZipResTask::class)

afterEvaluate {
    tasks.named("zipRes", ZipResTask::class) {
        val zipResExtensions = project.extensions.getByName<ZipResExtensions>("zipRes")
        resDir.set(file(zipResExtensions.resPath))
        outputFile.set(file(zipResExtensions.outputPath))
    }
}

執(zhí)行zipRes的輸出情況

第一次執(zhí)行

16:39:11: Executing task 'zipRes'...

> Task :zipRes

BUILD SUCCESSFUL in 88ms
1 actionable task: 1 executed
16:39:11: Task execution finished 'zipRes'.

第二次執(zhí)行

16:39:57: Executing task 'zipRes'...

> Task :zipRes UP-TO-DATE

BUILD SUCCESSFUL in 83ms
1 actionable task: 1 up-to-date
16:39:57: Task execution finished 'zipRes'.

沒有改動就是直接跳過該task的執(zhí)行,后面標記UP-TO-DATE

總結

task是Gradle構建的最小原子工作蒙兰,我們需要會創(chuàng)建task磷瘤、并配置它其弊、調整各種task之間的依賴來完成我們的構建

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市膀斋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌痹雅,老刑警劉巖仰担,帶你破解...
    沈念sama閱讀 212,332評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绩社,居然都是意外死亡摔蓝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評論 3 385
  • 文/潘曉璐 我一進店門愉耙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贮尉,“玉大人,你說我怎么就攤上這事朴沿〔卵瑁” “怎么了?”我有些...
    開封第一講書人閱讀 157,812評論 0 348
  • 文/不壞的土叔 我叫張陵赌渣,是天一觀的道長魏铅。 經常有香客問我,道長坚芜,這世上最難降的妖魔是什么览芳? 我笑而不...
    開封第一講書人閱讀 56,607評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮鸿竖,結果婚禮上沧竟,老公的妹妹穿的比我還像新娘。我一直安慰自己缚忧,他們只是感情好悟泵,可當我...
    茶點故事閱讀 65,728評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搔谴,像睡著了一般魁袜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敦第,一...
    開封第一講書人閱讀 49,919評論 1 290
  • 那天峰弹,我揣著相機與錄音,去河邊找鬼芜果。 笑死鞠呈,一個胖子當著我的面吹牛,可吹牛的內容都是我干的右钾。 我是一名探鬼主播蚁吝,決...
    沈念sama閱讀 39,071評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼旱爆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窘茁?” 一聲冷哼從身側響起怀伦,我...
    開封第一講書人閱讀 37,802評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎山林,沒想到半個月后房待,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,256評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡驼抹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,576評論 2 327
  • 正文 我和宋清朗相戀三年桑孩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片框冀。...
    茶點故事閱讀 38,712評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡流椒,死狀恐怖,靈堂內的尸體忽然破棺而出明也,到底是詐尸還是另有隱情宣虾,我是刑警寧澤,帶...
    沈念sama閱讀 34,389評論 4 332
  • 正文 年R本政府宣布温数,位于F島的核電站安岂,受9級特大地震影響,放射性物質發(fā)生泄漏帆吻。R本人自食惡果不足惜域那,卻給世界環(huán)境...
    茶點故事閱讀 40,032評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望猜煮。 院中可真熱鬧次员,春花似錦、人聲如沸王带。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愕撰。三九已至刹衫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搞挣,已是汗流浹背带迟。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囱桨,地道東北人仓犬。 一個月前我還...
    沈念sama閱讀 46,473評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像舍肠,于是被迫代替她去往敵國和親搀继。 傳聞我的和親對象是個殘疾皇子窘面,可洞房花燭夜當晚...
    茶點故事閱讀 43,606評論 2 350

推薦閱讀更多精彩內容