4) I would like to be able to specify that a chain of dependent tasks only execute a task if Task.didWork is true for all of its dependents. Note that this is not always desired, so you need to be able to turn this on and off. I'm not sure of the best way to configure this. If we use the onlyIf method suggested above, it might take another closure to check this that would be returned from a "needed" method. This would look like:
 myTask.onlyIf(needed())

This probably should be the default for tests, but perhaps not for all Tasks.


I'm not sure about this approach.

The tests should run if either the test classes or the classes under test have changed since last time we successfully ran the tests. Arguably a change to the test runtime classpath should also cause the tests to run. In other words, the tests should be run only if the input artifacts have not changed since last time we ran the tests. Checking whether all the dependencies of the test task have executed or not is only an approximation of this, and not a general solution. For example, if I assemble my classes under test using, say, 2 independent Compile tasks, then the test task should run if either task has done something. Or, I may assemble my classes using some other build tool, so that there's no task which we can use to check whether or not the classes have changed.

To me, the key to task optimisation is to base it on the input and output artifacts of a task. If we make it easy to declare both the input and output artifacts of a task, we make the model much richer, and from this we get a lot of goodness.

For example, if we know what the input artifacts for a task are, Gradle can apply change detection to those input artifacts on the task's behalf. If we also know which tasks produce those artifacts, then Gradle can optimise the change detection. Gradle could, for example, when it knows which task produces a given artifact, simply use the fact that the producer task executed an action or not to decide whether the input artifacts have changed, and only fall back to hashing or timestamps or a Java 7 file watcher or whatever when it doesn't know how the artifact is produced. Similarly, it could use the fact that a Jar was downloaded by the dependency management system to decide whether the input artifacts have changed.


This is very interesting. I'm just trying to play a little with some terminology. There are output-affecting input values (e.g. classpaths, src dirs, compiler options, ...) and also some non-output-affecting input values like log level. The output affecting input values can be subdivided into belonging to something like an Outputter and something like plain input values. Outputters can tell if they did some work, for plain input values the task needs its own history and change detection management. By providing a rich domain model important types of plain input values can be turned into outputters (e.g. SourceDir). And for a subset of the remaining range of input value types we should be able to provide a nice toolkit that makes it easy to define change detection.

With the above model, the default behavior of onlyIf is inputValues.haveChanged == true

There are also scenarios like: This task should not be executed on Friday. I think they don't fit into the input value model. So we still need to accommodate custom onlyIf rules.

One of the interesting issues is to make it easy to write such tasks.

Adding input and output artifacts to the model also lets us use this information to build the DAG, and to be smart about skipping tasks. For example, if the test task were to declare that it uses the tests classes directory and the test runtime configuration as input artifacts, then Gradle would be able to automatically add the tasks that produce these (if any) to the task dependencies of the test task.

One things that comes to my mind is a scenario, that two tasks output into classesDir. But a third tasks only wants to be dependent on one of those other tasks. Yet I see your point. It is a very interesting question how to integrate the concepts of the input/output model with the DAG model. Again, a richer domain model can help. If the test tasks declares to use for example a SourceDir object as an input value, my scenario from above could easily be solved. But you could ask why not declaring a dependsOn relation from test to SourceDir? I think this is basically what we do with this new input model, with the difference that it is more specific. Instead of just providing a dependsOn method, an input value of type SourceDir could be translated into: This is a dependsOn for the purpose of having the classpath of the production code in the runtime classpath of the tests.

- Hans

--
Hans Dockter
Gradle Project Manager
http://www.gradle.org


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email


Reply via email to