diff --git a/jps/jps-builders/resources/messages/JpsBuildBundle.properties b/jps/jps-builders/resources/messages/JpsBuildBundle.properties index b32040097f6e..ec43a6a6b07a 100644 --- a/jps/jps-builders/resources/messages/JpsBuildBundle.properties +++ b/jps/jps-builders/resources/messages/JpsBuildBundle.properties @@ -61,10 +61,10 @@ build.messages.modules.were.fully.rebuilt={1, choice, 1#Module {0} was|2#Modules to project configuration{3, choice, 0#|1#/dependencies} changes build.message.errors.occurred.while.compiling.module.0=Errors occurred while compiling module ''{0}'' build.message.compilation.failed.internal.java.compiler.error=Compilation failed: internal java compiler error -build.message.cannot.start.javac.process.for.0.unknown.jdk.home=Cannot start javac process for {0}: unknown JDK home path.\nPlease check project configuration. -build.message.cannot.start.javac.process.for.0.unsupported.java.version=Cannot start javac process for {0}: it is configured to use JDK {1}, \ - but IDE supports compilation using JDK {2} and newer only.\nConsider upgrading the project to use a supported version of JDK. Note, that \ - it is possible to keep the current Java language level to make produced *.class files compatible with Java {1} even when they are compiled by a newer JDK. +build.message.cannot.start.javac.process.for.0.unknown.jdk.home=Cannot start javac process for {0}: unknown JDK home path or version.\nPlease check project configuration. +build.message.unsupported.javac.version=Cannot start javac process for {0}: it is configured to use JDK {1}, \ + but IDE supports compilation using JDK {2} and newer only.\nConsider associating the module with a supported JDK version. Note, that \ + it is possible to keep the current Java language level to make produced *.class files compatible with Java {3} even when they are compiled by a newer compiler version. #artifacts builder.name.artifacts.builder=Artifacts builder diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index af151d6199e7..571c55c682e6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -59,7 +59,9 @@ import org.jetbrains.jps.model.serialization.PathMacroUtil; import org.jetbrains.jps.service.JpsServiceManager; import org.jetbrains.jps.service.SharedThreadPool; -import javax.tools.*; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; import java.io.File; import java.io.FileFilter; import java.io.IOException; @@ -431,15 +433,8 @@ public final class JavaBuilder extends ModuleLevelBuilder { // when forking external javac, compilers from SDK 1.7 and higher are supported final Pair forkSdk; if (shouldForkCompilerProcess(context, chunk, targetLanguageLevel)) { - Pair, Integer> associatedSdk = getAssociatedSdk(chunk); - forkSdk = getForkedJavacSdk(associatedSdk, targetLanguageLevel); + forkSdk = getForkedJavacSdk(diagnosticSink, chunk, targetLanguageLevel); if (forkSdk == null) { - diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, JpsBuildBundle.message("build.message.cannot.start.javac.process.for.0.unknown.jdk.home", chunk.getName()))); - return false; - } - Integer associatedSdkVersion = associatedSdk != null ? associatedSdk.second : null; - if (!isTargetReleaseSupported(forkSdk.second, targetLanguageLevel) && associatedSdkVersion != null && associatedSdkVersion < ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION) { - diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, JpsBuildBundle.message("build.message.cannot.start.javac.process.for.0.unsupported.java.version", chunk.getName(), associatedSdkVersion, ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION))); return false; } } @@ -1172,32 +1167,70 @@ public final class JavaBuilder extends ModuleLevelBuilder { } @Nullable - private static Pair getForkedJavacSdk(@Nullable Pair, Integer> associatedSdk, int targetLanguageLevel) { + private static Pair getForkedJavacSdk(DiagnosticListener diagnostic, ModuleChunk chunk, int targetLanguageLevel) { + final Pair, Integer> associatedSdk = getAssociatedSdk(chunk); + boolean canRunAssociatedJavac = false; if (associatedSdk != null) { final int sdkVersion = associatedSdk.second; - if (sdkVersion >= ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION && isTargetReleaseSupported(sdkVersion, targetLanguageLevel)) { - // current javac compiler does support required language level - return Pair.create(associatedSdk.first.getHomePath(), sdkVersion); + canRunAssociatedJavac = sdkVersion >= ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION; + if (isTargetReleaseSupported(sdkVersion, targetLanguageLevel)) { + if (canRunAssociatedJavac) { + return Pair.create(associatedSdk.first.getHomePath(), sdkVersion); + } + } + else { + LOG.warn("Target bytecode version " + targetLanguageLevel + " is not supported by SDK " + sdkVersion + " associated with module " + chunk.getName()); } - LOG.warn("Target bytecode version " + targetLanguageLevel + " is not supported by SDK version " + sdkVersion); } + final String fallbackJdkHome = System.getProperty(GlobalOptions.FALLBACK_JDK_HOME, null); if (fallbackJdkHome == null) { LOG.info("Fallback JDK is not specified. (See " + GlobalOptions.FALLBACK_JDK_HOME + " option)"); - return null; } final String fallbackJdkVersion = System.getProperty(GlobalOptions.FALLBACK_JDK_VERSION, null); if (fallbackJdkVersion == null) { LOG.info("Fallback JDK version is not specified. (See " + GlobalOptions.FALLBACK_JDK_VERSION + " option)"); + } + + if (associatedSdk == null && (fallbackJdkHome == null || fallbackJdkVersion == null)) { + diagnostic.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, JpsBuildBundle.message("build.message.cannot.start.javac.process.for.0.unknown.jdk.home", chunk.getName()))); return null; } - final int fallbackVersion = JpsJavaSdkType.parseVersion(fallbackJdkVersion); - if (fallbackVersion < ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION) { - LOG.info("Version string for fallback JDK is '" + fallbackJdkVersion + "' (recognized as version '" + fallbackVersion + "')." + - " At least version " + ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION + " is required."); - return null; + + // either associatedSdk or fallbackJdk is configured, but associatedSdk cannot be used + if (fallbackJdkHome != null) { + final int fallbackVersion = JpsJavaSdkType.parseVersion(fallbackJdkVersion); + if (isTargetReleaseSupported(fallbackVersion, targetLanguageLevel)) { + if (fallbackVersion >= ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION) { + return Pair.create(fallbackJdkHome, fallbackVersion); + } + else { + LOG.info("Version string for fallback JDK is '" + fallbackJdkVersion + "' (recognized as version '" + fallbackVersion + "')." + + " At least version " + ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION + " is required to launch javac process."); + } + } } - return Pair.create(fallbackJdkHome, fallbackVersion); + + // at this point, fallbackJdk is not suitable too + if (associatedSdk != null) { + if (canRunAssociatedJavac) { + // although target release is not supported, attempt to start javac, so that javac properly reports this error + return Pair.create(associatedSdk.first.getHomePath(), associatedSdk.second); + } + else { + diagnostic.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, + JpsBuildBundle.message( + "build.message.unsupported.javac.version", + chunk.getName(), + associatedSdk.second, + ExternalJavacProcess.MINIMUM_REQUIRED_JAVA_VERSION, + targetLanguageLevel + ) + )); + } + } + + return null; } private static @Nullable Pair<@NotNull JpsSdk, @NotNull Integer> getAssociatedSdk(ModuleChunk chunk) {