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