The build below is printing Second before First. I find it weird, as I thought that the onjects are initialized before they are added to the domain collection.
tasks.addRule("...") { taskName ->
task(taskName, type: JavaExec) {
ext.foobar='bazqux'
println "First ${it}(${ext.properties})"
}
}
p.tasks.withType(JavaExec).all { task ->
println "Second $task($task.ext.properties)"
def c = configurations.maybeCreate("baz${task.foobar}") // fails here - foobar is not set yet
task.outputs.files.each { f ->
p.artifacts.add(c.name, [file: f, builtBy: task])
}
}
Considering this, is there a good pattern to write a rule that depends on a task init state? The use-case is to have a reactive plugin which responds to the settings of another plugin maintained by a separate team.
How annoying. It seems that Gradle is doing the following
Creating the task
Adding the task to the TaskContainer (DomainObjectCollection)
Running the configuration closure to configure the task
It seems logical that 3 should occur before 2 but that’s not the case based on your printlns. This seems like a bug to me, but fixing it might cause regressions.
Or more likely, Gradle asks the container to create the object, so the factory can decorate and inject it before we see it. The container decides that while we are at it, why not run the rules too…
We find it counterintuitive only because we perceive the closure at creation to have the semantics of a constructor, while in fact it is more like a convenient init method.
Fwiw I don’t think that strengthening the semantics of the construction initializer should break many things - the ordering is not guaranteed anyway, and I would doubt there are cases where the init closure depends on values set by the rules. If there is a case where it overrides values set by the rules, that is easily fixable by adding a check in the rule.
In other words - a perfect candidate for late addition to 6.0
The problem is that tasks.withType(...) adds a listener to the collection. As soon as a task is added to the collection, your listener will fire. Ideally gradle would add the Task to the collection after running the configuration closure. But it seems that it adds it to the collection before (so your listener fires early).