diff --git a/platform/jps-bootstrap/.gitignore b/platform/jps-bootstrap/.gitignore
new file mode 100644
index 000000000000..7f8de99b273c
--- /dev/null
+++ b/platform/jps-bootstrap/.gitignore
@@ -0,0 +1,3 @@
+/target
+/classpath.pathlist
+/out
diff --git a/platform/jps-bootstrap/.idea/.gitignore b/platform/jps-bootstrap/.idea/.gitignore
new file mode 100644
index 000000000000..13566b81b018
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/platform/jps-bootstrap/.idea/ant.xml b/platform/jps-bootstrap/.idea/ant.xml
new file mode 100644
index 000000000000..50049ea2d346
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/ant.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/.idea/compiler.xml b/platform/jps-bootstrap/.idea/compiler.xml
new file mode 100644
index 000000000000..42ae2bbbc47d
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/.idea/encodings.xml b/platform/jps-bootstrap/.idea/encodings.xml
new file mode 100644
index 000000000000..3daf701f72b0
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/encodings.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/.idea/jarRepositories.xml b/platform/jps-bootstrap/.idea/jarRepositories.xml
new file mode 100644
index 000000000000..ccb6e98034ec
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/jarRepositories.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/.idea/misc.xml b/platform/jps-bootstrap/.idea/misc.xml
new file mode 100644
index 000000000000..5f3e0f8d5e19
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/.idea/vcs.xml b/platform/jps-bootstrap/.idea/vcs.xml
new file mode 100644
index 000000000000..c2365ab11f9b
--- /dev/null
+++ b/platform/jps-bootstrap/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/jps-bootstrap-classpath.xml b/platform/jps-bootstrap/jps-bootstrap-classpath.xml
new file mode 100644
index 000000000000..a3743ba702f3
--- /dev/null
+++ b/platform/jps-bootstrap/jps-bootstrap-classpath.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/jps-bootstrap.sh b/platform/jps-bootstrap/jps-bootstrap.sh
new file mode 100644
index 000000000000..40603b1f530e
--- /dev/null
+++ b/platform/jps-bootstrap/jps-bootstrap.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+# Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+
+set -eu
+
+JPS_BOOTSTRAP_DIR="$(cd "$(dirname "$0")"; pwd)"
+COMMUNITY_HOME="$(cd "$JPS_BOOTSTRAP_DIR/../.."; pwd)"
+JPS_BOOTSTRAP_WORK_DIR=${JPS_BOOTSTRAP_WORK_DIR:-$COMMUNITY_HOME/out/jps-bootstrap}
+
+SCRIPT_VERSION=jps-bootstrap-cmd-v1
+
+warn () {
+ echo "$@"
+}
+
+die () {
+ echo 2>&1
+ echo "$@" 2>&1
+ echo 2>&1
+ exit 1
+}
+
+darwin=false
+case "$(uname)" in
+ Darwin* )
+ darwin=true
+ ;;
+esac
+
+if [ "$darwin" = "true" ]; then
+ case $(uname -m) in
+ x86_64)
+ JVM_URL=https://corretto.aws/downloads/resources/11.0.9.12.1/amazon-corretto-11.0.9.12.1-macosx-x64.tar.gz
+ JVM_TARGET_DIR="$JPS_BOOTSTRAP_WORK_DIR/jvm/amazon-corretto-11.0.9.12.1-macosx-x64-$SCRIPT_VERSION"
+ ;;
+ arm64)
+ JVM_URL=https://cdn.azul.com/zulu/bin/zulu11.45.27-ca-jdk11.0.10-macosx_aarch64.tar.gz
+ JVM_TARGET_DIR="$JPS_BOOTSTRAP_WORK_DIR/jvm/zulu-11.0.10-macosx-arm64-$SCRIPT_VERSION"
+ ;;
+ *)
+ die "Unknown architecture $(uname -m)"
+ ;;
+ esac
+else
+ case $(uname -m) in
+ x86_64)
+ JVM_URL=https://corretto.aws/downloads/resources/11.0.9.12.1/amazon-corretto-11.0.9.12.1-linux-x64.tar.gz
+ JVM_TARGET_DIR="$JPS_BOOTSTRAP_WORK_DIR/jvm/amazon-corretto-11.0.9.12.1-linux-x64-$SCRIPT_VERSION"
+ ;;
+ aarch64)
+ JVM_URL=https://corretto.aws/downloads/resources/11.0.9.12.1/amazon-corretto-11.0.9.12.1-linux-aarch64.tar.gz
+ JVM_TARGET_DIR="$JPS_BOOTSTRAP_WORK_DIR/jvm/amazon-corretto-11.0.9.12.1-linux-aarch64-$SCRIPT_VERSION"
+ ;;
+ *)
+ die "Unknown architecture $(uname -m)"
+ ;;
+ esac
+fi
+
+mkdir -p "$JPS_BOOTSTRAP_WORK_DIR/jvm"
+
+if [ -e "$JVM_TARGET_DIR/.flag" ] && [ -n "$(ls "$JVM_TARGET_DIR")" ] && [ "x$(cat "$JVM_TARGET_DIR/.flag")" = "x${JVM_URL}" ]; then
+ # Everything is up-to-date in $JVM_TARGET_DIR, do nothing
+ true
+else
+ warn "Downloading $JVM_URL to $JVM_TEMP_FILE"
+
+ JVM_TEMP_FILE=$(mktemp "$JPS_BOOTSTRAP_WORK_DIR/jvm.tar.gz.XXXXXXXXX")
+ trap 'echo "Removing $JVM_TEMP_FILE"; rm -f "$JVM_TEMP_FILE"; trap - EXIT' EXIT INT HUP
+
+ if command -v curl >/dev/null 2>&1; then
+ if [ -t 1 ]; then CURL_PROGRESS="--progress-bar"; else CURL_PROGRESS="--silent --show-error"; fi
+ curl $CURL_PROGRESS --output "${JVM_TEMP_FILE}" "$JVM_URL"
+ elif command -v wget >/dev/null 2>&1; then
+ if [ -t 1 ]; then WGET_PROGRESS=""; else WGET_PROGRESS="-nv"; fi
+ wget $WGET_PROGRESS -O "${JVM_TEMP_FILE}" "$JVM_URL"
+ else
+ die "ERROR: Please install wget or curl"
+ fi
+
+ warn "Extracting $JVM_TEMP_FILE to $JVM_TARGET_DIR"
+ rm -rf "$JVM_TARGET_DIR"
+ mkdir -p "$JVM_TARGET_DIR"
+
+ tar -x -f "$JVM_TEMP_FILE" -C "$JVM_TARGET_DIR"
+ rm -f "$JVM_TEMP_FILE"
+
+ echo "$JVM_URL" >"$JVM_TARGET_DIR/.flag"
+fi
+
+JAVA_HOME=
+for d in "$JVM_TARGET_DIR" "$JVM_TARGET_DIR"/* "$JVM_TARGET_DIR/Contents/Home" "$JVM_TARGET_DIR/"*/Contents/Home; do
+ if [ -e "$d/bin/java" ]; then
+ JAVA_HOME="$d"
+ fi
+done
+
+if [ ! -e "$JAVA_HOME/bin/java" ]; then
+ die "Unable to find bin/java under $JVM_TARGET_DIR"
+fi
+
+set -x
+
+"$JAVA_HOME/bin/java" -jar "$COMMUNITY_HOME/lib/ant/lib/ant-launcher.jar" -f "$JPS_BOOTSTRAP_DIR/jps-bootstrap-classpath.xml"
+
+exec "$JAVA_HOME/bin/java" -classpath "@$JPS_BOOTSTRAP_WORK_DIR/classpath.pathlist" JpsBootstrapMain "$@"
diff --git a/platform/jps-bootstrap/pom.xml b/platform/jps-bootstrap/pom.xml
new file mode 100644
index 000000000000..7f5eb7744dca
--- /dev/null
+++ b/platform/jps-bootstrap/pom.xml
@@ -0,0 +1,71 @@
+
+
+
+ 4.0.0
+
+ org.jetbrains.jps-bootstrap
+ jps-bootstrap
+ 1.0.0
+
+
+ 11
+ 213.2547
+ UTF-8
+
+
+
+
+ com.jetbrains.intellij.platform
+ jps-model
+ ${bootstrap.intellij.version}
+
+
+ com.jetbrains.intellij.platform
+ jps-model-impl
+ ${bootstrap.intellij.version}
+
+
+ com.jetbrains.intellij.platform
+ jps-model-serialization
+ ${bootstrap.intellij.version}
+
+
+ com.jetbrains.intellij.tools
+ jps-build-standalone
+ ${bootstrap.intellij.version}
+
+
+ com.jetbrains.intellij.groovy
+ groovy-jps
+ ${bootstrap.intellij.version}
+
+
+ com.jetbrains.intellij.groovy
+ groovy-rt
+ ${bootstrap.intellij.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+
+
+
+
+
+ intellij-dependencies
+ https://cache-redirector.jetbrains.com/intellij-dependencies
+
+
+ kotlin-ide-plugin-dependencies
+ https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies
+
+
+
+
\ No newline at end of file
diff --git a/platform/jps-bootstrap/src/main/java/JpsBootstrapMain.java b/platform/jps-bootstrap/src/main/java/JpsBootstrapMain.java
new file mode 100644
index 000000000000..00e51345f843
--- /dev/null
+++ b/platform/jps-bootstrap/src/main/java/JpsBootstrapMain.java
@@ -0,0 +1,167 @@
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.io.URLUtil;
+import org.jetbrains.groovy.compiler.rt.GroovyRtConstants;
+import org.jetbrains.jps.api.GlobalOptions;
+import org.jetbrains.jps.build.Standalone;
+import org.jetbrains.jps.incremental.groovy.JpsGroovycRunner;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.java.JpsJavaDependenciesEnumerator;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.JpsModelSerializationDataService;
+import org.jetbrains.jps.model.serialization.JpsPathVariablesConfiguration;
+import org.jetbrains.jps.model.serialization.JpsProjectLoader;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "SameParameterValue"})
+public class JpsBootstrapMain {
+
+ private static final String PROJECT_HOME_ENV = "JPS_BOOTSTRAP_PROJECT_HOME";
+
+ @SuppressWarnings("ConfusingArgumentToVarargsMethod")
+ public static void main(String[] args) throws Throwable {
+ long startTime = System.currentTimeMillis();
+
+ String projectHomeString = System.getenv(PROJECT_HOME_ENV);
+ if (projectHomeString == null) {
+ System.err.println("Please set " + PROJECT_HOME_ENV + " environment variable");
+ System.exit(1);
+ }
+
+ Path projectHome = Path.of(projectHomeString);
+ Path buildDir = projectHome.resolve("out").resolve("jps-bootstrap");
+
+ JpsModel model = JpsElementFactory.getInstance().createModel();
+ JpsPathVariablesConfiguration pathVariablesConfiguration =
+ JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(model.getGlobal());
+ pathVariablesConfiguration.addPathVariable(
+ "MAVEN_REPOSITORY",
+ FileUtilRt.toSystemIndependentName(buildDir.resolve("m2").toAbsolutePath().toString()));
+
+ System.setProperty("kotlin.incremental.compilation", "true");
+ System.setProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "true");
+
+ Map pathVariables = JpsModelSerializationDataService.computeAllPathVariables(model.getGlobal());
+ JpsProjectLoader.loadProject(model.getProject(), pathVariables, projectHome.toString());
+ System.out.println(
+ "Loaded project " + projectHome + ": " +
+ model.getProject().getModules().size() + " modules, " +
+ model.getProject().getLibraryCollection().getLibraries().size() + " libraries in " +
+ (System.currentTimeMillis() - startTime) + " ms");
+
+ long buildStart = System.currentTimeMillis();
+
+ addSdk(model, "corretto-11", System.getProperty("java.home"));
+
+ String url = "file://" + FileUtilRt.toSystemIndependentName(buildDir.resolve("out").toString());
+ JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(model.getProject()).setOutputUrl(url);
+
+ System.setProperty(JpsGroovycRunner.GROOVYC_IN_PROCESS, "true");
+ System.setProperty(GroovyRtConstants.GROOVYC_ASM_RESOLVING_ONLY, "false");
+ System.setProperty(GlobalOptions.USE_DEFAULT_FILE_LOGGING_OPTION, "true");
+ System.setProperty(GlobalOptions.LOG_DIR_OPTION, buildDir.resolve("log").toString());
+ System.out.println("Log: " + System.getProperty(GlobalOptions.LOG_DIR_OPTION));
+
+ JpsModule module = model.getProject().getModules()
+ .stream()
+ .filter(m -> "intellij.idea.community.build".equals(m.getName()))
+ .findFirst().orElseThrow();
+
+ final boolean[] errors = {false};
+
+ Path dataStorageRoot = buildDir.resolve("jps-build-data");
+ Standalone.runBuild(
+ () -> model,
+ dataStorageRoot.toFile(),
+ false,
+ // setOf("intellij.platform.util"),
+ ContainerUtil.set(module.getName()),
+ false,
+ Collections.emptyList(),
+ false,
+ msg -> {
+ BuildMessage.Kind kind = msg.getKind();
+ //if (kind == BuildMessage.Kind.ERROR || kind == BuildMessage.Kind.INTERNAL_BUILDER_ERROR || kind == BuildMessage.Kind.PROGRESS) {
+ if (kind == BuildMessage.Kind.ERROR || kind == BuildMessage.Kind.INTERNAL_BUILDER_ERROR) {
+ System.out.println(kind + " " + msg.getMessageText());
+ }
+
+ if (kind == BuildMessage.Kind.ERROR || kind == BuildMessage.Kind.INTERNAL_BUILDER_ERROR) {
+ errors[0] = true;
+ }
+ }
+ );
+
+ System.out.println("Finished build in " + (System.currentTimeMillis() - buildStart) + " ms");
+
+ if (errors[0]) {
+ System.err.println("Build finished with errors");
+ System.exit(1);
+ }
+
+ JpsJavaDependenciesEnumerator enumerator = JpsJavaExtensionService
+ .dependencies(module)
+ .runtimeOnly()
+ .productionOnly()
+ .recursively()
+ .withoutSdk();
+
+ List roots = new ArrayList<>();
+ for (File file : enumerator.classes().getRoots()) {
+ URL toURL = file.toURI().toURL();
+ roots.add(toURL);
+ }
+
+ try (URLClassLoader classloader = new URLClassLoader(roots.toArray(new URL[0]), ClassLoader.getSystemClassLoader())) {
+ Class> mainClass = classloader.loadClass("org.jetbrains.intellij.build.ExampleGroovyMain");
+
+ MethodHandles.lookup()
+ .findStatic(mainClass, "main", MethodType.methodType(Void.TYPE, String[].class))
+ .invokeExact(args);
+ }
+ }
+
+ private static List readModulesFromReleaseFile(Path jdkDir) throws IOException {
+ Path releaseFile = jdkDir.resolve("release");
+ Properties p = new Properties();
+ try (InputStream is = Files.newInputStream(releaseFile)) {
+ p.load(is);
+ }
+ String jbrBaseUrl = URLUtil.JRT_PROTOCOL + URLUtil.SCHEME_SEPARATOR +
+ FileUtil.toSystemIndependentName(jdkDir.toFile().getAbsolutePath()) +
+ URLUtil.JAR_SEPARATOR;
+ String modules = p.getProperty("MODULES");
+ return ContainerUtil.map(StringUtil.split(StringUtil.unquoteString(modules), " "), s -> jbrBaseUrl + s);
+ }
+
+ private static void addSdk(JpsModel model, String sdkName, String sdkHome) throws IOException {
+ JpsJavaExtensionService.getInstance().addJavaSdk(model.getGlobal(), sdkName, sdkHome);
+ JpsLibrary additionalSdk = model.getGlobal().getLibraryCollection().findLibrary(sdkName);
+ if (additionalSdk == null) {
+ throw new IllegalStateException("SDK " + sdkHome + " was not found");
+ }
+
+ for (String moduleUrl : readModulesFromReleaseFile(Path.of(sdkHome))) {
+ additionalSdk.addRoot(moduleUrl, JpsOrderRootType.COMPILED);
+ }
+ }
+}