Posted at

Gradle で動的にタスクを定義する (環境ごとのビルド構成定義に便利!)

More than 3 years have passed since last update.

Gradle でタスクを定義するといえば


build.gradle

task buildAll() {

...
}

という風に記載すると思いますが,動的に定義する方法です.基本的にリファレンスそのままですが,自分が触ってみてハマったところについても言及しつつ…


build.gradle

["Foo", "Bar", "Buz"].each { name ->

task "build$name" << {
println "$name"
}
}

これで gradle tasks をすると,以下のように出てきます.

Screen Shot 2016-03-09 at 10.55.47 PM.png

実行したら,こんな感じになります.

Screen Shot 2016-03-09 at 10.59.33 PM.png

上記の例では配列で Foo, Bar, Buz を宣言していましたが,設定ファイルなどで定義して,環境ごとの設定ファイルを見るディレクトリを指定する,といった使い方が出来そうです.


動的に定義したタスク間の依存

動的に定義したタスクの間で依存を定義することも出来ます.


build.gradle

task common {

println 'common'
}

["Foo", "Bar", "Buz"].each { name ->
task "copy$name"(type: Copy) {
from "src/$name/resources"
into "build/src/$name/resources"
}

task "zip$name"(type: Zip, dependsOn: "copy$name") {
from task["copy$name"]
baseName "dist-$name"
destinationDir file(buildDir)
}

}


これを実行したら以下のようになります.

Screen Shot 2016-03-09 at 11.10.49 PM.png

現在はすべて UP-TO-DATE ですが… zipFoo は copyFoo に,zipBuz は copyBuz に依存していて,copy タスクは common に依存しています.


タスク内容を実行フェーズで実行するとうまくいかないことがある.

見出しの通りですが,


build.gradle

task "copy$name" << {

copy {
from somewhere
into another
}
}

task "zip$name"(type: Zip) {
from tasks["copy$name"]
}


上記のように,copy$name のアウトプットが出来る場所が実行フェーズにならないとわからないような場合,zip$name が依存する copy$name は常に UP-TO-DATE になってしまいます.しかも,outputs.upToDateWhen {false} にしても効かない!ので気をつけてください.