Tom Eyckmans wrote:
Hi,
During aSkype session on sunday (Hans & me) we thought of introducing
a SourceDirectory concept to improve our compile/resource and test
handling.
I think this is a fantastic idea.
some of my first ideas:
# Defining source & resource dirs:
sourceDir('main') {
dir('src/main/java')
}
resourceDir('main') {
dir('src/main/resources')
replaceTokens ( prefix : '${', suffix : '}' ) ( [
tokenOne: 'valueOne',
tokenTwo: 'valueTwo'
])
}
testSourceDir('main') {
dir('src/test/java')
}
testResourceDir('main' {
dir('src/test/resources')
}
a more advanced example (with jdk version specific code):
sourceDir('main') { dir('src/main/java') }
sourceDir('jdk14') { dir('src/jdk14/java') }
sourceDir('jdk15') { dir('src/jdk15/java') }
sourceDirGroup('jdk14'){ sourceDirs('main','jdk14') }
sourceDirGroup('jdk15'){ sourceDirs('main','jdk15') }
testSourceDir('main') { dir('src/test/java') }
testSourceDir('jdk14') { dir('src/test-jdk14/java') }
testSourceDir('jdk15') { dir('src/test-jdk15/java') }
testSourceDirGroup('jdk14') { testSourceDirs('main','jdk14') }
testSourceDirGroup('jdk15') { testSourceDirs('main','jdk15') }
Some comments/questions:
How would we deal with resources and source living in the same
directory? production and test classes in the same directory? java 1.4
and java 1.5 classes in the same directory?
How would we deal with a multi-language project, which has both java and
groovy source, or java and c source, or whatever?
Why do we need source dir groups?
I'm not sure about how we should define and reference these domain
objects. This is another type of domain object with a name and type,
which you can add to the project, configure, and refer to, just like
tasks, projects, configurations, repositories, etc. We should make the
DSL for source directories consistent with the DSL for other domain
objects with a name and type.
Using http://docs.codehaus.org/display/GRADLE/Dependencies as a
reference for what we want the DSL to look like, we should either put
source directories in a context like repositories:
sourceDirectories {
SourceDirectory(name: 'api') {
dir('...')
}
SourceDirectory(name: 'main') {
dir('...')
}
TestSourceDirectory(name: 'test') {
dir('...')
}
}
or we should treat them the same way as tasks, something like:
main(SourceDirectory) {
dir('...')
}
or we should change the DSL shown on the wiki to match what you've got here.
Personally, I would really like a DSL where I can refer to the domain
objects using a groovy identifier, rather than a string (or even worse,
forcing me to sometimes use a string and sometimes an identifier, like
we currently do with tasks).
Regardless, it might be a good idea if you added some of the stuff
you've described here to the DSL wiki page, so we can see it in context
with the other DSL stuff, which might help us figure out something
consistent for all domain objects.
# Define how stuff should be compiled
// default by name and synhtetic
compile('main') {
// options
}
// or
compileMain {
// options
}
// custom compiles (naming optional)
compile ( sourceDir('build/generated-java-sources') ) {
// options
}
// or
compile ('antlr-source-compile',
sourceDir('build/generated-java-sources') ) {
// options
}
What are these defining? compile tasks? some kind of domain object?
# Define how stuff should be tested:
// default by name and synhtetic
test('main') {
// options
}
// or
testMain {
// options
}
// custom compiles (naming optional but required when you want to be
able to use it from the command line)
test (sourceDir('main'), testSourceDir('main') ) {
dependsOn(...) ?
// options
}
// with explicit name
test ('slow-test', sourceDir('main'), testSourceDir('main') ) {
// options
}
what are these defining?
# Define how stuff should be javadoc-ed
javadoc('main') {
// options
}
// or
javadocMain() {
// options
}
// custom javadoc
javadoc('custom', sourceDirs('jdk14','antlr-sources') ) {
// options
}
what are these defining?
# Define how stuff should be packaged
defaultJar(JarTask, name: project.name <http://project.name>) {
mainCompile { // include the result of main compile
// additional options includes/excludes ?
}
mainResources // include the result of main resources
}
// or
defaultJar(JarTask, name: project.name <http://project.name>) {
main // all of main compile + resources
}
defaultSourceJar(JarTask, name: project.name <http://project.name>,
classifier: 'sources') {
mainSources
}
defaultJavadocJar(JarTask, name: project.name <http://project.name>,
classifier: 'javadoc' ) {
javadocMain
}
defaultTestJar(JarTask, name: project.name <http://project.name>,
classifier: 'tests') {
mainTestCompile
mainTestResources
}
// or
defaultTestJar(JarTask, name:project.name <http://project.name>,
classifier: 'tests') {
mainTest // all of mainTest test compile + test resources
}
defaultTestSourceJar(JarTask, name: project.name
<http://project.name>, classifier: 'test-sources') {
mainTestSources
}
// this way it is very easy to define bundles:
gradleExternalJavadocBundle(JarTask, name: 'gradle-external-javadoc' ) {
main {
package('org.gradle.external.javadoc')
}
manifest {
// additional manifest instructions
}
}
We will need some way to include the these things with a prefix, as not
everything ends up in the root of an archive.
I think this is a very powerfull concept to use the task names to
include the result of a compile/resources task in an artifact and I
find it very natural but other views may differ.
I agree. In fact, we should generalise it: you should be able to add any
domain object which implements FileCollection (say) to an archive. Given
that Configuration, Dependency, SourceDirectory, Archive, and all file
producing tasks implement FileCollection, this makes it very easy to
assemble archives.
Adam