Skip to content

Commit 2eda3ed

Browse files
authored
Provide better support for toolchains for JVM projects (#208)
* test: reproduce the problem by a test-project > * What went wrong: > Execution failed for task :greeter.toolchain:compileJava. > > Cannot specify --release via `CompileOptions.compilerArgs` when using `JavaCompile.release`. * fix: use Gradle native implementation to set the `--release` option to compiler * fix: refer to toolchain config to grab the version of java compiler * build: build the greeter.toolchain proj with Gradle 6.6 Gradle 6.6 has no toolchain support, but has javaCompile.options.release property. * chore: remove needless imports * build: use Java 11 for new test project using Java 17 breaks the build in GitHub Actions workflow, because Java 17 has more strict control on the Java module.
1 parent 87aeda5 commit 2eda3ed

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

src/main/java/org/javamodularity/moduleplugin/extensions/DefaultModularityExtension.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
import org.gradle.api.Project;
66
import org.gradle.api.Task;
77
import org.gradle.api.plugins.JavaPlugin;
8+
import org.gradle.api.plugins.JavaPluginExtension;
89
import org.gradle.api.tasks.compile.JavaCompile;
10+
import org.gradle.jvm.toolchain.JavaToolchainSpec;
11+
import org.gradle.util.GradleVersion;
912
import org.javamodularity.moduleplugin.JavaProjectHelper;
1013
import org.javamodularity.moduleplugin.tasks.ClasspathFile;
1114

@@ -74,6 +77,17 @@ private void configureMixedJavaRelease(int mainJavaRelease, int moduleInfoJavaRe
7477
// TODO: Remove this method when Gradle supports it natively: https://github.com/gradle/gradle/issues/2510
7578
private void setJavaRelease(JavaCompile javaCompile, int javaRelease) {
7679
String currentJavaVersion = JavaVersion.current().toString();
80+
if (toolchainIsSupported()) {
81+
JavaToolchainSpec toolchain = project.getExtensions().getByType(JavaPluginExtension.class).getToolchain();
82+
if (toolchain != null) {
83+
// If toolchain is enabled, the version of java compiler is NOT same to the version of JVM running Gradle
84+
// so we need to get the version of toolchain explicitly as follows
85+
String toolchainVersion = toolchain.getLanguageVersion().map(Object::toString).getOrNull();
86+
if (toolchainVersion != null) {
87+
currentJavaVersion = toolchainVersion;
88+
}
89+
}
90+
}
7791
if (!javaCompile.getSourceCompatibility().equals(currentJavaVersion)) {
7892
throw new IllegalStateException("sourceCompatibility should not be set together with --release option");
7993
}
@@ -86,8 +100,29 @@ private void setJavaRelease(JavaCompile javaCompile, int javaRelease) {
86100
throw new IllegalStateException("--release option is already set in compiler args");
87101
}
88102

89-
compilerArgs.add("--release");
90-
compilerArgs.add(String.valueOf(javaRelease));
103+
if (releaseOptionIsSupported()) {
104+
// using the `convention(Integer)` method instead of the `set(Integer)` method, to let users set overwrite explicitly
105+
javaCompile.getOptions().getRelease().convention(javaRelease);
106+
} else {
107+
compilerArgs.add("--release");
108+
compilerArgs.add(String.valueOf(javaRelease));
109+
}
110+
}
111+
112+
/**
113+
* @see <a href="https://github.com/gradle/gradle/issues/2510#issuecomment-657436188">The comment on GitHub issue that says {@code --release} option is added in Gradle 6.6</a>
114+
* @return true if the version of Gradle is 6.6 or later
115+
*/
116+
private boolean releaseOptionIsSupported() {
117+
return GradleVersion.current().compareTo(GradleVersion.version("6.6")) >= 0;
118+
}
119+
120+
/**
121+
* @see <a href="https://docs.gradle.org/6.7/javadoc/org/gradle/api/plugins/JavaPluginExtension.html#getToolchain--">The Javadoc that says {@code JavaPluginExtension.getToolchain()} is added in Gradle 6.7</a>
122+
* @return true if the version of Gradle is 6.7 or later
123+
*/
124+
private boolean toolchainIsSupported() {
125+
return GradleVersion.current().compareTo(GradleVersion.version("6.7")) >= 0;
91126
}
92127

93128
private JavaProjectHelper helper() {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//region NO-OP (DSL testing)
2+
3+
// one of the supported Java version (prefer LTS version)
4+
def toolchainVer = 11
5+
6+
java {
7+
toolchain {
8+
languageVersion.set(JavaLanguageVersion.of(toolchainVer))
9+
}
10+
}
11+
12+
modularity {
13+
// This version should be less than `toolchainVer` because:
14+
// * if the version is same to `toolchainVer` we cannot reproduce the existing problem
15+
// * if the version is greather than `toolchainVer` javac cannot create class files
16+
standardJavaRelease(9)
17+
}
18+
//endregion
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package examples.greeter.api;
2+
3+
public interface Greeter {
4+
String hello();
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module greeter.api {
2+
exports examples.greeter.api;
3+
}

test-project/settings.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ include 'greeter.runner'
1515

1616
include 'greeter.javaexec'
1717
include 'greeter.startscripts'
18+
19+
if(GradleVersion.current().compareTo(GradleVersion.version("6.6")) >= 0) {
20+
include 'greeter.toolchain'
21+
}

0 commit comments

Comments
 (0)