What you're trying to achieve is perfectly possible. Let's check step by step how this can be done. First of all, we instruct Gradle to compile all Java sources with Java 8 source and target compatibility and execute compilation with a Java 8 executable taken from environment variable JAVA8_HOME:
plugins {
id 'java'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType(JavaCompile) {
options.with {
fork = true
forkOptions.javaHome = System.env.'JAVA8_HOME' as File
}
}
Running the build with the --info switch shows that the Java 8 executable is indeed taken from the environment variable JAVA8_HOME and applies to all Java compilation tasks.
> Task :compileJava
Compiling with Java command line compiler 'C:\dev\java\jdk-8\bin\javac.exe'.
> Task :compileTestJava
Compiling with Java command line compiler 'C:\dev\java\jdk-8\bin\javac.exe'.
Executing tests with Java 11 taken from environment variable JAVA11_HOME works in a similar manner.
test {
executable = "${System.env.'JAVA11_HOME'}/bin/java"
}
This produces again the following output:
> Task :test
Command: C:\dev\java\jdk-11/bin/java -Dorg.gradle.native=false ...
Subprojects
Applying this configuration to all subprojects in a multi-module project is straight forward. The following shows a root project's build.gradle that applies all rules only to those sub-projects having the Java plugin applied.
plugins {
id 'base'
}
allprojects {
plugins.withId('java') {
repositories {
mavenCentral()
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType(JavaCompile) {
options.with {
fork = true
forkOptions.javaHome = System.env.'JAVA8_HOME' as File
}
}
test {
useJUnitPlatform()
executable = "${System.env.'JAVA11_HOME'}/bin/java"
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
}
}
}
Since you now depend on having environment variables set up, it makes sense to check them before actually starting the build. This can be done by checking the task graph once ready:
gradle.taskGraph.whenReady { taskGraph ->
if (taskGraph.getAllTasks().find { it instanceof JavaCompile } != null
&& (System.env.'JAVA8_HOME' == null || System.env.'JAVA11_HOME' == null)) {
throw new GradleException("Please export 'JAVA8_HOME' and 'JAVA11_HOME'")
}
}
Jenkins
In Jenkins, all you need to do is to make sure to install the required JDKs and export the environment variables properly. A Jenkinsfile may look like this (take it with a grain of salt, I didn't test it yet):
pipeline {
tools {
jdk 'jdk-8'
jdk 'jdk-11'
}
environment {
JAVA8_HOME = "${tool 'jdk-8'}"
JAVA11_HOME = "${tool 'jdk-11'}"
}
stages {
stage('Build') {
steps {
checkout scm
sh "./gradlew --no-daemon --info --stacktrace clean build"
}
}
}
}