What's the difference between mustRunAfter and dependsOn in Gradle?
Solution 1:
For example:
tasks.create('a')
tasks.create('b').dependsOn('a')
tasks.create('c')
tasks.create('d').mustRunAfter('c')
-
dependsOn
- sets task dependencies. Executingb
here would require thata
be executed first. -
mustRunAfter
- sets task ordering. Executingd
does not requirec
. But, when bothc
andd
are included,c
will execute befored
.
Solution 2:
Sometimes they have the same effect. For example, if taskC dependsOn taskA and taskB, then it doesn't matter whether taskB dependsOn taskA or mustRunAfter it - when you run taskC, the order will be taskA, taskB, taskC.
But if taskC dependsOn taskB only, then there's a difference. If taskB dependsOn taskA, then it's the same as above - taskA, taskB, taskC. If taskB merely mustRunAfter taskA, then taskA doesn't run, and running taskC will run taskB, then taskC.
mustRunAfter really means if taskA runs at all, then taskB must run after it.
Solution 3:
Where possible, declare task inputs instead of task dependencies. That said, expanding on mkobit's answer:
Ordering and dependencies involving two tasks
mustRunAfter
mustRunAfter
controls the execution order of tasks explicitly specified on the command line, but doesn't create implicit dependencies on other tasks. Given taskA
and taskB
:
build.gradle.kts
val taskA by tasks.registering {
doLast {
println("taskA")
}
}
val taskB by tasks.registering {
doLast {
println("taskB")
}
}
taskB {
mustRunAfter(taskA)
}
then
-
gradle taskB taskA
executestaskA
followed bytaskB
; -
gradle taskA
executestaskA
only; -
gradle taskB
executestaskB
only.
dependsOn
dependsOn
creates implicit dependencies on other tasks. Given the same two tasks:
taskB {
dependsOn(taskA)
}
then
-
gradle taskB
executestaskA
followed bytaskB
; -
gradle taskB taskA
executestaskA
followed bytaskB
; -
gradle taskA
executestaskA
only.
Ordering and dependencies involving three tasks
mustRunAfter
and dependsOn
accept an unordered collection of tasks. Given:
val taskC by tasks.registering {
doLast {
println("taskC")
}
}
taskC {
dependsOn(taskA, taskB)
}
then gradle taskC
executes taskA
and taskB
in no guaranteed order, followed by taskC
(assuming no other dependsOn
or mustRunAfter
declarations).
mustRunAfter
also controls the execution order between interdependent tasks that would otherwise have no guaranteed order. Given:
taskB {
mustRunAfter(taskA)
}
then gradle taskC
executes taskA
followed by taskB
followed by taskC
, but gradle taskB
only runs taskA
because taskB does not dependOn(taskA)
.
Other types of task dependency
-
taskA { finalizedBy(taskB) }
ensuresgradle taskA
executestaskA
followed bytaskB
; -
shouldRunAfter
provides weaker ordering guarantees thanmustRunAfter
, useful for breaking cyclic dependencies and parallel task execution.
Further reading
Consult the Gradle documentation for more information on:
- adding dependencies to tasks
- ordering tasks
- skipping tasks