Tasks dependencies

Hi -

I just ran into a snag with task dependencies and I am almost certain it shouldn’t be working that way.

So in my build, I have the following…

task a << { println "task a" }
task b << { println "task b" }
task c << { println "task c" }
  task mytask(dependsOn: ['b', 'c', 'a'])

When I execute gradle -m mytask, I get this…

:a SKIPPED
:b SKIPPED
:c SKIPPED
:mytask SKIPPED

Notice task a is executed first even though I have specified it should run last! So it seems when I pass a list of task dependencies, gradle is ordering/sorting the list before executing the tasks. I don’t think that should be the case. The order of the list of dependencies should be maintained in the order specified by the user and executed in that order.

I have tried the same in gradle versions 1.8, 1.9 and 1.10. All behave the same way.

Please advice.

Thanks

You haven’t specified that ‘b’ has to run before ‘a’. Your build script merely states that ‘mytask’ depends on all the listed tasks. The order of the task names passed to dependsOn doesn’ matter.

If you need to order tasks, use ‘mustRunAfter’ or ‘shouldRunAfter’.

Thanks Luke. I did run into that part in the docs i.e. ordering tasks execution and it is still an incubating feature, so was a bit hesitant to use it.

I also have put a work around in my project, i.e.

c.dependsOn b
a.dependsOn c
  task mytask(dependsOn: ['a'])

It just seemed like a bug to me to have the tasks dependencies ordered before execution. Mainly out of curiosity, is there any reason behind that?

is there any reason behind that?

Yes, this is a long heavily debated topic :slight_smile:

The fundamental reason is that…

task foo {
  dependsOn a,b,c
}

Doesn’t actually say anything about the relationship between a, b and c. Does the user want them in order? Or is that just how they wrote it? Why do they have that order? Does that mean they can’t run in parallel? Is it ok for Gradle to use a different order if there is a good reason?

In short, it’s not rich enough and if taken literally prevents Gradle from making other optimisations.

‘mustRunAfter’ etc. have strong semantics that give Gradle the information it needs.

Ok. Thanks for clearing the air. The new things we learn daily :wink: