Hi,
I've made a few changes to how you implement tasks over the last month
or so. Here's a bit of a summary, with some questions at the end.
1. You don't need to provide a constructor any more.
We now inject the project and name around the side directly into
AbstractTask. This means we can also inject other things, such as the
OutputHandler, without exposing this to the task implementations.
2. You can mark the 'main' method of a task with the @TaskAction
annotation. It automatically gets added as a task action.
3. There's some documentation:
http://gradle.org/latest/docs/userguide/custom_tasks.html
4. You can mark the input and output properties of a task using annotations:
@InputFile
public File getConfigFile()
@InputDirectory
public File getTestClassesDir()
@InputFiles
public Iterable<File> getSourceDirs()
@OutputFile
public File getReportFile()
@OutputDirectory
public File getDestinationDir()
Currently, we use these annotations to apply some validation to the task
properties. The validation is added as a task action, so it is performed
just before the task is executed:
@InputFile/@InputDirectory: Check the property is not null, and the
specified file exists and is a file/directory
@InputFiles: Check the property is not null.
@OutputFile/@OutputDirectory: Check the property is not null, and that
the specified file can be created as a file/directory. Also create the
parent dir if it does not exist.
There's also an @Optional annotation, which switches off the not-null
check, and a @SkipWhenEmpty, which skips the task if the associated
@InputFiles property is an empty FileCollection.
I'd like to use these annotations to also:
- Wire up dependencies. For example, we know that build/classes/main is
an output file of both the compileTest and processTestResources tasks,
and an input file of the test task, so we could automatically add the
these as dependencies of the test task. We also know that the classpath
of the test task is actually the testRuntime configuration, so we could
automatically add its buildDependencies to the test task.
That is,
task intTests(type: Test) {
testClassesDir = source.intTests.classesDir // auto add
compileIntTest and processIntTestResources
classpath = configurations.testRuntime // auto add
testRuntime.buildDependencies
}
- Apply optimisation. For example, we know that build/classes/main and
testRuntime are input files of the test task, and that
build/reports/test is an output dir of the test task. We can skip test
if its input files have not changed since it last executed successfully
and if its output dir exists and is not empty. We can decide whether its
input files have changed by hashing them, or using their timestamps, or
the last successful execution time of the tasks which produce those files.
One question I have is how to apply this to task actions which are added
to the task as closures:
task intTests(type: Test)
intTests.doFirst {
.. some setup ..
}
or
task explodedDistBase << {
.. copy some stuff ..
}
One option is to allow you to declare the input and output files of a task:
task explodedDistBase(inputDirs: source.main.groovySrcDirs, outputDir:
distDir) << {
copy { from inputDirs; into outputDir }
}
where 'inputFile', 'inputDirs', 'inputFiles', 'outputDir', etc
correspond to the @InputFile annotation, etc, and are added as
properties of the task.
Another question is what other annotations we should add.
Thoughts?
Adam
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email