Wednesday, November 7, 2012

Anatomy of a Gradle Task: Execution Time

So I'm trying out gradle in the hope of being able to simplify and streamline an existing maven build which is quite large and inconsistent. And I just spent some time to figure out a few gotcha about gradle tasks and this post is to help others understand, because I think the gradle docs aren't clear enough on this point

What I wanted to achieve is, to copy all *.properties files in src/main/java to the resources-output directory so they are included in the jar, because javac won't pick them up since they're no java source files. What happened was that, depending on what approach I tried, sometimes the copy worked sometimes it didn't and I couldn't understand why.

Except for the first example in the gradle docs, which uses doLast, each example uses "<<". Compare the following two equivalent definitions of the hello task.

Loading ....

Let's dissect it real quick. We have a Closure that prints "Hello World". In the first example, it is passed as a parameter to the "doLast" method of the Task (Remember: methods in groovy can be called without parentheses so it's equivalent to "doLast({...})" which should make the method call clear). I suspect this method appends the closure to some ordered collection for later execution. The second example that uses "<<" uses an overloaded operator which in the end just calls doLast and ends up having the same effect. This Closure, and that's the important thing to take away here: is executed at build time.

Compare this with this third example which is like the first but without the "doLast" part.

Loading ....

This snippet, however, will print "Hello World" right away since it is executed at configuration time.

So putting it all together, my copy ended up looking like this (printlns will be removed or replaced with logging later):

Loading ....

This will configure the copy task right away (all the paths seem precalculated at he beginning so referencing them at configure time is save).

To conclude: The "<<" shortcut is great in some situations but I think it can be quite dangerous since it's just 2 characters that separate two entirely different behaviours. So the gradle syntax is terse and expressive but you really have to understand what you're intending to do and also be mindful of what a task does when reading a gradle script, since the differences can be quite subtle.

Update: The Javadoc of the Task actually describes this and probably much better than I can

.

No comments:

Post a Comment