22

Because my Java sources and targets must be JRE 1.6 compatible, I need to set options.bootClasspath to a path that contains the 1.6 versions of rt.jar and jce.jar. It must build on both Windows and Unix (Linux/Solaris). What is the proper way to do this? I now use the following approach in my top-level build.gradle, it works, but it seems far from elegant, especially the os-dependent separator : or ;:

import org.apache.tools.ant.taskdefs.condition.Os

subprojects {
  apply plugin: 'java'

  compileJava {
    sourceCompatibility = 1.6
    targetCompatibility = 1.6
    def java6_home = System.getenv("JAVA_HOME_6")
    def java6_lib = "C:/localdata/Program Files (x86)/Java/jdk1.6.0_45/jre/lib/"

    if (java6_home != null) {
      java6_lib = java6_home + "/jre/lib/"
    }

    def sep = ':'
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
      sep = ';'
    }
    options.bootClasspath = java6_lib + "rt.jar" + sep + java6_lib + "jce.jar"
  }
}
Gerrit Brouwer
  • 732
  • 1
  • 6
  • 14
  • There is `separator` and `pathSeparator` in `File` as referenced in [this question](http://stackoverflow.com/questions/3548775/platform-independent-paths-in-java). That should ease some of your elegance concerns. – Patru Mar 27 '14 at 08:15
  • Thanx, using `File.pathSeparator` saves 5 lines of code :-) – Gerrit Brouwer Mar 27 '14 at 09:11

5 Answers5

29

I am using the following code (assuming the JDK6_HOME points to the root of the JDK 1.6 installation):

tasks.withType(JavaCompile) {
    doFirst {
        if (sourceCompatibility == '1.6' && System.env.JDK6_HOME != null) {
            options.fork = true
            options.bootClasspath = "$System.env.JDK6_HOME/jre/lib/rt.jar"
            options.bootClasspath += "$File.pathSeparator$System.env.JDK6_HOME/jre/lib/jsse.jar"
            // use the line above as an example to add jce.jar 
            // and other specific JDK jars
        }
    }
}

This approach automatically detects the presence of the environment variable and automatically sets the bootClasspath for all modules that declare sourceCompatibility as 1.6.

The options.fork = true is required when you use bootClasspath.

Oleg Estekhin
  • 8,063
  • 5
  • 49
  • 52
  • 2
    Thanx! Using File.pathSeparator saves 5 lines of code. However, I doubt if the `options.fork = true` is needed. The user guide says: "By default, the Java compiler runs in the Gradle process. Setting options.fork to true causes compilation to occur in a separate process. In the case of the Ant javac task, this means that a new process will be forked for each compile task, which can slow down compilation." – Gerrit Brouwer Mar 27 '14 at 09:01
  • 2
    http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html#org.gradle.api.tasks.compile.CompileOptions:bootClasspath : Only takes effect if fork is true. – Oleg Estekhin Mar 27 '14 at 09:07
  • Thanx for giving the proper ref. So I guess there is no way to work around the resulting compilation slowdown :-( – Gerrit Brouwer Mar 27 '14 at 09:15
  • 2
    The documentation has changed since 2.6 because it does not mention to take effect only with `fork = true` anymore. See [Gradle 2.5 Documentation](https://docs.gradle.org/2.5/dsl/org.gradle.api.tasks.compile.CompileOptions.html#org.gradle.api.tasks.compile.CompileOptions:bootClasspath) vs [Gradle 2.6 Documentation](https://docs.gradle.org/2.6/dsl/org.gradle.api.tasks.compile.CompileOptions.html#org.gradle.api.tasks.compile.CompileOptions:bootClasspath). Did not try it yet but will do and will report findings. – Matt Aug 24 '15 at 17:53
  • 1
    I can confirm that `fork=true` is not needed on Gradle 2.10. I'm using JDK8 and setting JDK7's `rt.jar` to prevent "bootstrap class path not set in conjunction with -source 1.7" and the warning disappeared even without `fork`. – TWiStErRob Mar 07 '16 at 14:11
  • I newer versions of gradle the way the bootstrap classpath is set changed: options.bootstrapClasspath = files("$System.env.JDK7_HOME/jre/lib/rt.jar", "..") – Stefan Feuerhahn Mar 19 '19 at 10:21
4

The accepted answer can work, but if you're using some classes outside java.lang (e.g. javax.crypto.*) you may find you'll get various ClassNotFoundExceptionException's being raised as more JAR files need to be added to the bootClasspath.

To avoid this, I use the following which has the following advantages;

.

tasks.withType(JavaCompile) {
    doFirst {
        if (JavaVersion.toVersion(sourceCompatibility) == JavaVersion.VERSION_1_6
            && JavaVersion.current() != JavaVersion.VERSION_1_6
            && System.env.JDK6_HOME != null) {
            options.fork = true
            options.bootClasspath = fileTree(include: ['*.jar'], dir: "$System.env.JDK6_HOME/jre/lib/").join(File.pathSeparator)
            options.extensionDirs = "$System.env.JDK6_HOME/jre/lib/ext/"
        }
    }
}
gdt
  • 1,822
  • 17
  • 19
1

Since Gradle 4.3 you can use CompileOptions.bootstrapClasspath instead to remove the need for an OS-dependent separator.

Lóránt Pintér
  • 10,152
  • 14
  • 47
  • 53
0

A slight modification of the cool solution by Oleg Estekhin above, but doesn't require JDKX_HOME to be set (calculates it on the fly.) Also, modified for doing Java 1.7 builds:

tasks.withType(JavaCompile) {
    doFirst {
        if (sourceCompatibility == '1.7') {
            def JDK7_HOME = "/usr/libexec/java_home -v 1.7".execute().text.trim()
            options.bootClasspath = "$JDK7_HOME/jre/lib/rt.jar"
            options.bootClasspath += "$File.pathSeparator$JDK7_HOME/jre/lib/jsse.jar"
            // use the line above as an example to add jce.jar 
            // and other specific JDK jars
        }
    }
}
Joshua Richardson
  • 1,827
  • 22
  • 22
  • 2
    The platform independence of `$File.pathSeparator` is lost when you use `/usr/libexec/java_home` to detect the java home. – willkil Oct 31 '16 at 22:36
0

I tried to add many jars to my bootClassPath using the instructions above, but never resolved my build issue. I finally resolved the build by setting my JAVA_HOME to point to the IBM JDK 1.7 required by the WebSphere server and adding it to my path. My other projects require Oracle JDK 1.8 so I did not want to make this change permanent.

set JAVA_HOME="C:\Program Files (x86)\IBM\WebSphere\AppServer\java_1.7.1_64\"
set PATH=%JAVA_HOME%\bin;%PATH%
gradle clean war
gradle clean ear deployLocal
Larry Ricker
  • 199
  • 1
  • 7