まくまくGradleノート
Gradle でタスクの依存関係を表現する
2021-02-03

タスク間に依存関係を設定する

org.gradle.api.Task オブジェクトの dependsOn メソッド を使用することで、タスク間に依存関係を持たせることができます。

方法1)タスク定義時の引数で依存定義する

タスク定義時の dependsOn 引数(厳密にはマップキー)でタスク間の依存関係を設定することができます。 次の例では、hello1 タスクに依存する hello2 タスクを定義しています。

build.gradle

task hello1 {
    doLast { println 'Hello 1' }
}

task hello2(dependsOn: hello1) {
    doLast { println 'Hello 2' }
}

hello2 タスクを実行するときに、先に hello1 タスクが実行されるようになります。

$ gradle -q hello2
Hello 1
Hello 2

方法2)Configure クロージャ内で依存定義する

タスク定義時の Configure クロージャ内で dependsOn メソッドを呼び出して依存関係を指定することができます。

task hello1 {
    doLast {
        println 'Hello 1'
    }
}

task hello2 {
    dependsOn hello1
    doLast {
        println 'Hello 2'
    }
}

方法3)タスク定義後に依存を追加する

すでに定義済みのタスク(Task オブジェクト)の dependsOn メソッドを呼び出すことで、後付けで依存関係を追加することができます。

task hello1 {
    doLast { println 'Hello 1' }
}

task hello2 {
    doLast { println 'Hello 2' }
}

hello2.dependsOn hello1

まだ定義されていないタスクを依存関係に追加する

hello2.dependsOn hello1

のように依存関係を追加するときに、hello1 というオブジェクト名で参照できているのは、hello1 タスクがすでに定義済みで、Project オブジェクトの hello1 プロパティとして参照可能になっているからです(Configuration フェーズでは上から順番に処理されていくので、hello1 タスクの定義が上に記述されている必要があります)。

まだ定義されていないタスクを依存先に設定するには、その タスク名を文字列で指定 します。 次の例では、hello1 タスクの依存先として、まだ定義されていない hello2 タスクを指定しています。

task hello1 {
    dependsOn 'hello2'
    doLast { println 'Hello 1' }
}

task hello2 {
    doLast { println 'Hello 2' }
}

複数のタスクに依存するタスクを定義する

複数タスクへの依存

複数のタスクに依存するタスクを定義することもできます。 下記の例では、hello1 タスクと hello2 タスクの両方に依存する hello3 タスクを定義しています。

build.gradle

task hello1 { doLast { println 'Hello 1' }}
task hello2 { doLast { println 'Hello 2' }}
task hello3 { doLast { println 'Hello 3' }}

hello3.dependsOn hello1, hello2

Task#dependsOn メソッドは、依存関係を 追加する ためのメソッドなので、次のように別々に依存関係を追加しても同様です。

hello3.dependsOn hello1
hello3.dependsOn hello2

また、次のように同じ依存関係を何度追加しても、依存するタスクが呼び出されるのは 1 回だけです。

hello3.dependsOn hello1
hello3.dependsOn hello1
hello3.dependsOn hello1

タスク定義時の dependsOn パラメータでも複数の依存関係を指定することができます。

task hello1 { doLast { println 'Hello 1' }}
task hello2 { doLast { println 'Hello 2' }}
task hello3(dependsOn: [hello1, hello2]) {
    doLast { println 'Hello 3' }
}

上記のように依存関係を定義することで、hello3 タスクの実行前に hello1 タスクと hello2 タスクが実行されることが保証されます。

実行結果

$ gradle hello3
Hello 1
Hello 2
Hello 3

タスクの実行順序の制御

上記のように Task#dependsOn メソッドで、2 つ以上のタスク(hello1hello2)に依存する hello3 タスクを定義することができました。 しかし、この指定だけでは hello1 タスクと hello2 タスクの実行順序までは保証されない ということに注意してください。 こういった緩い制約になっていることで、Groovy のタスクの多くは並列実行することが可能になっています。

仮に、必ず hello1hello2hello3 の順番で実行しないといけないのであれば、次のように hello1hello2 の依存関係を定義するという方法があります。

task hello1 { doLast { println 'Hello 1' }}
task hello2(dependsOn: hello1) { doLast { println 'Hello 2' }}
task hello3(dependsOn: hello2) { doLast { println 'Hello 3' }}

ただし、こうすると、hello2 タスクの実行時にも必ず hello1 タスクが実行されることになってしまいます。

$ gradle -q hello2
Hello 1
Hello 2

$ gradle -q hello3
Hello 1
Hello 2
Hello 3

hello3 タスクの実行にのみ、hello1hello2hello3 の順番で実行するには、次のように Task#mustRunAfter メソッドを使います。

task hello1 { doLast { println 'Hello 1' }}
task hello2 { doLast { println 'Hello 2' }}
task hello3 { doLast { println 'Hello 3' }}

hello2.mustRunAfter hello1
hello3.dependsOn hello1, hello2

これで、hello2 タスクの単独実行時には hello1 タスクを実行しないで済みます。

$ gradle -q hello2
Hello 2

$ gradle -q hello3
Hello 1
Hello 2
Hello 3
2021-02-03