2週間ぶりですが前回のつづきです。
[dependsOn()]
タスクへの依存関係を定義する方法としてdependsOn()がある。
これまでに学んできたところでは、dependsOn()にタスクを渡す方法としては以下のものがあった。
- タスク名を文字列で指定する
tasks.register("taskY") { println("taskY") } tasks.register("taskX") { dependsOn("taskY") }
- 委譲プロパティを利用して定義したタスクを渡す
val taskY by tasks.registering { doLast { println("taskY") } } tasks.register("taskX") { dependsOn(taskY) } tasks.register
tasks
コレクションから型指定で取得する
tasks.register("taskX") { dependsOn(tasks.withType<Copy>()) }
[プロバイダからタスクを取得する]
これに加えて、プロバイダからタスクを取得して、dependsOn()
に渡すこともできる。
val taskX by tasks.registering { doLast { println("taskX") } } taskX { dependsOn(provider { // 「lib」という名前で始まるタスクのみ取得 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") } }
上記の実行結果は以下のようになる。
$ gradle -q taskX lib1 lib2 taskX
ここで使われているproviderはどうやらこのクラスらしい。
何かしらの値を提供するインターフェース、ということらしい。
典型的な使い方は、エクステンションからタスクに値を渡すほか、複雑な計算を遅延させて、タスクが実行され必要になるときに値を渡すこともできるようだ。
[タスクの実行順序を指定する]
Gradleのタスクは、gradle taskX taskY
のように複数のタスクをまとめて実行できる。
その際、mustRunAfter()
またはshouldRunAfter()
を利用することで、実行順序を指定できる。この場合、実行順序を指定するだけなので、タスク間に依存関係はなく、従ってそれぞれのタスクを独立して実行することが可能だ。
val taskX by tasks.registering { doLast { println("taskX") } } val taskY by tasks.registering { doLast { println("taskY") } } taskY { mustRunAfter(taskX) // taskYは必ずtaskXの後に実行する }
上記のコードを実行すると以下のようになる。
$ gradle -q taskY taskX taskX taskY
shouldRunAfter()
の場合は、以下の2つの場合に無視されるので、厳密な実行順序が必要ない場合に利用するとよい。
- 実行順序の循環が発生する場合
- タスクが並列実行され、全てのタスクの依存関係が満たされている場合
循環が発生するのは以下のような場合である。このコードでは、taskXを実行する前にtaskYが実行され、taskYの前にtaskZが実行される必要があり、かつ、taskZはtaksXのあとに実行されるべし、となっておりtaskXが先かtaskZが先かという問題が生じてしまっている。
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 // shouldRunAfterは無視される taskY taskX
上記のshouldRunAfter()
を、mustRunAfter()
に変更してtaskXを実行すると、以下のよう依存関係が循環し、ビルドが失敗となる。
$ gradle -q taskX FAILURE: Build failed with an exception. * What went wrong: Circular dependency between the following tasks: :taskX \--- :taskY \--- :taskZ \--- :taskX (*) (*) - details omitted (listed previously) * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 672ms
[まとめ]
- タスクの依存関係を追加する方法として、provider経由で処理をタスク実行時まで遅延させられる
- タスクの実行順序指定にmustRunAfter()とshouldRunAfter()が利用できる
- タスクの依存関係と実行順序で循環参照が発生するとビルドが失敗する
- サンプルコードは以下のリポジトリにまとめてある