-
Notifications
You must be signed in to change notification settings - Fork 271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gradle plugin does not respect all possible ways to configure java source target compatibility and produces variants with a wrong jvm version #1772
Comments
I did a couple of tests to see how different configurations behave. java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.JETBRAINS
}
}
//tasks.compileJava {
// options.release = 7
//}
//tasks {
// withType<JavaCompile> {
// sourceCompatibility = "1.7"
// targetCompatibility = "1.7"
// }
//}
//java {
// sourceCompatibility = JavaVersion.VERSION_1_7
// targetCompatibility = JavaVersion.VERSION_1_7
//}
println("java.sourceCompatibility = " + java.sourceCompatibility)
println("java.targetCompatibility = " + java.targetCompatibility)
tasks.withType<JavaCompile> {
println("withType<JavaCompile> sourceCompatibility = $sourceCompatibility")
println("withType<JavaCompile> targetCompatibility = $targetCompatibility")
}
tasks.compileJava {
println("tasks.compileJava options.release = " + options.release.get())
} Output:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.JETBRAINS
}
}
tasks.compileJava {
options.release = 7
}
//tasks {
// withType<JavaCompile> {
// sourceCompatibility = "1.7"
// targetCompatibility = "1.7"
// }
//}
//java {
// sourceCompatibility = JavaVersion.VERSION_1_7
// targetCompatibility = JavaVersion.VERSION_1_7
//}
println("java.sourceCompatibility = " + java.sourceCompatibility)
println("java.targetCompatibility = " + java.targetCompatibility)
tasks.withType<JavaCompile> {
println("withType<JavaCompile> sourceCompatibility = $sourceCompatibility")
println("withType<JavaCompile> targetCompatibility = $targetCompatibility")
}
tasks.compileJava {
println("tasks.compileJava options.release = " + options.release.get())
} Output:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.JETBRAINS
}
}
//tasks.compileJava {
// options.release = 7
//}
tasks {
withType<JavaCompile> {
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
}
}
//java {
// sourceCompatibility = JavaVersion.VERSION_1_7
// targetCompatibility = JavaVersion.VERSION_1_7
//}
println("java.sourceCompatibility = " + java.sourceCompatibility)
println("java.targetCompatibility = " + java.targetCompatibility)
tasks.withType<JavaCompile> {
println("withType<JavaCompile> sourceCompatibility = $sourceCompatibility")
println("withType<JavaCompile> targetCompatibility = $targetCompatibility")
}
tasks.compileJava {
println("tasks.compileJava options.release = " + options.release.get())
} Output:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.JETBRAINS
}
}
//tasks.compileJava {
// options.release = 7
//}
//tasks {
// withType<JavaCompile> {
// sourceCompatibility = "1.7"
// targetCompatibility = "1.7"
// }
//}
java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
println("java.sourceCompatibility = " + java.sourceCompatibility)
println("java.targetCompatibility = " + java.targetCompatibility)
tasks.withType<JavaCompile> {
println("withType<JavaCompile> sourceCompatibility = $sourceCompatibility")
println("withType<JavaCompile> targetCompatibility = $targetCompatibility")
}
tasks.compileJava {
println("tasks.compileJava options.release = " + options.release.get())
} Output:
|
According to the above
Changes probably all possible configurations except only this thing remains uninitialized:
But the problem with this way is that:
|
I see the next ways to fix this:
|
This issue is probably relevant only when compiling for ancient JDKs like for 1.7. It may be necessary if the plugin does some customizations to the JPS or running JUnit tests (in that case a class from the plugin may be run directly on JDK from user's project). Because in all other ways I we could simply use this approach to configure JDK & source level: java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.JETBRAINS
}
} But the above approach does not seem to be available for JDK less than 11 unless we also change the vendor from JvmVendorSpec.JETBRAINS to whatever else provides old JDKs. |
Yep, just tested java {
toolchain {
languageVersion = JavaLanguageVersion.of(7)
}
} creates a correct variant as well
But it works only by a coincidence because this way the source level matches the JDK and we also are not using JBR anymore (because there are not old JBRs), which is not critical but not ideal either. |
So the recommendation should be:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(7)
//vendor = JvmVendorSpec.JETBRAINS
}
}
// This one will configure source level in all possible places in Gradle (tested above)
// However, these options do not protect against the use of APIs introduced in later Java versions.
// Also this is required to fix https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1772 because Intellij Gradle plugin does not look at any other configuration
java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
// And another config to fix the lack of API control in the above config:
// The release flag provides guarantees similar to toolchains.
// It validates that the Java sources are not using language features introduced in later Java versions,
// and also that the code does not access APIs from more recent JDKs.
// The bytecode produced by the compiler also corresponds to the requested Java version,
// meaning that the compiled code cannot be executed on older JVMs.
tasks.compileJava {
options.release = 7
} |
What happened?
Currently no other ways of configuring source compatibility is supported except:
while Gradle recommends to use instead e.g.
or
or:
which is not good because the "java {" way does not do this:
Relevant documentation https://docs.gradle.org/current/userguide/building_java_projects.html#sec:java_cross_compilation
This may be useful: https://github.com/gradle/gradle/blob/master/platforms/jvm/plugins-java-base/src/main/java/org/gradle/api/plugins/jvm/internal/DefaultJvmLanguageUtilities.java#L82
This came out of #1713
See https://github.com/AlexanderBartash/intellij-platform-plugin-template/blob/issue-1713/common/build.gradle.kts#L50
Try running "./gradlew :common:outgoingVariants" with and without this "java {" block
The difference:
Relevant log output or stack trace
No response
Steps to reproduce
See https://github.com/AlexanderBartash/intellij-platform-plugin-template/blob/issue-1713/common/build.gradle.kts#L50
Gradle IntelliJ Plugin version
2.0.1
Gradle version
8.10.2
Operating System
Linux
Link to build, i.e. failing GitHub Action job
No response
The text was updated successfully, but these errors were encountered: