Using the groovy eclipse compiler with Gradle 1.1

Does anyone know why the following behaves differently between java and groovy files?

apply plugin: 'java'
apply plugin: 'groovy'
  repositories { mavenCentral() }
  configurations { jdt }
  dependencies {
   jdt "org.codehaus.groovy:groovy-eclipse-batch:2.0.0-01"
   groovy "org.codehaus.groovy:groovy-all:1.8.6"
}
  def newCompiler = { task ->
    task.doFirst {
     options.fork = true
    options.forkOptions.executable = 'java'
    options.forkOptions.jvmArgs = ['-cp', configurations.jdt.asPath, 'org.eclipse.jdt.internal.compiler.batch.Main' ]
  }
}
  tasks.withType(Compile).each newCompiler
tasks.withType(GroovyCompile).each newCompiler

Running this gives (output cleaned up):

:compileJava
Compiling with Java command line compiler 'java'.
Starting process 'command 'java''. Working directory /Users/shin/codebase/groovyJDT
 Command: java
 -cp groovy-eclipse-batch-2.0.0-01.jar
 org.eclipse.jdt.internal.compiler.batch.Main
 -d /Users/shin/bbc/codebase/groovyJDT/build/classes/main
 -g
 -classpath groovy-all-1.8.6.jar
 /Users/shin/bbc/codebase/groovyJDT/src/main/java/Atest.java
An attempt to initialize for well behaving parent process finished.
Successfully started process 'command 'java''
Process 'command 'java'' finished with exit value 0 (state: SUCCEEDED)
  :compileGroovy
Starting Gradle compiler daemon.
Starting process 'Gradle Worker 1'. Working directory /Users/shin/codebase/groovyJDT
 Command:
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java
 -cp groovy-eclipse-batch-2.0.0-01.jar
 org.eclipse.jdt.internal.compiler.batch.Main
 -Dfile.encoding=MacRoman
 -cp gradle-base-services-1.1.jar gradle-core-1.1.jar gradle-cli-1.1.jar gradle-native-1.1.jar gradle-messaging-1.1.jar slf4j-api-1.6.6.jar logback-classic-1.0.6.jar logback-core-1.0.6.jar jul-to-slf4j-1.6.6.jar
org.gradle.process.internal.launcher.GradleWorkerMain

Groovy gets compiled via the compiler daemon and has extra arguments appended but I was expecting it to work like the Java command line compiler. Consequently, no Groovy gets compiled because Main craps out because of the extra arguments. Source files aren’t passed to it either.

I’m looking at a couple of other options like upgrading the Groovy Eclipse plugin (https://github.com/adammurdoch/gradle-groovy-eclipse-compiler) but I’m not too savvy with the Gradle internals. I also tried getting the Java command line compiler to use the Eclipse compiler and recognise Groovy files but didn’t have much joy with the includes picking them up.

Thanks.

We don’t support the Groovy Eclipse compiler at this point, and I’m not sure if there is a way to make it work with the existing GroovyCompile task. ‘compileGroovy.options’ configures options for Java joint compilation of Groovy code. To configure options for Groovy compilation, you’ll have to use ‘compileGroovy.groovyOptions’.

groovyOptions doesn’t have the same kind of options like Java options does such as setting an executable. Seems they’re only options to pass to groovyc. Thanks anyway though.

I thought about getting the java plugin to recognise .groovy as source files and use another compiler but I don’t think that’s possible either.

What’s your motivation for using the Groovy Eclipse compiler?

I’m converting a project from Maven to Gradle that uses a mix of Java and Groovy. The current Maven configuration uses the Groovy Eclipse Compiler so I know everything should be compiling.

Moving to Gradle and groovyc threw up errors around Apache Wink picking incorrect implementation classes; we started to think it’s something to do with static initialisers and particular to groovyc.

At this time, you’d probably have to write your own task to integrate with the Groovy Eclipse compiler. Might be easier to try and solve the groovyc problems. Note that in general, groovyc joint compilation is much more stable in Gradle than it is in Maven.

I’ve ended up getting the Java plugin to use another compiler and recognise .groovy files by manipulating the compiler arguments.

FileTree groovySources = fileTree(dir: 'src/main')
groovySources.include '**/*.groovy'
  task compileGroovy(overwrite: true) {
  println "compileGroovy: I do NOTHING."
}
  tasks.withType(Compile).each { task ->
      task.doFirst {
     options.fork = true
    options.forkOptions.executable = 'java'
    options.forkOptions.jvmArgs = ['-cp', configurations.jdt.asPath, 'org.eclipse.jdt.internal.compiler.batch.Main' ]
    options.compilerArgs = ['-source', sourceCompatibility,
                            '-target', targetCompatibility,
                            '-nowarn' ] + groovySources.files.flatten() as String[]
      }
}

I still need the groovy plugin so that all the classpaths etc are setup automatically for me; hence why I need to overwrite the compileGroovy task so it does nothing. Same goes for test tasks and sources.

Feels very hacky and I have to test it more. But it might do for now.

I still need the groovy plugin so that all the classpaths etc are setup automatically for me

The Groovy plugin doesn’t do all that much. I think you could not apply it and just setup the configurations manually quite easily.

Yes you’re right. I’ve ended up just including groovy-all.jar as a compile dependency.

I was thinking I’d have to take the Groovy sources and add pass them to the compiler with -sourcepath but in my testing it didn’t seem to make a difference.

Thanks for the suggestion.

In case it helps anyone else, this is what we’ve ended up using for now. Lots of options hardcoded but we’re using it as a plugin running out of buildSrc so it’s satisfying our project’s needs for now.

package org.gradle
  import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.tasks.compile.Compile
import org.gradle.api.file.FileTree
  class GroovyEclipseCompilerPlugin implements Plugin<Project> {
      private static final String compilerVersion = 'org.codehaus.groovy:groovy-eclipse-batch:2.0.0-01'
    private static final String groovyVersion
= "org.codehaus.groovy:groovy-all:1.8.6"
      void apply(Project project) {
                def sourceCompatibility=1.6
        def targetCompatibility=1.6
                  project.configurations.add('groovyEclipseCompiler')
          project.dependencies.add('compile', groovyVersion)
            project.dependencies.add('groovyEclipseCompiler', compilerVersion)
          FileTree groovySources = project.fileTree(dir: 'src/main/groovy').include('**/*.groovy')
        FileTree groovyTestSources = project.fileTree(dir: 'src/test/groovy').include('**/*.groovy')
          def newCompiler = { Compile compile, ArrayList<FileTree> sources ->
            compile.options.fork = true
            compile.options.forkOptions.executable = 'java'
            compile.options.forkOptions.jvmArgs = ['-cp', project.configurations.groovyEclipseCompiler.asPath, 'org.eclipse.jdt.internal.compiler.batch.Main']
            compile.options.compilerArgs = ['-source', sourceCompatibility,
                    '-target', targetCompatibility,
                    '-nowarn'] + sources*.files.flatten() as String[]
        }
          // Set up the compileJava task
        project.tasks.compileJava.inputs.files groovySources.files
                          project.tasks.compileJava.ext.doFirst = newCompiler(project.tasks.compileJava, [groovySources])
                  // Set up the compileTestJava task
        project.tasks.compileTestJava.inputs.files groovyTestSources.files
                          project.tasks.compileTestJava.ext.doFirst = newCompiler(project.tasks.compileTestJava, [groovySources, groovyTestSources])
              }
}