diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildUtils.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildUtils.groovy index 701f27f04fa3..e67059a857ce 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildUtils.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildUtils.groovy @@ -38,6 +38,16 @@ class BuildUtils { addToClassLoaderClassPath(path, ant, BuildUtils.class.classLoader) } + @CompileDynamic + static void addToSystemClasspath(File file) { + def classLoader = ClassLoader.getSystemClassLoader() + if (!(classLoader instanceof URLClassLoader)) { + throw new BuildException("Cannot add to system classpath: unsupported class loader $classLoader (${classLoader.getClass()})") + } + + classLoader.addURL(file.toURI().toURL()) + } + static void addToJpsClassPath(String path, AntBuilder ant) { //we need to add path to classloader of BuilderService to ensure that classes from that path will be returned by JpsServiceManager.getExtensions addToClassLoaderClassPath(path, ant, Class.forName("org.jetbrains.jps.incremental.BuilderService").classLoader) diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JpsCompilationRunner.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JpsCompilationRunner.groovy index c3d5ae97a44f..e399747df077 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JpsCompilationRunner.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JpsCompilationRunner.groovy @@ -42,6 +42,7 @@ import org.apache.tools.ant.BuildException import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable +import org.jetbrains.intellij.build.BuildMessages import org.jetbrains.intellij.build.CompilationContext import org.jetbrains.jps.api.CmdlineRemoteProto import org.jetbrains.jps.api.GlobalOptions @@ -67,6 +68,7 @@ import org.jetbrains.jps.model.module.JpsModule */ @CompileStatic class JpsCompilationRunner { + private static boolean ourToolsJarAdded private final CompilationContext context private final JpsCompilationData compilationData @@ -150,6 +152,9 @@ class JpsCompilationRunner { private void runBuild(final Set modulesSet, final boolean allModules, Collection artifactNames, boolean includeTests, boolean resolveProjectDependencies) { + if (!modulesSet.isEmpty() || allModules) { + addToolsJarToSystemClasspath(context.paths.jdkHome, context.messages) + } System.setProperty(GlobalOptions.USE_DEFAULT_FILE_LOGGING_OPTION, "false") final AntMessageHandler messageHandler = new AntMessageHandler() AntLoggerFactory.ourMessageHandler = messageHandler @@ -217,6 +222,23 @@ class JpsCompilationRunner { } } + /** + * Add tools.jar to the system classloader's classpath. {@link javax.tools.ToolProvider} will load javac implementation classes by its own URLClassLoader, + * which uses the system classloader as its parent, so we need to ensure that tools.jar will be accessible from the system classloader, + * otherwise the loaded classes will be incompatible with the classes loaded by {@link org.jetbrains.jps.javac.ast.JavacReferenceCollectorListener}. + */ + private static void addToolsJarToSystemClasspath(String jdkHome, BuildMessages messages) { + if (ourToolsJarAdded) { + return + } + File toolsJar = new File(jdkHome, "lib/tools.jar") + if (!toolsJar.exists()) { + messages.error("Failed to add tools.jar to classpath: $toolsJar doesn't exist") + } + BuildUtils.addToSystemClasspath(toolsJar) + ourToolsJarAdded = true + } + private class AntMessageHandler implements MessageHandler { private MultiMap errorMessagesByCompiler = MultiMap.createLinked() private float progress = -1.0