Gradle タスクの直列実行を Collection.inject() で書いてみる
非同期処理の直列実行を Array.reduce() で書いてみる - GeekFactory と同じことを Gradle (Groovy) でやってみます。
Gradle で複数のタスクの依存関係を定義するケースを考えます。Task.dependsOn を使って複数のタスクを指定した場合、タスクの順序は保証されません。例えば、下記のように3つのタスクに対して依存関係を定義してみます。
task somethingA << { println 'A' } task somethingC << { println 'C' } task somethingB << { println 'B' } task something { dependsOn somethingA, somethingC, somethingB }
something タスクを実行すると下記のようになります。dependsOn で指定したものとは異なる順序で実行されています。なお、環境やバージョンによっては結果が違うかもしれません。
:somethingA A :somethingB B :somethingC C :something
タスクの直列化
では、複数のタスクを順序付けして実行するにはどうすればよいでしょうか。タスク間に依存関係のチェーンを定義してみましょう。
task somethingA << { println 'A' } task somethingC << { println 'C' } task somethingB << { println 'B' } task something {} somethingC.dependsOn somethingA somethingB.dependsOn somethingC something.dependsOn somethingB
something タスクを実行すると下記のようになります。意図した順序で実行されていることが分かります。
:somethingA A :somethingC C :somethingB B :something
一般化
タスクのリストに一般化してみましょう。タスクの実行順序を設定する configureSequentialDependencies() 関数を書いてみます。
/** * Configure task dependencies to be executed sequentially. * * @param top top of chain * @param tasks */ void configureSequentialDependencies(Task top, List<Task> tasks) { tasks.reverse().inject(top) { x, y -> x.dependsOn y y } } configureSequentialDependencies(something, [somethingA, somethingC, somethingB])
これで任意のタスクに対して実行順序制約を設定できるようになりました。
スクリプトに書いた順にタスクを実行したいケースは意外とよくあるので、きっと役に立つと思います。