With no ‘<<’, you are running that closure in the configuration phase of Gradle. This means that it runs everytime you do a build, regardles of the tasks you execute.
With the ‘<<’, you are adding a ‘doLast’ action which would run as the last thing the task does (i.e. after it runs the command specified on the ‘Exec’ task).
The failure seems suspicious to me (given the ‘buildToc’ name vs. the ‘buildFoo’ name). If those are really separate tasks the ‘<<’ on ‘buildFoo’ should have absolutely no effect.
If I change the script to use << (the only change)
task foo(type:Exec) << {
Now I see that foo fails, but when building notfoo it is no longer printing out == foo ==
~/tmp %> gradle foo :foo FAILED
FAILURE: Build failed with an exception.
What went wrong: Execution failed for task ‘:foo’. > execCommand == null!
Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 0.998 secs
~/tmp %> gradle notfoo :notfoo == notfoo ==
BUILD SUCCESSFUL
Total time: 0.981 secs
The real question is whether the foo task exec command runs when building notfoo, or is everything except the actual exec run?
It feels like thers’s an inconsistency in the use of << for exec tasks.
Is it that the exec task body is just setup and nothing actually runs until later ? In which, case, when does the exec run, when the doLast is invoked?
No inconsistency, ‘Exec’ tasks work the same as any other task you would have tried to configure. It’s all about how Gradle processes the build script.
When you run a build, Gradle goes through 3 phases. There’s a pretty good example in the 55.2 section of the Build Lifecycle chapter in the user guide.
Here’s another take on it:
task foo(type: Exec) {
// this is configuration
// i.e. it runs regardless
}
task bar(type: Exec) << {
// this is execution
// i.e. it only runs if you call the task
}
Your task fails because ‘<<’ (i.e. ‘doLast’) adds an action that won’t be run until after the Gradle tries to execute the command specified by the ‘Exec’ task. Because you put the ‘commandLine ‘/bin/ls’’ in the ‘doLast’, Gradle wouldn’t know what command to run until after it tries to run it. Hence the failure.
The only times I find it makes sense to use ‘<<’ are on a one-off task:
task myfoo << {
// do some stuff when this executes
}
Otherwise, for a typical task like ‘Exec’ you are almost certainly going to have to configure it first. If you have additional actions to run, you might as well just call ‘doLast’ later:
A problem occurred configuring project ‘:MY.lib’. > Exception thrown while executing model rule: org.gradle.nativebinaries.plugins.NativeComponentModelPlugin$Rules#configureGeneratedSourceSets(org.gradle.language.base.ProjectSourceSet)
Could not find property ‘sourceDir’ on task ‘:MY.lib:generateCPPStubs’.
Could you please give any pointer what is missing here