How to make javac2 work in Gradle - SOLVED!

I've seen quite a few threads here and on the Gradle forums about how to get the JetBrains forms compiler (javac2) to work in Gradle.

This used to work via several methods, but broke during Gradle's evolution prior to it's release.

Here's how you do it - (you can download a complete copy of this script at http://ant-master-build-scripts.googlecode.com/svn/trunk/master-gradle/master-build.gradle)

First, you need to tell Gradle you need to use some libraries in the task. Create a configuration so this classpath doesn't pollute your source code (more than necessary at runtime, anyway):

configurations {
  javac2
}


I like to declare the versions separate from the libraries, so if I change a bunch of stuff the version number is in one place:

dependencies {
  ext.libraryVersions += [

    forms_rt:       '11.0.3',
    intellij:       '11.0.3',

    javac2asm:      '3.3.1',
    jdom:           '1.0'
  ]



  javac2 'com.intellij:javac2:'+                   libraryVersions.intellij,
         'com.intellij:annotations:'+              libraryVersions.intellij,
         'asm:asm-commons:'+                       libraryVersions.javac2asm,
         'asm:asm-parent:'+                        libraryVersions.javac2asm,
         'org.jdom:jdom:'+                         libraryVersions.jdom



    runtime 'com.intellij:forms_rt:'+              libraryVersions.forms_rt
}

Now we've got the libraries available to the build script, we create the task (by overriding compileJava):

task compileJava (overwrite: true) << {

  theDir = file("${project.buildDir.path}/classes/main")
  //make any source dirs needed for the output
  theDir.mkdirs()


  mainSrcDir = "${projectDir}/src/main/java"
  destDir = "${projectDir}/build/classes/main"
  javaSoureCompatibility = sourceCompatibility
  javaTargetCompatibility = targetCompatibility
  optimize = "off"
  deprecation = "off"
  includeAntRuntime = false
  javaDeprecation = deprecation
  debugLevel = "lines,vars,source"
  debug = "on"
  classpath = configurations.compile.asPath


  compileJavac2(mainSrcDir, classpath, destDir, debug, debugLevel, javaDeprecation, includeAntRuntime, optimize, javaSoureCompatibility, javaTargetCompatibility)
}


private void compileJavac2(mainSrcDir, classpath, destDir, debug, debugLevel, deprecation, includeAntRuntime, optimize, sourceCompatibility, targetCompatibility)
{
  ant {
    taskdef(name: 'javac2',
            classname: 'com.intellij.ant.Javac2',
            classpath: configurations.javac2.asPath)


    javac2(srcdir: mainSrcDir,
           classpath: classpath,
           destdir: destDir,
           debug: debug,
           debugLevel: debugLevel,
           deprecation: deprecation,
           includeAntRuntime: includeAntRuntime,
           optimize: optimize,
           source: sourceCompatibility,
           target: targetCompatibility
    )
  }
}


The nice thing about this is that by overriding the compileJava task, all of the task dependencies seem to be honored - in other words, it knows when to comile which files, or leave them alone.  I'll get a little fancier with this and declare them explicitly, as this might break with a future version of Gradle.  Worst case, it recompiles everything all the time.

The other nice thing about this is that only the main java classes are compiled with this - test and Groovy classes are left untouched.

The build script referenced in  http://ant-master-build-scripts.googlecode.com/svn/trunk/master-gradle/master-build.gradle is actually my "base" build script, which I import into all others.

I do a lot of Swing work, and this has been working well for me.  I hope others find this useful as well.

Douglas Bullard

Please sign in to leave a comment.