2009/3/18 Adam Murdoch <[email protected]>

>
>
> 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.
>
cool

>
>
>  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?
>
I think the solution to this would be to type the sourceDirs like we do with
artifact tasks, the type would define includes/excludes.

> production and test classes in the same directory?
> java 1.4 and java 1.5 classes in the same directory?

I think both are really nasty situations that should be avoided at all times
(compile/testCompile configuration concept is useless) but in the case that
it happens, I think we should just compile it twice and don't treat it in a
special way. Best possible scenario would be to define the
sourceDirs/testSourceDirs with includes/excludes (packaged based/ or
classname based (again abstract class issues probably when not following a
naming convention)) otherwise I think it is a lost cause and it really ought
to be separate dirs anyways :).

>
> How would we deal with a multi-language project, which has both java and
> groovy source, or java and c source, or whatever?
>
I think by typeing the sourceDirs we have a good handle on multi-language
projects, for groovy source the type would extend the java type and include
both java/groovy sources, I wouldn't go for multi-typed sourceDirs because
we would have to figure out a pretty difficult regexp expression merger (and
I'm not nearly smart enough for that :)).

>
>
> Why do we need source dir groups?
>

In case of the following sourceDirGroup:

sourceDirGroup('jdk14'){    sourceDirs('main','jdk14')      }

You include multiple sourceDirs
- main
- jdk14

By grouping these source dirs you don't need to mention both dirs when
referencing the group.

>
>
> 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.
>
I agree that naming domain objects should be consistent all the way.

>
>
> 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('...')
> }
>
I like both perhaps a combo/split is also an option (amount of strings like
with taks but still grouped):

sourceDirectories { // type of the items defined in this block:
    main {
        dir('...')
    }
}
testSourceDirectories {
     test {
         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).
>
I agree we should pick one and also agree and I think that the groovy
identifier is way more flexible.

>
>
> 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.
>

I'll update the wiki page this evening.

>
>
>  # 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?
>

both a domain object and a task (more info in reply to the more generalized
idea)

>
>
>
>  # 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?
>
both a domain object and a task (more info in reply to the more generalized
idea)

>
>
>  # 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?
>
both a domain object and a task (more info in reply to the more generalized
idea)

>
>
>  # Define how stuff should be packaged
>
>  defaultJar(JarTask, name: 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) {
>       main // all of main compile + resources
> }
>
>  defaultSourceJar(JarTask, name: project.name, classifier: 'sources') {
>     mainSources
> }
>
>  defaultJavadocJar(JarTask, name: project.name, classifier: 'javadoc' ) {
>     javadocMain
> }
>
>  defaultTestJar(JarTask, name: project.name, classifier: 'tests') {
>     mainTestCompile
>     mainTestResources
> }
> // or
> defaultTestJar(JarTask, name:project.name, classifier: 'tests') {
>     mainTest // all of mainTest test compile + test resources
> }
>
>  defaultTestSourceJar(JarTask, name: 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 agree, just a tought:

defaultJavadocJar(JarTask, name: project.name, classifier: 'javadoc' ) {
    docs { // if not defined in this context it is a directory
        'api-docs' {
            javadocMain
       }
    }
}


>
>
>  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.
>
I'm not sure if adding the FileCollection stuff on tasks is the best way to
go, I think tasks have a very clear responsibility that would get cluttered,
I would make the domain objects fronts for the task(s) (think of a resouces
domain object could be a front for a copy + tokenReplace tasks) behind them,
the domain objects would also be a perfect place for us to add logic to
detect if files have changed so we can skip compile/copy+tokenReplace... if
nothing has changed (in a doFirst call isCompileNeeded, skip when false), in
a doLast let the domain object know what the destination dir was of the
compile/...

>
>
>
> Adam
>
>

Reply via email to