Build multiple source & target compatibility


(Raleigh) #1

Hi All :gradlephant:,

I have a project (multi-project actually) that gets built for different JRE versions. Same code (mostly) needs to be built for 1.6, 1.7, and 1.8.

Right now this is accomplished by calling gradle multiple times, once for each target. The target is specified by a build property. The bootClasspath is set to use the correct jars based on the property, see below.

This works okay… but I am wondering if there is a better way. Not every invocation needs to build all variants, most of the time only 1 is needed. CI need to build all variants, so which targets get built needs to be configurable…
Is it possible to build for each desired target variant in a single Gradle invocation?
How would that be accomplished?

sourceCompatibility = project.targetJRE
targetCompatibility = project.targetJRE



// Set the classpath to use the correct JARs for building
tasks.withType(JavaCompile) {
    doFirst {
        options.encoding = 'UTF8'
        switch (targetCompatibility.toString()) {
            case '1.6':
                options.bootClasspath = rootProject.file("jre/bootstrap/1.6/rt.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/bootstrap/1.6/plugin.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/ext/1.6/jaccess.jar")
                break
            case '1.7':
                options.bootClasspath = rootProject.file("jre/bootstrap/1.7/rt.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/bootstrap/1.7/plugin.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/ext/1.7/jaccess.jar")
                break
            case '1.8':
            default:
                options.bootClasspath = rootProject.file("jre/bootstrap/1.8/rt.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/bootstrap/1.8/plugin.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/ext/1.8/jaccess.jar")
                options.bootClasspath += File.pathSeparator + rootProject.file("jre/bootstrap/1.8/jce.jar")
                break
        }
    }
}

thanks,
:confused:



(Stefan Oehme) #2

You can do that with the same approach I described here. You’d have one compile task and jar for each Java version.


(Raleigh) #3

Hi Stefan,

Thanks for the reply.
I’m not quite sure how to apply the variant suggestion you linked to in this situation.
How/when would options.bootClasspath get set correctly? Would the output dirs (for the .class files) need to be different for each variant, would Gradle handle that automagically or would my build scripts need to manage that?

I’ve looked through the documentation on variants and haven’t found much, is there some place I can look for more info and/or working samples?

Also for the plug-in suggestion, I am having some difficulties there, is there a good plugin sample that I could use as a template?


(Stefan Oehme) #4

Variants are not something built-in, but something you could build. You would have one sourceSet for each variant and thus one compile task and .class folder for each variant. You could then set the options for each variant.

The biggest challenge would be dependency resolution, as you would need to resolve the correct variant of upstream projects. Gradle currently doesn’t provide good out-of-the-box support, but that will change.

All that being said, there is currently no straightforward way to do this. Setting up a variant system requires advanced Gradle knowledge. The Android plugin does it for instance. You might want to stick with the command-line-argument solution until Gradle provides more variant support out of the box.


(Raleigh) #5

Thanks for the reply!

I’ll look over the src for the Android plugin and see if I can figure something out.

I hope support for tasks like this make it onto the Roadmap soon! :neutral_face:


(Stefan Oehme) #6

We are currently working on making project dependencies more flexible to support this variant use case. You’d still have to build the rest, i.e. creating the sourceSets, the jar tasks and the publications. But those things are relatively easy if you familiarize yourself with the API of the ‘java’ plugin.