kdnakt blog

hello there.

Gradleのタスクの理解を深める

前回の基本編に続けて、さらにGradleタスクについて理解を深める。

kdnakt.hatenablog.com

 

今日の教材はこちら。

docs.gradle.org

 

 

[委譲プロパティによるタスク定義]

前回学んだ方法では、tasks.named()APIを利用して、別で定義されたタスクにアクションを追加したり、依存関係を追加したりした。

tasks.register("taskX") {
    doLast {
        println("Hello Earth")
    }
}
tasks.named("taskX") {
    doFirst {
        println("Hello Venus")
    }
}
tasks.register("taskY") {
    doLast {
        println("taskY")
    }
}
tasks.named("taskX") {
    dependsOn("taskY")
}

 

別のやり方として、Kotlinの委譲プロパティ(Delegated property)を利用してタスクを定義したり変更したりすることもできる。

val hello by tasks.registering {
    doLast {
        println("hello")
    }
}

 

この場合、プロパティ名がタスク名になるので、gradle -q helloでタスクを呼び出せる。

$ gradle -q hello
hello

 

GradleのCopyタスククラスを利用してmyCopyタスクを設定する場合、以下のようになる。

// 通常のタスク定義
tasks.register<Copy>("myCopy") {
    from(file("srcDir"))
    into(buildDir)
}

// 委譲プロパティによるタスク定義
val myCopy by tasks.registering(Copy::class) {
    from(file("srcDir"))
    into(buildDir)
}

 

委譲プロパティを利用して定義したタスクについても、依存関係を後から定義することができる。

val taskX by tasks.registering {
    doLast {
        println("taskX")
    }
}

val taskY by tasks.registering {
    doLast {
        println("taskY")
    }
}

taskX {
    dependsOn(taskY)
}

 

上記のtaskXを実行すると、以下のように出力される。

$ gradle -q taskX
taskY
taskX

 

tasks.named()を利用するより多少コードがスッキリする気がする。

厳密には、named()に該当するexisting()というメソッドがあり、既存タスクを委譲プロパティにとることができる。

// タスク定義
tasks.register<Copy>("myCopy")    

// 既存タスクを委譲プロパティで設定変更
val myCopy by tasks.existing(Copy::class) {
    from("resources")
    into("target")
}

// さらに設定変更
myCopy {
    include("**/*.txt", "**/*.xml", "**/*.properties")
}

 

[タスクのコンストラクタ]

タスクはKotlinのクラスとしても実装できる。

abstract class CustomTask @Inject constructor(
    private val message: String,
    private val number: Int
) : DefaultTask()

tasks.register<CustomTask>("myTask", "hello", 42)

 

Gradleプラグインを自作したときに似たような記法をしたのを思い出した。

kdnakt.hatenablog.com

 

これだけだとタスクを実行しても何も起きないので、以下のようにカスタムタスクの挙動を追加した。

abstract class CustomTask @Inject constructor(
	private val message: String,
	private val number: Int
): DefaultTask() {
	@TaskAction
	fun doSomething() {
		println("$message: $number")
	}
}

 

ここでmyTaskを実行すると、予想通り以下のようになった。

$ gradle -q myTask
hello: 42

 

[まとめ]

  • build.gradle.ktsでの委譲プロパティを利用したタスク定義ができる
  • Gradleがデフォルトで提供しているタスク定義クラス(Copyなど)がある
  • カスタムタスクを実装してコンストラクタでプロパティを設定できる
  • サンプルコードは以下のリポジトリにまとめてある  

github.com