mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
jps-bootstrap: convert jps-bootstrap to Kotlin
GitOrigin-RevId: 3c7549a2452bffe1d95f5f3a8961a49cb6bbdb7a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
088c21cac3
commit
12f2a727a3
@@ -71,9 +71,6 @@
|
||||
</resolver:resolve>
|
||||
|
||||
<delete dir="${classes.dir}" />
|
||||
<mkdir dir="${classes.dir}/java" />
|
||||
<mkdir dir="${classes.dir}/kotlin" />
|
||||
|
||||
<java
|
||||
classname="org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
|
||||
classpathref="classpath.kotlin.compiler"
|
||||
@@ -88,24 +85,12 @@
|
||||
<arg path="${jps.bootstrap.dir}/src/main/java" />
|
||||
<arg path="${community.home}/platform/build-scripts/downloader/src" />
|
||||
<arg value="-d" />
|
||||
<arg value="${classes.dir}/kotlin" />
|
||||
<arg value="${classes.dir}" />
|
||||
</java>
|
||||
<javac
|
||||
destdir="${classes.dir}/java"
|
||||
encoding="UTF-8"
|
||||
release="11"
|
||||
debug="true"
|
||||
includeantruntime="false"
|
||||
classpathref="classpath.buildscripts">
|
||||
<classpath path="${classes.dir}/kotlin" />
|
||||
<src path="${jps.bootstrap.dir}/src/main/java" />
|
||||
<src path="${community.home}/platform/build-scripts/downloader/src" />
|
||||
</javac>
|
||||
|
||||
<delete file="${classes.dir}.jar" />
|
||||
<zip destfile="${classes.dir}.jar">
|
||||
<fileset dir="${classes.dir}/java" />
|
||||
<fileset dir="${classes.dir}/kotlin" />
|
||||
<fileset dir="${classes.dir}" />
|
||||
</zip>
|
||||
|
||||
<mkdir dir="${uber.dir}" />
|
||||
|
||||
+59
-83
@@ -1,106 +1,82 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jpsBootstrap;
|
||||
package org.jetbrains.jpsBootstrap
|
||||
|
||||
import com.google.common.base.StandardSystemProperty;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader;
|
||||
import org.jetbrains.jps.model.JpsProject;
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
|
||||
import org.jetbrains.jps.model.java.JpsJavaProjectExtension;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
import org.jetbrains.jps.util.JpsPathUtil;
|
||||
import com.google.common.base.StandardSystemProperty
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader.downloadFileToCacheLocation
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader.extractFileToCacheLocation
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.verbose
|
||||
import org.jetbrains.jps.model.JpsProject
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import org.jetbrains.jps.util.JpsPathUtil
|
||||
import java.io.IOException
|
||||
import java.net.URI
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
object ClassesFromCompileInc {
|
||||
const val MANIFEST_JSON_URL_ENV_NAME = "JPS_BOOTSTRAP_MANIFEST_JSON_URL"
|
||||
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.verbose;
|
||||
|
||||
public final class ClassesFromCompileInc {
|
||||
public final static String MANIFEST_JSON_URL_ENV_NAME = "JPS_BOOTSTRAP_MANIFEST_JSON_URL";
|
||||
|
||||
public static void downloadProjectClasses(JpsProject project, BuildDependenciesCommunityRoot communityRoot, Collection<JpsModule> modules) throws IOException, InterruptedException {
|
||||
String manifestUrl = System.getenv(MANIFEST_JSON_URL_ENV_NAME);
|
||||
if (manifestUrl == null || manifestUrl.isBlank()) {
|
||||
throw new IllegalStateException("Env variable '" + MANIFEST_JSON_URL_ENV_NAME + "' is missing or empty");
|
||||
}
|
||||
verbose("Got manifest json url '" + manifestUrl + "' from $" + MANIFEST_JSON_URL_ENV_NAME);
|
||||
|
||||
final Path manifest = BuildDependenciesDownloader.downloadFileToCacheLocation(communityRoot, URI.create(manifestUrl));
|
||||
Map<JpsModule, Path> productionModuleOutputs = downloadProductionPartsFromMetadataJson(manifest, communityRoot, modules);
|
||||
assignModuleOutputs(project, productionModuleOutputs);
|
||||
@Throws(IOException::class, InterruptedException::class)
|
||||
fun downloadProjectClasses(project: JpsProject, communityRoot: BuildDependenciesCommunityRoot, modules: Collection<JpsModule?>?) {
|
||||
val manifestUrl = System.getenv(MANIFEST_JSON_URL_ENV_NAME)
|
||||
check(!(manifestUrl == null || manifestUrl.isBlank())) { "Env variable '$MANIFEST_JSON_URL_ENV_NAME' is missing or empty" }
|
||||
verbose("Got manifest json url '$manifestUrl' from $$MANIFEST_JSON_URL_ENV_NAME")
|
||||
val manifest = downloadFileToCacheLocation(communityRoot, URI.create(manifestUrl))
|
||||
val productionModuleOutputs = downloadProductionPartsFromMetadataJson(manifest, communityRoot, modules)
|
||||
assignModuleOutputs(project, productionModuleOutputs)
|
||||
}
|
||||
|
||||
private static void assignModuleOutputs(JpsProject project, Map<JpsModule, Path> productionModuleOutputs) {
|
||||
Path nonExistentPath = Path.of(
|
||||
private fun assignModuleOutputs(project: JpsProject, productionModuleOutputs: Map<JpsModule, Path>) {
|
||||
val nonExistentPath = Path.of(
|
||||
System.getProperty(StandardSystemProperty.JAVA_IO_TMPDIR.key()),
|
||||
UUID.randomUUID().toString());
|
||||
UUID.randomUUID().toString())
|
||||
|
||||
// Set it to non-existent path since we won't run build and standard built output won't be available anyway
|
||||
JpsJavaProjectExtension projectExtension = JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(project);
|
||||
projectExtension.setOutputUrl(JpsPathUtil.pathToUrl(nonExistentPath.toString()));
|
||||
|
||||
for (Map.Entry<JpsModule, Path> entry : productionModuleOutputs.entrySet()) {
|
||||
JpsModule module = entry.getKey();
|
||||
final JpsJavaModuleExtension javaExtension = JpsJavaExtensionService.getInstance().getOrCreateModuleExtension(module);
|
||||
javaExtension.setOutputUrl(JpsPathUtil.pathToUrl(entry.getValue().toString()));
|
||||
javaExtension.setInheritOutput(false);
|
||||
val projectExtension = JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(project)
|
||||
projectExtension.outputUrl = JpsPathUtil.pathToUrl(nonExistentPath.toString())
|
||||
for ((module, value) in productionModuleOutputs) {
|
||||
val javaExtension = JpsJavaExtensionService.getInstance().getOrCreateModuleExtension(module)
|
||||
javaExtension.outputUrl = JpsPathUtil.pathToUrl(value.toString())
|
||||
javaExtension.isInheritOutput = false
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<JpsModule, Path> downloadProductionPartsFromMetadataJson(Path metadataJson, BuildDependenciesCommunityRoot communityRoot, Collection<JpsModule> modules) throws InterruptedException, IOException {
|
||||
CompilationPartsMetadata partsMetadata;
|
||||
|
||||
try (BufferedReader manifestReader = Files.newBufferedReader(metadataJson, StandardCharsets.UTF_8)) {
|
||||
partsMetadata = new Gson().fromJson(manifestReader, CompilationPartsMetadata.class);
|
||||
private fun downloadProductionPartsFromMetadataJson(metadataJson: Path, communityRoot: BuildDependenciesCommunityRoot, modules: Collection<JpsModule?>?): Map<JpsModule, Path> {
|
||||
var partsMetadata: CompilationPartsMetadata
|
||||
Files.newBufferedReader(metadataJson, StandardCharsets.UTF_8).use { manifestReader -> partsMetadata = Gson().fromJson(manifestReader, CompilationPartsMetadata::class.java) }
|
||||
check(partsMetadata.files!!.isNotEmpty()) { "partsMetadata.files is empty, check $metadataJson" }
|
||||
val tasks: MutableList<Callable<Pair<JpsModule, Path>>> = ArrayList()
|
||||
for (module in modules!!) {
|
||||
val c = Callable {
|
||||
val modulePrefix = "production/" + module!!.name
|
||||
val hash = partsMetadata.files!![modulePrefix]
|
||||
?: throw IllegalStateException("Unable to find module output by name '$modulePrefix' in $metadataJson")
|
||||
val outputPartUri = URI.create(partsMetadata.serverUrl + "/" + partsMetadata.prefix + "/" + modulePrefix + "/" + hash + ".jar")
|
||||
val outputPart = downloadFileToCacheLocation(communityRoot, outputPartUri)
|
||||
val outputPartExtracted = extractFileToCacheLocation(communityRoot, outputPart)
|
||||
module to outputPartExtracted
|
||||
}
|
||||
tasks.add(c)
|
||||
}
|
||||
|
||||
if (partsMetadata.files.isEmpty()) {
|
||||
throw new IllegalStateException("partsMetadata.files is empty, check " + metadataJson);
|
||||
}
|
||||
|
||||
List<Callable<Pair<JpsModule, Path>>> tasks = new ArrayList<>();
|
||||
for (final JpsModule module : modules) {
|
||||
Callable<Pair<JpsModule, Path>> c = () -> {
|
||||
String modulePrefix = "production/" + module.getName();
|
||||
|
||||
String hash = partsMetadata.files.get(modulePrefix);
|
||||
if (hash == null) {
|
||||
throw new IllegalStateException("Unable to find module output by name '" + modulePrefix + "' in " + metadataJson);
|
||||
}
|
||||
|
||||
URI outputPartUri = URI.create(partsMetadata.serverUrl + "/" + partsMetadata.prefix + "/" + modulePrefix + "/" + hash + ".jar");
|
||||
final Path outputPart = BuildDependenciesDownloader.downloadFileToCacheLocation(communityRoot, outputPartUri);
|
||||
final Path outputPartExtracted = BuildDependenciesDownloader.extractFileToCacheLocation(communityRoot, outputPart);
|
||||
|
||||
return Pair.pair(module, outputPartExtracted);
|
||||
};
|
||||
tasks.add(c);
|
||||
}
|
||||
|
||||
return JpsBootstrapUtil.executeTasksInParallel(tasks)
|
||||
.stream().collect(Collectors.toUnmodifiableMap(pair -> pair.getFirst(), pair -> pair.getSecond()));
|
||||
return JpsBootstrapUtil.executeTasksInParallel(tasks).associate { it.first to it.second }
|
||||
}
|
||||
|
||||
private static final class CompilationPartsMetadata {
|
||||
private class CompilationPartsMetadata {
|
||||
@SerializedName("server-url")
|
||||
public String serverUrl;
|
||||
public String prefix;
|
||||
var serverUrl: String? = null
|
||||
var prefix: String? = null
|
||||
|
||||
/**
|
||||
* Map compilation part path to a hash, for now SHA-256 is used.
|
||||
* sha256(file) == hash, though that may be changed in the future.
|
||||
*/
|
||||
public Map<String, String> files;
|
||||
var files: Map<String, String>? = null
|
||||
}
|
||||
}
|
||||
|
||||
+274
-302
@@ -1,192 +1,131 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jpsBootstrap
|
||||
|
||||
package org.jetbrains.jpsBootstrap;
|
||||
import com.google.common.hash.Hashing
|
||||
import com.intellij.execution.CommandLineWrapperUtil
|
||||
import com.intellij.openapi.diagnostic.IdeaLogRecordFormatter
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.text.Strings
|
||||
import com.intellij.util.ExceptionUtil
|
||||
import jetbrains.buildServer.messages.serviceMessages.MessageWithAttributes
|
||||
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes
|
||||
import org.apache.commons.cli.*
|
||||
import org.jetbrains.annotations.Contract
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.fatal
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.setVerboseEnabled
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.verbose
|
||||
import org.jetbrains.intellij.build.dependencies.JdkDownloader.getJavaExecutable
|
||||
import org.jetbrains.intellij.build.dependencies.JdkDownloader.getJdkHome
|
||||
import org.jetbrains.intellij.build.dependencies.TeamCityHelper.isUnderTeamCity
|
||||
import org.jetbrains.jps.incremental.storage.ProjectStamps
|
||||
import org.jetbrains.jps.model.JpsModel
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import org.jetbrains.jpsBootstrap.JpsBootstrapUtil.toBooleanChecked
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import java.util.*
|
||||
import java.util.logging.ConsoleHandler
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.Logger
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.io.path.readLines
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.intellij.execution.CommandLineWrapperUtil;
|
||||
import com.intellij.openapi.diagnostic.IdeaLogRecordFormatter;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.Strings;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import jetbrains.buildServer.messages.serviceMessages.MessageWithAttributes;
|
||||
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes;
|
||||
import org.apache.commons.cli.*;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging;
|
||||
import org.jetbrains.intellij.build.dependencies.JdkDownloader;
|
||||
import org.jetbrains.intellij.build.dependencies.TeamCityHelper;
|
||||
import org.jetbrains.jps.incremental.storage.ProjectStamps;
|
||||
import org.jetbrains.jps.model.JpsModel;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
class JpsBootstrapMain(args: Array<String>?) {
|
||||
private val projectHome: Path
|
||||
private val communityHome: BuildDependenciesCommunityRoot
|
||||
private var moduleNameToRun: String? = null
|
||||
private var classNameToRun: String? = null
|
||||
private val buildTargetXmx: String
|
||||
private val jpsBootstrapWorkDir: Path
|
||||
private var javaArgsFileTarget: Path? = null
|
||||
private var mainArgsToRun: List<String>? = null
|
||||
private val additionalSystemProperties: Properties
|
||||
private val additionalSystemPropertiesFromPropertiesFile: Properties
|
||||
private val onlyDownloadJdk: Boolean
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.*;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.stream.Collectors;
|
||||
init {
|
||||
initLogging()
|
||||
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.*;
|
||||
import static org.jetbrains.jpsBootstrap.JpsBootstrapUtil.getJpsArtifactsResolutionRetryProperties;
|
||||
import static org.jetbrains.jpsBootstrap.JpsBootstrapUtil.getTeamCitySystemProperties;
|
||||
import static org.jetbrains.jpsBootstrap.JpsBootstrapUtil.toBooleanChecked;
|
||||
|
||||
@SuppressWarnings({"SameParameterValue"})
|
||||
public class JpsBootstrapMain {
|
||||
private static final String DEFAULT_BUILD_SCRIPT_XMX = "4g";
|
||||
|
||||
private static final String COMMUNITY_HOME_ENV = "JPS_BOOTSTRAP_COMMUNITY_HOME";
|
||||
private static final String JPS_BOOTSTRAP_VERBOSE = "JPS_BOOTSTRAP_VERBOSE";
|
||||
|
||||
private static final Option OPT_HELP = Option.builder("h").longOpt("help").build();
|
||||
private static final Option OPT_VERBOSE = Option.builder("v").longOpt("verbose").desc("Show more logging from jps-bootstrap and the building process").build();
|
||||
private static final Option OPT_SYSTEM_PROPERTY = Option.builder("D").hasArgs().valueSeparator('=').desc("Pass system property to the build script").build();
|
||||
private static final Option OPT_PROPERTIES_FILE = Option.builder().longOpt("properties-file").hasArg().desc("Pass system properties to the build script from specified properties file https://en.wikipedia.org/wiki/.properties").build();
|
||||
private static final Option OPT_BUILD_TARGET_XMX = Option.builder().longOpt("build-target-xmx").hasArg().desc("Specify Xmx to run build script. default: " + DEFAULT_BUILD_SCRIPT_XMX).build();
|
||||
private static final Option OPT_JAVA_ARGFILE_TARGET = Option.builder().longOpt("java-argfile-target").hasArg().desc("Write java argfile to this file").build();
|
||||
private static final Option OPT_ONLY_DOWNLOAD_JDK = Option.builder().longOpt("download-jdk").desc("Download project JDK and exit").build();
|
||||
private static final List<Option> ALL_OPTIONS =
|
||||
Arrays.asList(OPT_HELP, OPT_VERBOSE, OPT_SYSTEM_PROPERTY, OPT_PROPERTIES_FILE, OPT_JAVA_ARGFILE_TARGET, OPT_BUILD_TARGET_XMX, OPT_ONLY_DOWNLOAD_JDK);
|
||||
|
||||
static final boolean underTeamCity = TeamCityHelper.INSTANCE.isUnderTeamCity();
|
||||
|
||||
private static Options createCliOptions() {
|
||||
Options opts = new Options();
|
||||
|
||||
for (Option option : ALL_OPTIONS) {
|
||||
opts.addOption(option);
|
||||
val cmdline = try {
|
||||
DefaultParser().parse(createCliOptions(), args, true)
|
||||
}
|
||||
catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
showUsagesAndExit()
|
||||
throw IllegalStateException("NOT_REACHED")
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Path jpsBootstrapWorkDir = null;
|
||||
|
||||
try {
|
||||
JpsBootstrapMain mainInstance = new JpsBootstrapMain(args);
|
||||
jpsBootstrapWorkDir = mainInstance.jpsBootstrapWorkDir;
|
||||
mainInstance.main();
|
||||
System.exit(0);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
fatal(ExceptionUtil.getThrowableText(t));
|
||||
|
||||
// Better diagnostics for local users
|
||||
if (!TeamCityHelper.INSTANCE.isUnderTeamCity()) {
|
||||
System.err.println("\n###### ERROR EXIT due to FATAL error: " + t.getMessage() + "\n");
|
||||
String work = jpsBootstrapWorkDir == null ? "PROJECT_HOME/build/jps-bootstrap-work" : jpsBootstrapWorkDir.toString();
|
||||
System.err.println("###### You may try to delete caches at " + work + " and retry");
|
||||
}
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private final Path projectHome;
|
||||
private final BuildDependenciesCommunityRoot communityHome;
|
||||
private final String moduleNameToRun;
|
||||
private final String classNameToRun;
|
||||
private final String buildTargetXmx;
|
||||
private final Path jpsBootstrapWorkDir;
|
||||
private final Path javaArgsFileTarget;
|
||||
private final List<String> mainArgsToRun;
|
||||
private final Properties additionalSystemProperties;
|
||||
private final Properties additionalSystemPropertiesFromPropertiesFile;
|
||||
private final boolean onlyDownloadJdk;
|
||||
|
||||
public JpsBootstrapMain(String[] args) throws IOException {
|
||||
initLogging();
|
||||
|
||||
CommandLine cmdline;
|
||||
try {
|
||||
cmdline = (new DefaultParser()).parse(createCliOptions(), args, true);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
showUsagesAndExit();
|
||||
throw new IllegalStateException("NOT_REACHED");
|
||||
val freeArgs = cmdline.args.toList()
|
||||
if (cmdline.hasOption(OPT_HELP) || freeArgs.isEmpty()) {
|
||||
showUsagesAndExit()
|
||||
}
|
||||
|
||||
final List<String> freeArgs = Arrays.asList(cmdline.getArgs());
|
||||
if (cmdline.hasOption(OPT_HELP) || freeArgs.size() < 1) {
|
||||
showUsagesAndExit();
|
||||
}
|
||||
|
||||
projectHome = Path.of(freeArgs.get(0)).normalize();
|
||||
onlyDownloadJdk = cmdline.hasOption(OPT_ONLY_DOWNLOAD_JDK);
|
||||
projectHome = Path.of(freeArgs.first()).normalize()
|
||||
onlyDownloadJdk = cmdline.hasOption(OPT_ONLY_DOWNLOAD_JDK)
|
||||
if (onlyDownloadJdk) {
|
||||
moduleNameToRun = null;
|
||||
classNameToRun = null;
|
||||
mainArgsToRun = Collections.emptyList();
|
||||
javaArgsFileTarget = null;
|
||||
moduleNameToRun = null
|
||||
classNameToRun = null
|
||||
mainArgsToRun = emptyList()
|
||||
javaArgsFileTarget = null
|
||||
}
|
||||
else {
|
||||
moduleNameToRun = freeArgs.get(1);
|
||||
classNameToRun = freeArgs.get(2);
|
||||
mainArgsToRun = freeArgs.subList(3, freeArgs.size());
|
||||
javaArgsFileTarget = Path.of(cmdline.getOptionValue(OPT_JAVA_ARGFILE_TARGET));
|
||||
moduleNameToRun = freeArgs[1]
|
||||
classNameToRun = freeArgs[2]
|
||||
mainArgsToRun = freeArgs.subList(3, freeArgs.size)
|
||||
javaArgsFileTarget = Path.of(cmdline.getOptionValue(OPT_JAVA_ARGFILE_TARGET))
|
||||
}
|
||||
|
||||
additionalSystemProperties = cmdline.getOptionProperties("D");
|
||||
|
||||
additionalSystemPropertiesFromPropertiesFile = new Properties();
|
||||
additionalSystemProperties = cmdline.getOptionProperties("D")
|
||||
additionalSystemPropertiesFromPropertiesFile = Properties()
|
||||
if (cmdline.hasOption(OPT_PROPERTIES_FILE)) {
|
||||
Path propertiesFile = Path.of(cmdline.getOptionValue(OPT_PROPERTIES_FILE));
|
||||
try (Reader reader = Files.newBufferedReader(propertiesFile)) {
|
||||
info("Loading properties from " + propertiesFile);
|
||||
additionalSystemPropertiesFromPropertiesFile.load(reader);
|
||||
val propertiesFile = Path.of(cmdline.getOptionValue(OPT_PROPERTIES_FILE))
|
||||
Files.newBufferedReader(propertiesFile).use { reader ->
|
||||
info("Loading properties from $propertiesFile")
|
||||
additionalSystemPropertiesFromPropertiesFile.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
String verboseEnv = System.getenv(JPS_BOOTSTRAP_VERBOSE);
|
||||
BuildDependenciesLogging.setVerboseEnabled(cmdline.hasOption(OPT_VERBOSE) || (verboseEnv != null && toBooleanChecked(verboseEnv)));
|
||||
val verboseEnv = System.getenv(JPS_BOOTSTRAP_VERBOSE)
|
||||
setVerboseEnabled(cmdline.hasOption(OPT_VERBOSE) || (verboseEnv != null && verboseEnv.toBooleanChecked()))
|
||||
|
||||
String communityHomeString = System.getenv(COMMUNITY_HOME_ENV);
|
||||
if (communityHomeString == null) {
|
||||
throw new IllegalStateException("Please set " + COMMUNITY_HOME_ENV + " environment variable");
|
||||
}
|
||||
|
||||
communityHome = new BuildDependenciesCommunityRoot(Path.of(communityHomeString));
|
||||
jpsBootstrapWorkDir = projectHome.resolve("build").resolve("jps-bootstrap-work");
|
||||
|
||||
info("Working directory: " + jpsBootstrapWorkDir);
|
||||
Files.createDirectories(jpsBootstrapWorkDir);
|
||||
|
||||
buildTargetXmx = cmdline.hasOption(OPT_BUILD_TARGET_XMX) ? cmdline.getOptionValue(OPT_BUILD_TARGET_XMX) : DEFAULT_BUILD_SCRIPT_XMX;
|
||||
val communityHomeString = System.getenv(COMMUNITY_HOME_ENV)
|
||||
?: error("Please set $COMMUNITY_HOME_ENV environment variable")
|
||||
communityHome = BuildDependenciesCommunityRoot(Path.of(communityHomeString))
|
||||
jpsBootstrapWorkDir = projectHome.resolve("build").resolve("jps-bootstrap-work")
|
||||
info("Working directory: $jpsBootstrapWorkDir")
|
||||
Files.createDirectories(jpsBootstrapWorkDir)
|
||||
buildTargetXmx = if (cmdline.hasOption(OPT_BUILD_TARGET_XMX)) cmdline.getOptionValue(OPT_BUILD_TARGET_XMX) else DEFAULT_BUILD_SCRIPT_XMX
|
||||
}
|
||||
|
||||
private Path downloadJdk() {
|
||||
Path jdkHome;
|
||||
private fun downloadJdk(): Path {
|
||||
val jdkHome: Path
|
||||
if (underTeamCity) {
|
||||
jdkHome = JdkDownloader.getJdkHome(communityHome);
|
||||
SetParameterServiceMessage setParameterServiceMessage = new SetParameterServiceMessage(
|
||||
jdkHome = getJdkHome(communityHome)
|
||||
var setParameterServiceMessage = SetParameterServiceMessage(
|
||||
"jps.bootstrap.java.home", jdkHome.toString()
|
||||
);
|
||||
System.out.println(setParameterServiceMessage.asString());
|
||||
setParameterServiceMessage = new SetParameterServiceMessage(
|
||||
"jps.bootstrap.java.executable", JdkDownloader.INSTANCE.getJavaExecutable(jdkHome).toString());
|
||||
System.out.println(setParameterServiceMessage.asString());
|
||||
)
|
||||
println(setParameterServiceMessage.asString())
|
||||
setParameterServiceMessage = SetParameterServiceMessage(
|
||||
"jps.bootstrap.java.executable", getJavaExecutable(jdkHome).toString())
|
||||
println(setParameterServiceMessage.asString())
|
||||
}
|
||||
else {
|
||||
// On local run JDK was already downloaded via jps-bootstrap.{sh,cmd}
|
||||
jdkHome = Path.of(System.getProperty("java.home"));
|
||||
jdkHome = Path.of(System.getProperty("java.home"))
|
||||
}
|
||||
return jdkHome;
|
||||
return jdkHome
|
||||
}
|
||||
|
||||
private void main() throws Throwable {
|
||||
Path jdkHome = downloadJdk();
|
||||
@Throws(Throwable::class)
|
||||
private fun main() {
|
||||
val jdkHome = downloadJdk()
|
||||
if (onlyDownloadJdk) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -194,133 +133,123 @@ public class JpsBootstrapMain {
|
||||
* Don't override settings properties if they're already present in System.properties(), in additionalSystemProperties or
|
||||
* in additionalSystemPropertiesFromPropertiesFile.
|
||||
*/
|
||||
Properties resolverRetrySettingsProperties = getJpsArtifactsResolutionRetryProperties(
|
||||
val resolverRetrySettingsProperties = JpsBootstrapUtil.getJpsArtifactsResolutionRetryProperties(
|
||||
additionalSystemPropertiesFromPropertiesFile,
|
||||
additionalSystemProperties,
|
||||
System.getProperties()
|
||||
);
|
||||
resolverRetrySettingsProperties.forEach((k, v) -> System.setProperty((String) k, (String) v));
|
||||
)
|
||||
resolverRetrySettingsProperties.forEach { k, v -> System.setProperty(k as String, v as String) }
|
||||
|
||||
Path kotlincHome = KotlinCompiler.downloadAndExtractKotlinCompiler(communityHome);
|
||||
|
||||
JpsModel model = JpsProjectUtils.loadJpsProject(projectHome, jdkHome, kotlincHome);
|
||||
JpsModule module = JpsProjectUtils.getModuleByName(model, moduleNameToRun);
|
||||
|
||||
downloadOrBuildClasses(module, model, kotlincHome);
|
||||
|
||||
List<File> moduleRuntimeClasspath = JpsProjectUtils.getModuleRuntimeClasspath(module);
|
||||
verbose("Module " + module.getName() + " classpath:\n " + moduleRuntimeClasspath.stream().map(JpsBootstrapMain::fileDebugInfo).collect(Collectors.joining("\n ")));
|
||||
|
||||
writeJavaArgfile(moduleRuntimeClasspath);
|
||||
val kotlincHome = KotlinCompiler.downloadAndExtractKotlinCompiler(communityHome)
|
||||
val model = JpsProjectUtils.loadJpsProject(projectHome, jdkHome, kotlincHome)
|
||||
val module = JpsProjectUtils.getModuleByName(model, moduleNameToRun!!)
|
||||
downloadOrBuildClasses(module, model, kotlincHome)
|
||||
val moduleRuntimeClasspath = JpsProjectUtils.getModuleRuntimeClasspath(module)
|
||||
verbose("""Module ${module.name} classpath:
|
||||
${moduleRuntimeClasspath.stream().map { file: File? -> fileDebugInfo(file) }.collect(Collectors.joining("\n "))}""")
|
||||
writeJavaArgfile(moduleRuntimeClasspath)
|
||||
}
|
||||
|
||||
private void removeOpenedPackage(List<String> openedPackages, String openedPackage, List<String> unknownPackages) {
|
||||
private fun removeOpenedPackage(openedPackages: MutableList<String>, openedPackage: String, unknownPackages: MutableList<String>) {
|
||||
if (!openedPackages.remove(openedPackage)) {
|
||||
unknownPackages.add(openedPackage);
|
||||
unknownPackages.add(openedPackage)
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getOpenedPackages() throws Exception {
|
||||
Path openedPackagesPath = communityHome.communityRoot.resolve("plugins/devkit/devkit-core/src/run/OpenedPackages.txt");
|
||||
List<String> openedPackages = ContainerUtil.filter(Files.readAllLines(openedPackagesPath), it -> !it.isBlank());
|
||||
List<String> unknownPackages = new ArrayList<>();
|
||||
|
||||
if (!SystemInfo.isWindows) {
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/sun.awt.windows=ALL-UNNAMED", unknownPackages);
|
||||
}
|
||||
if (!SystemInfo.isMac) {
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/com.apple.eawt=ALL-UNNAMED", unknownPackages);
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/com.apple.eawt.event=ALL-UNNAMED", unknownPackages);
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/com.apple.laf=ALL-UNNAMED", unknownPackages);
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED", unknownPackages);
|
||||
}
|
||||
if (!SystemInfo.isLinux) {
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/com.sun.java.swing.plaf.gtk=ALL-UNNAMED", unknownPackages);
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED", unknownPackages);
|
||||
removeOpenedPackage(openedPackages,"--add-opens=java.desktop/sun.lwawt=ALL-UNNAMED", unknownPackages);
|
||||
}
|
||||
if (!unknownPackages.isEmpty()) {
|
||||
throw new Exception(String.format("OS specific opened packages: ['%s'] not found in '%s'. " +
|
||||
@get:Throws(Exception::class)
|
||||
private val openedPackages: List<String>
|
||||
get() {
|
||||
val openedPackagesPath = communityHome.communityRoot.resolve("plugins/devkit/devkit-core/src/run/OpenedPackages.txt")
|
||||
val openedPackages = openedPackagesPath.readLines().filter { it.isNotBlank() }.toMutableList()
|
||||
val unknownPackages = mutableListOf<String>()
|
||||
if (!SystemInfo.isWindows) {
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/sun.awt.windows=ALL-UNNAMED", unknownPackages)
|
||||
}
|
||||
if (!SystemInfo.isMac) {
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/com.apple.eawt=ALL-UNNAMED", unknownPackages)
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/com.apple.eawt.event=ALL-UNNAMED", unknownPackages)
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/com.apple.laf=ALL-UNNAMED", unknownPackages)
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/sun.lwawt.macosx=ALL-UNNAMED", unknownPackages)
|
||||
}
|
||||
if (!SystemInfo.isLinux) {
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/com.sun.java.swing.plaf.gtk=ALL-UNNAMED", unknownPackages)
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED", unknownPackages)
|
||||
removeOpenedPackage(openedPackages, "--add-opens=java.desktop/sun.lwawt=ALL-UNNAMED", unknownPackages)
|
||||
}
|
||||
if (unknownPackages.isNotEmpty()) {
|
||||
throw Exception(String.format("OS specific opened packages: ['%s'] not found in '%s'. " +
|
||||
"Probably you need to clean up OS-specific package names in org.jetbrains.jpsBootstrap.JpsBootstrapMain",
|
||||
String.join("','", unknownPackages), openedPackagesPath));
|
||||
java.lang.String.join("','", unknownPackages), openedPackagesPath))
|
||||
}
|
||||
return openedPackages
|
||||
}
|
||||
return openedPackages;
|
||||
}
|
||||
|
||||
private void writeJavaArgfile(List<File> moduleRuntimeClasspath) throws Exception {
|
||||
Properties systemProperties = new Properties();
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun writeJavaArgfile(moduleRuntimeClasspath: List<File?>?) {
|
||||
val systemProperties = Properties()
|
||||
if (underTeamCity) {
|
||||
systemProperties.putAll(getTeamCitySystemProperties());
|
||||
systemProperties.putAll(JpsBootstrapUtil.teamCitySystemProperties)
|
||||
}
|
||||
systemProperties.putAll(additionalSystemPropertiesFromPropertiesFile);
|
||||
systemProperties.putAll(additionalSystemProperties);
|
||||
|
||||
systemProperties.putIfAbsent("file.encoding", "UTF-8"); // just in case
|
||||
systemProperties.putIfAbsent("java.awt.headless", "true");
|
||||
systemProperties.putAll(additionalSystemPropertiesFromPropertiesFile)
|
||||
systemProperties.putAll(additionalSystemProperties)
|
||||
systemProperties.putIfAbsent("file.encoding", "UTF-8") // just in case
|
||||
systemProperties.putIfAbsent("java.awt.headless", "true")
|
||||
|
||||
/*
|
||||
* Add dependencies resolution retries properties to argfile.
|
||||
* Don't override them if they're already present in additionalSystemProperties or in additionalSystemPropertiesFromPropertiesFile.
|
||||
*/
|
||||
Properties resolverRetrySettingsProperties = getJpsArtifactsResolutionRetryProperties(
|
||||
* Add dependencies resolution retries properties to argfile.
|
||||
* Don't override them if they're already present in additionalSystemProperties or in additionalSystemPropertiesFromPropertiesFile.
|
||||
*/
|
||||
val resolverRetrySettingsProperties = JpsBootstrapUtil.getJpsArtifactsResolutionRetryProperties(
|
||||
additionalSystemPropertiesFromPropertiesFile,
|
||||
additionalSystemProperties
|
||||
);
|
||||
systemProperties.putAll(resolverRetrySettingsProperties);
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("-ea");
|
||||
args.add("-Xmx" + buildTargetXmx);
|
||||
|
||||
args.addAll(getOpenedPackages());
|
||||
|
||||
args.addAll(convertPropertiesToCommandLineArgs(systemProperties));
|
||||
|
||||
args.add("-classpath");
|
||||
args.add(Strings.join(moduleRuntimeClasspath, File.pathSeparator));
|
||||
|
||||
args.add("-Dbuild.script.launcher.main.class=" + classNameToRun);
|
||||
args.add("org.jetbrains.intellij.build.impl.BuildScriptLauncher");
|
||||
|
||||
args.addAll(mainArgsToRun);
|
||||
|
||||
)
|
||||
systemProperties.putAll(resolverRetrySettingsProperties)
|
||||
val args: MutableList<String> = ArrayList()
|
||||
args.add("-ea")
|
||||
args.add("-Xmx$buildTargetXmx")
|
||||
args.addAll(openedPackages)
|
||||
args.addAll(convertPropertiesToCommandLineArgs(systemProperties))
|
||||
args.add("-classpath")
|
||||
args.add(Strings.join(moduleRuntimeClasspath!!, File.pathSeparator))
|
||||
args.add("-Dbuild.script.launcher.main.class=$classNameToRun")
|
||||
args.add("org.jetbrains.intellij.build.impl.BuildScriptLauncher")
|
||||
args.addAll(mainArgsToRun!!)
|
||||
CommandLineWrapperUtil.writeArgumentsFile(
|
||||
javaArgsFileTarget.toFile(),
|
||||
javaArgsFileTarget!!.toFile(),
|
||||
args,
|
||||
StandardCharsets.UTF_8
|
||||
);
|
||||
|
||||
info("java argfile:\n" + Files.readString(javaArgsFileTarget));
|
||||
)
|
||||
info("""
|
||||
java argfile:
|
||||
${Files.readString(javaArgsFileTarget)}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
private void downloadOrBuildClasses(JpsModule module, JpsModel model, Path kotlincHome) throws Throwable {
|
||||
String fromJpsBuildEnvValue = System.getenv(JpsBuild.CLASSES_FROM_JPS_BUILD_ENV_NAME);
|
||||
boolean runJpsBuild = fromJpsBuildEnvValue != null && JpsBootstrapUtil.toBooleanChecked(fromJpsBuildEnvValue) || ProjectStamps.PORTABLE_CACHES;
|
||||
@Throws(Throwable::class)
|
||||
private fun downloadOrBuildClasses(module: JpsModule, model: JpsModel, kotlincHome: Path) {
|
||||
val fromJpsBuildEnvValue = System.getenv(JpsBuild.CLASSES_FROM_JPS_BUILD_ENV_NAME)
|
||||
val runJpsBuild = (fromJpsBuildEnvValue != null && fromJpsBuildEnvValue.toBooleanChecked()) || ProjectStamps.PORTABLE_CACHES
|
||||
|
||||
String manifestJsonUrl = System.getenv(ClassesFromCompileInc.MANIFEST_JSON_URL_ENV_NAME);
|
||||
var manifestJsonUrl = System.getenv(ClassesFromCompileInc.MANIFEST_JSON_URL_ENV_NAME)
|
||||
if (manifestJsonUrl != null && manifestJsonUrl.isBlank()) {
|
||||
manifestJsonUrl = null;
|
||||
manifestJsonUrl = null
|
||||
}
|
||||
|
||||
if (runJpsBuild && manifestJsonUrl != null) {
|
||||
throw new IllegalStateException("Both env. variables are set, choose only one: " +
|
||||
check(!(runJpsBuild && manifestJsonUrl != null)) {
|
||||
"Both env. variables are set, choose only one: " +
|
||||
JpsBuild.CLASSES_FROM_JPS_BUILD_ENV_NAME + " " +
|
||||
ClassesFromCompileInc.MANIFEST_JSON_URL_ENV_NAME);
|
||||
ClassesFromCompileInc.MANIFEST_JSON_URL_ENV_NAME
|
||||
}
|
||||
|
||||
if (!runJpsBuild && manifestJsonUrl == null) {
|
||||
// Nothing specified. It's ok locally, but on buildserver we must be sure
|
||||
if (underTeamCity) {
|
||||
throw new IllegalStateException("On buildserver one of the following env. variables must be set: " +
|
||||
check(!underTeamCity) {
|
||||
"On buildserver one of the following env. variables must be set: " +
|
||||
JpsBuild.CLASSES_FROM_JPS_BUILD_ENV_NAME + " " +
|
||||
ClassesFromCompileInc.MANIFEST_JSON_URL_ENV_NAME);
|
||||
ClassesFromCompileInc.MANIFEST_JSON_URL_ENV_NAME
|
||||
}
|
||||
}
|
||||
|
||||
Set<JpsModule> modulesSubset = JpsProjectUtils.getRuntimeModulesClasspath(module);
|
||||
|
||||
JpsBuild jpsBuild = new JpsBuild(communityHome, model, jpsBootstrapWorkDir, kotlincHome);
|
||||
val modulesSubset = JpsProjectUtils.getRuntimeModulesClasspath(module)
|
||||
val jpsBuild = JpsBuild(communityHome, model, jpsBootstrapWorkDir, kotlincHome)
|
||||
|
||||
// Some workarounds like 'kotlinx.kotlinx-serialization-compiler-plugin-for-compilation' library (used as Kotlin compiler plugin)
|
||||
// require that the corresponding library was downloaded. It's unclear from modules structure which libraries exactly required
|
||||
@@ -328,71 +257,114 @@ public class JpsBootstrapMain {
|
||||
//
|
||||
// In case of running from read-to-use classes we need all dependent libraries as well
|
||||
// Instead of calculating what libraries are exactly required, download them all
|
||||
jpsBuild.resolveProjectDependencies();
|
||||
|
||||
jpsBuild.resolveProjectDependencies()
|
||||
if (manifestJsonUrl != null) {
|
||||
info("Downloading project classes from " + manifestJsonUrl);
|
||||
ClassesFromCompileInc.downloadProjectClasses(model.getProject(), communityHome, modulesSubset);
|
||||
} else {
|
||||
jpsBuild.buildModules(modulesSubset);
|
||||
info("Downloading project classes from $manifestJsonUrl")
|
||||
ClassesFromCompileInc.downloadProjectClasses(model.project, communityHome, modulesSubset)
|
||||
}
|
||||
else {
|
||||
jpsBuild.buildModules(modulesSubset)
|
||||
}
|
||||
}
|
||||
|
||||
private static String fileDebugInfo(File file) {
|
||||
try {
|
||||
if (file.exists()) {
|
||||
BasicFileAttributes attributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
|
||||
if (attributes.isDirectory()) {
|
||||
return file + " directory";
|
||||
private class SetParameterServiceMessage(name: String, value: String)
|
||||
: MessageWithAttributes(ServiceMessageTypes.BUILD_SET_PARAMETER, mapOf("name" to name, "value" to value))
|
||||
|
||||
companion object {
|
||||
private const val DEFAULT_BUILD_SCRIPT_XMX = "4g"
|
||||
private const val COMMUNITY_HOME_ENV = "JPS_BOOTSTRAP_COMMUNITY_HOME"
|
||||
private const val JPS_BOOTSTRAP_VERBOSE = "JPS_BOOTSTRAP_VERBOSE"
|
||||
private val OPT_HELP = Option.builder("h").longOpt("help").build()
|
||||
private val OPT_VERBOSE = Option.builder("v").longOpt("verbose").desc("Show more logging from jps-bootstrap and the building process").build()
|
||||
private val OPT_SYSTEM_PROPERTY = Option.builder("D").hasArgs().valueSeparator('=').desc("Pass system property to the build script").build()
|
||||
private val OPT_PROPERTIES_FILE = Option.builder().longOpt("properties-file").hasArg().desc("Pass system properties to the build script from specified properties file https://en.wikipedia.org/wiki/.properties").build()
|
||||
private val OPT_BUILD_TARGET_XMX = Option.builder().longOpt("build-target-xmx").hasArg().desc("Specify Xmx to run build script. default: $DEFAULT_BUILD_SCRIPT_XMX").build()
|
||||
private val OPT_JAVA_ARGFILE_TARGET = Option.builder().longOpt("java-argfile-target").hasArg().desc("Write java argfile to this file").build()
|
||||
private val OPT_ONLY_DOWNLOAD_JDK = Option.builder().longOpt("download-jdk").desc("Download project JDK and exit").build()
|
||||
private val ALL_OPTIONS = listOf(OPT_HELP, OPT_VERBOSE, OPT_SYSTEM_PROPERTY, OPT_PROPERTIES_FILE, OPT_JAVA_ARGFILE_TARGET, OPT_BUILD_TARGET_XMX, OPT_ONLY_DOWNLOAD_JDK)
|
||||
val underTeamCity = isUnderTeamCity
|
||||
private fun createCliOptions(): Options {
|
||||
val opts = Options()
|
||||
for (option in ALL_OPTIONS) {
|
||||
opts.addOption(option)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
var jpsBootstrapWorkDir: Path? = null
|
||||
try {
|
||||
val mainInstance = JpsBootstrapMain(args)
|
||||
@Suppress("UNUSED_VALUE")
|
||||
jpsBootstrapWorkDir = mainInstance.jpsBootstrapWorkDir
|
||||
mainInstance.main()
|
||||
exitProcess(0)
|
||||
}
|
||||
catch (t: Throwable) {
|
||||
fatal(ExceptionUtil.getThrowableText(t))
|
||||
|
||||
// Better diagnostics for local users
|
||||
if (!isUnderTeamCity) {
|
||||
System.err.println("""
|
||||
|
||||
###### ERROR EXIT due to FATAL error: ${t.message}
|
||||
|
||||
""".trimIndent())
|
||||
val work = jpsBootstrapWorkDir?.toString() ?: "PROJECT_HOME/build/jps-bootstrap-work"
|
||||
System.err.println("###### You may try to delete caches at $work and retry")
|
||||
}
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fileDebugInfo(file: File?): String {
|
||||
return try {
|
||||
if (file!!.exists()) {
|
||||
val attributes = Files.readAttributes(file.toPath(), BasicFileAttributes::class.java)
|
||||
if (attributes.isDirectory) {
|
||||
"$file directory"
|
||||
}
|
||||
else {
|
||||
val length = attributes.size()
|
||||
val sha256 = Hashing.sha256().hashBytes(Files.readAllBytes(file.toPath())).toString()
|
||||
"$file file length $length sha256 $sha256"
|
||||
}
|
||||
}
|
||||
else {
|
||||
long length = attributes.size();
|
||||
String sha256 = Hashing.sha256().hashBytes(Files.readAllBytes(file.toPath())).toString();
|
||||
return file + " file length " + length + " sha256 " + sha256;
|
||||
"$file missing file"
|
||||
}
|
||||
}
|
||||
else {
|
||||
return file + " missing file";
|
||||
catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> convertPropertiesToCommandLineArgs(Properties properties) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String propertyName : properties.stringPropertyNames().stream().sorted().collect(Collectors.toList())) {
|
||||
String value = properties.getProperty(propertyName);
|
||||
|
||||
result.add("-D" + propertyName + "=" + value);
|
||||
private fun convertPropertiesToCommandLineArgs(properties: Properties): List<String> {
|
||||
return properties
|
||||
.map { (it.key as String) to (it.value as String) }
|
||||
.sortedBy { it.first }
|
||||
.map { "-D${it.first}=${it.second}" }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Contract("->fail")
|
||||
private static void showUsagesAndExit() {
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
formatter.setWidth(1000);
|
||||
formatter.printHelp("./jps-bootstrap.sh [jps-bootstrap options] MODULE_NAME CLASS_NAME [arguments_passed_to_CLASS_NAME's_main]", createCliOptions());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
private static void initLogging() {
|
||||
java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger("");
|
||||
|
||||
for (Handler handler : rootLogger.getHandlers()) {
|
||||
rootLogger.removeHandler(handler);
|
||||
@Contract("->fail")
|
||||
private fun showUsagesAndExit() {
|
||||
val formatter = HelpFormatter()
|
||||
formatter.width = 1000
|
||||
formatter.printHelp("./jps-bootstrap.sh [jps-bootstrap options] MODULE_NAME CLASS_NAME [arguments_passed_to_CLASS_NAME's_main]", createCliOptions())
|
||||
exitProcess(1)
|
||||
}
|
||||
IdeaLogRecordFormatter layout = new IdeaLogRecordFormatter();
|
||||
ConsoleHandler consoleHandler = new ConsoleHandler();
|
||||
consoleHandler.setFormatter(new IdeaLogRecordFormatter(false, layout));
|
||||
consoleHandler.setLevel(java.util.logging.Level.WARNING);
|
||||
rootLogger.addHandler(consoleHandler);
|
||||
}
|
||||
|
||||
private static class SetParameterServiceMessage extends MessageWithAttributes {
|
||||
public SetParameterServiceMessage(@NotNull String name, @NotNull String value) {
|
||||
super(ServiceMessageTypes.BUILD_SET_PARAMETER, Map.of("name", name, "value", value));
|
||||
private fun initLogging() {
|
||||
val rootLogger = Logger.getLogger("")
|
||||
for (handler in rootLogger.handlers) {
|
||||
rootLogger.removeHandler(handler)
|
||||
}
|
||||
val layout = IdeaLogRecordFormatter()
|
||||
val consoleHandler = ConsoleHandler()
|
||||
consoleHandler.formatter = IdeaLogRecordFormatter(false, layout)
|
||||
consoleHandler.level = Level.WARNING
|
||||
rootLogger.addHandler(consoleHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+88
-125
@@ -1,159 +1,122 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jpsBootstrap;
|
||||
package org.jetbrains.jpsBootstrap
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.*;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info;
|
||||
import static org.jetbrains.jpsBootstrap.JpsBootstrapMain.underTeamCity;
|
||||
object JpsBootstrapUtil {
|
||||
const val TEAMCITY_BUILD_PROPERTIES_FILE_ENV = "TEAMCITY_BUILD_PROPERTIES_FILE"
|
||||
const val TEAMCITY_CONFIGURATION_PROPERTIES_SYSTEM_PROPERTY = "teamcity.configuration.properties.file"
|
||||
const val JPS_RESOLUTION_RETRY_ENABLED_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.enabled"
|
||||
const val JPS_RESOLUTION_RETRY_MAX_ATTEMPTS_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.max.attempts"
|
||||
const val JPS_RESOLUTION_RETRY_DELAY_MS_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.delay.ms"
|
||||
const val JPS_RESOLUTION_RETRY_BACKOFF_LIMIT_MS_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.backoff.limit.ms"
|
||||
|
||||
public final class JpsBootstrapUtil {
|
||||
public static final String TEAMCITY_BUILD_PROPERTIES_FILE_ENV = "TEAMCITY_BUILD_PROPERTIES_FILE";
|
||||
public static final String TEAMCITY_CONFIGURATION_PROPERTIES_SYSTEM_PROPERTY = "teamcity.configuration.properties.file";
|
||||
|
||||
public static final String JPS_RESOLUTION_RETRY_ENABLED_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.enabled";
|
||||
public static final String JPS_RESOLUTION_RETRY_MAX_ATTEMPTS_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.max.attempts";
|
||||
public static final String JPS_RESOLUTION_RETRY_DELAY_MS_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.delay.ms";
|
||||
public static final String JPS_RESOLUTION_RETRY_BACKOFF_LIMIT_MS_PROPERTY = "org.jetbrains.jps.incremental.dependencies.resolution.retry.backoff.limit.ms";
|
||||
|
||||
|
||||
public static boolean toBooleanChecked(String s) {
|
||||
switch (s) {
|
||||
case "true": return true;
|
||||
case "false": return false;
|
||||
default:
|
||||
throw new IllegalArgumentException("Could not convert '" + s + "' to boolean. Only 'true' or 'false' values are accepted");
|
||||
fun String.toBooleanChecked(): Boolean {
|
||||
return when (this) {
|
||||
"true" -> true
|
||||
"false" -> false
|
||||
else -> error("Could not convert '$this' to boolean. Only 'true' or 'false' values are accepted")
|
||||
}
|
||||
}
|
||||
|
||||
public static Properties getTeamCitySystemProperties() throws IOException {
|
||||
if (!underTeamCity) {
|
||||
throw new IllegalStateException("Not under TeamCity");
|
||||
@get:Throws(IOException::class)
|
||||
val teamCitySystemProperties: Properties
|
||||
get() {
|
||||
check(JpsBootstrapMain.underTeamCity) { "Not under TeamCity" }
|
||||
val buildPropertiesFile = System.getenv(TEAMCITY_BUILD_PROPERTIES_FILE_ENV)
|
||||
check(!(buildPropertiesFile == null || buildPropertiesFile.length == 0)) { "'TEAMCITY_BUILD_PROPERTIES_FILE_ENV' env. variable is missing or empty under TeamCity build" }
|
||||
val properties = Properties()
|
||||
Files.newBufferedReader(Path.of(buildPropertiesFile)).use { reader -> properties.load(reader) }
|
||||
return properties
|
||||
}
|
||||
|
||||
final String buildPropertiesFile = System.getenv(TEAMCITY_BUILD_PROPERTIES_FILE_ENV);
|
||||
if (buildPropertiesFile == null || buildPropertiesFile.length() == 0) {
|
||||
throw new IllegalStateException("'TEAMCITY_BUILD_PROPERTIES_FILE_ENV' env. variable is missing or empty under TeamCity build");
|
||||
val teamCityConfigProperties: Properties
|
||||
get() {
|
||||
val systemProperties = teamCitySystemProperties
|
||||
val configPropertiesFile = systemProperties.getProperty(TEAMCITY_CONFIGURATION_PROPERTIES_SYSTEM_PROPERTY)
|
||||
check(!(configPropertiesFile == null || configPropertiesFile.length == 0)) { "TeamCity system property '$TEAMCITY_CONFIGURATION_PROPERTIES_SYSTEM_PROPERTY' is missing under TeamCity build" }
|
||||
val properties = Properties()
|
||||
Files.newBufferedReader(Path.of(configPropertiesFile)).use { reader -> properties.load(reader) }
|
||||
return properties
|
||||
}
|
||||
|
||||
Properties properties = new Properties();
|
||||
try (BufferedReader reader = Files.newBufferedReader(Path.of(buildPropertiesFile))) {
|
||||
properties.load(reader);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static Properties getTeamCityConfigProperties() throws IOException {
|
||||
Properties systemProperties = getTeamCitySystemProperties();
|
||||
|
||||
final String configPropertiesFile = systemProperties.getProperty(TEAMCITY_CONFIGURATION_PROPERTIES_SYSTEM_PROPERTY);
|
||||
if (configPropertiesFile == null || configPropertiesFile.length() == 0) {
|
||||
throw new IllegalStateException("TeamCity system property '" + TEAMCITY_CONFIGURATION_PROPERTIES_SYSTEM_PROPERTY + "' is missing under TeamCity build");
|
||||
}
|
||||
|
||||
Properties properties = new Properties();
|
||||
try (BufferedReader reader = Files.newBufferedReader(Path.of(configPropertiesFile))) {
|
||||
properties.load(reader);
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static String getTeamCityConfigPropertyOrThrow(String configProperty) throws IOException {
|
||||
final Properties properties = getTeamCityConfigProperties();
|
||||
final String value = properties.getProperty(configProperty);
|
||||
if (value == null) {
|
||||
throw new IllegalStateException("TeamCity config property " + configProperty + " was not found");
|
||||
}
|
||||
return value;
|
||||
@Throws(IOException::class)
|
||||
fun getTeamCityConfigPropertyOrThrow(configProperty: String): String {
|
||||
val properties = teamCityConfigProperties
|
||||
return properties.getProperty(configProperty)
|
||||
?: throw IllegalStateException("TeamCity config property $configProperty was not found")
|
||||
}
|
||||
|
||||
/**
|
||||
* Create properties to enable artifacts resolution retries in org.jetbrains.jps.incremental.dependencies.DependencyResolvingBuilder
|
||||
* if ones absent in {@code existingProperties}. Latest of {@code existingProperties} has the highest priority.
|
||||
* if ones absent in `existingProperties`. Latest of `existingProperties` has the highest priority.
|
||||
*
|
||||
* @param existingProperties Existing properties to check whether required values already present.
|
||||
* @return Properties to enable artifacts resolution retries while build.
|
||||
*/
|
||||
public static Properties getJpsArtifactsResolutionRetryProperties(final Properties... existingProperties) {
|
||||
final Properties properties = new Properties();
|
||||
|
||||
final Properties existingPropertiesMerged = new Properties();
|
||||
for (Properties it : existingProperties) {
|
||||
existingPropertiesMerged.putAll(it);
|
||||
fun getJpsArtifactsResolutionRetryProperties(vararg existingProperties: Properties?): Properties {
|
||||
val properties = Properties()
|
||||
val existingPropertiesMerged = Properties()
|
||||
for (it in existingProperties) {
|
||||
existingPropertiesMerged.putAll(it!!)
|
||||
}
|
||||
|
||||
String enabled = existingPropertiesMerged.getProperty(JPS_RESOLUTION_RETRY_ENABLED_PROPERTY, "true");
|
||||
properties.put(JPS_RESOLUTION_RETRY_ENABLED_PROPERTY, enabled);
|
||||
|
||||
String maxAttempts = existingPropertiesMerged.getProperty(JPS_RESOLUTION_RETRY_MAX_ATTEMPTS_PROPERTY, "3");
|
||||
properties.put(JPS_RESOLUTION_RETRY_MAX_ATTEMPTS_PROPERTY, maxAttempts);
|
||||
|
||||
String initialDelayMs = existingPropertiesMerged.getProperty(JPS_RESOLUTION_RETRY_DELAY_MS_PROPERTY, "1000");
|
||||
properties.put(JPS_RESOLUTION_RETRY_DELAY_MS_PROPERTY, initialDelayMs);
|
||||
|
||||
String backoffLimitMs = existingPropertiesMerged.getProperty(
|
||||
val enabled = existingPropertiesMerged.getProperty(JPS_RESOLUTION_RETRY_ENABLED_PROPERTY, "true")
|
||||
properties[JPS_RESOLUTION_RETRY_ENABLED_PROPERTY] = enabled
|
||||
val maxAttempts = existingPropertiesMerged.getProperty(JPS_RESOLUTION_RETRY_MAX_ATTEMPTS_PROPERTY, "3")
|
||||
properties[JPS_RESOLUTION_RETRY_MAX_ATTEMPTS_PROPERTY] = maxAttempts
|
||||
val initialDelayMs = existingPropertiesMerged.getProperty(JPS_RESOLUTION_RETRY_DELAY_MS_PROPERTY, "1000")
|
||||
properties[JPS_RESOLUTION_RETRY_DELAY_MS_PROPERTY] = initialDelayMs
|
||||
val backoffLimitMs = existingPropertiesMerged.getProperty(
|
||||
JPS_RESOLUTION_RETRY_BACKOFF_LIMIT_MS_PROPERTY,
|
||||
Long.toString(TimeUnit.MINUTES.toMillis(5))
|
||||
);
|
||||
properties.put(JPS_RESOLUTION_RETRY_BACKOFF_LIMIT_MS_PROPERTY, backoffLimitMs);
|
||||
|
||||
return properties;
|
||||
java.lang.Long.toString(TimeUnit.MINUTES.toMillis(5))
|
||||
)
|
||||
properties[JPS_RESOLUTION_RETRY_BACKOFF_LIMIT_MS_PROPERTY] = backoffLimitMs
|
||||
return properties
|
||||
}
|
||||
|
||||
static <T> List<T> executeTasksInParallel(List<Callable<T>> tasks) throws InterruptedException {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(5);
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
info("Executing " + tasks.size() + " in parallel");
|
||||
|
||||
List<Future<T>> futures = executorService.invokeAll(tasks);
|
||||
|
||||
List<Throwable> errors = new ArrayList<>();
|
||||
List<T> results = new ArrayList<>();
|
||||
for (Future<T> future : futures) {
|
||||
fun <T> executeTasksInParallel(tasks: List<Callable<T>>): List<T> {
|
||||
val executorService = Executors.newFixedThreadPool(5)
|
||||
val start = System.currentTimeMillis()
|
||||
return try {
|
||||
info("Executing " + tasks.size + " in parallel")
|
||||
val futures = executorService.invokeAll(tasks)
|
||||
val errors: MutableList<Throwable?> = ArrayList()
|
||||
val results: MutableList<T> = ArrayList()
|
||||
for (future in futures) {
|
||||
try {
|
||||
T r = future.get(10, TimeUnit.MINUTES);
|
||||
results.add(r);
|
||||
val r = future[10, TimeUnit.MINUTES]
|
||||
results.add(r)
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
errors.add(e.getCause());
|
||||
if (errors.size() > 4) {
|
||||
executorService.shutdownNow();
|
||||
break;
|
||||
catch (e: ExecutionException) {
|
||||
errors.add(e.cause)
|
||||
if (errors.size > 4) {
|
||||
executorService.shutdownNow()
|
||||
break
|
||||
}
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
throw new IllegalStateException("Timeout waiting for results, exiting");
|
||||
catch (e: TimeoutException) {
|
||||
throw IllegalStateException("Timeout waiting for results, exiting")
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.size() > 0) {
|
||||
RuntimeException t = new RuntimeException("Unable to execute all targets, " + errors.size() + " error(s)");
|
||||
for (Throwable err : errors) {
|
||||
t.addSuppressed(err);
|
||||
if (errors.size > 0) {
|
||||
val t = RuntimeException("Unable to execute all targets, " + errors.size + " error(s)")
|
||||
for (err in errors) {
|
||||
t.addSuppressed(err)
|
||||
}
|
||||
throw t;
|
||||
throw t
|
||||
}
|
||||
|
||||
if (results.size() != tasks.size()) {
|
||||
throw new IllegalStateException("received results size != tasks size (" + results.size() + " != " + tasks.size() + ")");
|
||||
}
|
||||
|
||||
return results;
|
||||
} finally {
|
||||
info("Finished all tasks in " + (System.currentTimeMillis() - start) + " ms");
|
||||
|
||||
if (!executorService.isShutdown()) {
|
||||
executorService.shutdownNow();
|
||||
check(results.size == tasks.size) { "received results size != tasks size (" + results.size + " != " + tasks.size + ")" }
|
||||
results
|
||||
}
|
||||
finally {
|
||||
info("Finished all tasks in " + (System.currentTimeMillis() - start) + " ms")
|
||||
if (!executorService.isShutdown) {
|
||||
executorService.shutdownNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +1,194 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jpsBootstrap;
|
||||
package org.jetbrains.jpsBootstrap
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import jetbrains.buildServer.messages.serviceMessages.PublishArtifacts;
|
||||
import org.jetbrains.groovy.compiler.rt.GroovyRtConstants;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesConstants;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesUtil;
|
||||
import org.jetbrains.intellij.build.dependencies.DotNetPackagesCredentials;
|
||||
import org.jetbrains.jps.api.CmdlineRemoteProto;
|
||||
import org.jetbrains.jps.api.GlobalOptions;
|
||||
import org.jetbrains.jps.build.Standalone;
|
||||
import org.jetbrains.jps.incremental.MessageHandler;
|
||||
import org.jetbrains.jps.incremental.groovy.JpsGroovycRunner;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.model.JpsModel;
|
||||
import org.jetbrains.jps.model.JpsNamedElement;
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import jetbrains.buildServer.messages.serviceMessages.PublishArtifacts
|
||||
import org.jetbrains.groovy.compiler.rt.GroovyRtConstants
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesConstants
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.error
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.verbose
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.warn
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesUtil.cleanDirectory
|
||||
import org.jetbrains.intellij.build.dependencies.DotNetPackagesCredentials.setupSystemCredentials
|
||||
import org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope
|
||||
import org.jetbrains.jps.api.GlobalOptions
|
||||
import org.jetbrains.jps.build.Standalone
|
||||
import org.jetbrains.jps.incremental.MessageHandler
|
||||
import org.jetbrains.jps.incremental.groovy.JpsGroovycRunner
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage
|
||||
import org.jetbrains.jps.model.JpsModel
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import java.util.stream.Collectors
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
class JpsBuild(communityRoot: BuildDependenciesCommunityRoot, private val myModel: JpsModel?, jpsBootstrapWorkDir: Path, kotlincHome: Path?) {
|
||||
private val myModuleNames: Set<String>
|
||||
private val myDataStorageRoot: Path
|
||||
private val myJpsLogDir: Path
|
||||
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.*;
|
||||
import static org.jetbrains.jpsBootstrap.JpsBootstrapMain.underTeamCity;
|
||||
|
||||
public final class JpsBuild {
|
||||
public static final String CLASSES_FROM_JPS_BUILD_ENV_NAME = "JPS_BOOTSTRAP_CLASSES_FROM_JPS_BUILD";
|
||||
|
||||
private final JpsModel myModel;
|
||||
private final Set<String> myModuleNames;
|
||||
private final Path myDataStorageRoot;
|
||||
private final Path myJpsLogDir;
|
||||
|
||||
public JpsBuild(BuildDependenciesCommunityRoot communityRoot, JpsModel model, Path jpsBootstrapWorkDir, Path kotlincHome) throws Exception {
|
||||
myModel = model;
|
||||
myModuleNames = myModel.getProject().getModules().stream().map(JpsNamedElement::getName).collect(Collectors.toUnmodifiableSet());
|
||||
myDataStorageRoot = jpsBootstrapWorkDir.resolve("jps-build-data");
|
||||
|
||||
System.setProperty("aether.connector.resumeDownloads", "false");
|
||||
System.setProperty("jps.kotlin.home", kotlincHome.toString());
|
||||
init {
|
||||
myModuleNames = myModel!!.project.modules.stream().map { obj: JpsModule -> obj.name }.collect(Collectors.toUnmodifiableSet())
|
||||
myDataStorageRoot = jpsBootstrapWorkDir.resolve("jps-build-data")
|
||||
System.setProperty("aether.connector.resumeDownloads", "false")
|
||||
System.setProperty("jps.kotlin.home", kotlincHome.toString())
|
||||
|
||||
// Set IDEA home path to something or JPS can't instantiate ClasspathBoostrap.java for Groovy JPS
|
||||
// which calls PathManager.getLibPath() (it should not)
|
||||
System.setProperty(PathManager.PROPERTY_HOME_PATH, communityRoot.communityRoot.toString());
|
||||
|
||||
System.setProperty("kotlin.incremental.compilation", "true");
|
||||
System.setProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "true");
|
||||
|
||||
if (underTeamCity && System.getProperty(GlobalOptions.COMPILE_PARALLEL_MAX_THREADS_OPTION) == null) {
|
||||
System.setProperty(PathManager.PROPERTY_HOME_PATH, communityRoot.communityRoot.toString())
|
||||
System.setProperty("kotlin.incremental.compilation", "true")
|
||||
System.setProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "true")
|
||||
if (JpsBootstrapMain.Companion.underTeamCity && System.getProperty(GlobalOptions.COMPILE_PARALLEL_MAX_THREADS_OPTION) == null) {
|
||||
// Under TeamCity agents try to utilize all available cpu resources
|
||||
int cpuCount = Integer.parseInt(JpsBootstrapUtil.getTeamCityConfigPropertyOrThrow("teamcity.agent.hardware.cpuCount"));
|
||||
System.setProperty(GlobalOptions.COMPILE_PARALLEL_MAX_THREADS_OPTION, Integer.toString(cpuCount + 1));
|
||||
val cpuCount = JpsBootstrapUtil.getTeamCityConfigPropertyOrThrow("teamcity.agent.hardware.cpuCount").toInt()
|
||||
System.setProperty(GlobalOptions.COMPILE_PARALLEL_MAX_THREADS_OPTION, Integer.toString(cpuCount + 1))
|
||||
}
|
||||
|
||||
System.setProperty(JpsGroovycRunner.GROOVYC_IN_PROCESS, "true");
|
||||
System.setProperty(GroovyRtConstants.GROOVYC_ASM_RESOLVING_ONLY, "false");
|
||||
System.setProperty(GlobalOptions.USE_DEFAULT_FILE_LOGGING_OPTION, "true");
|
||||
|
||||
myJpsLogDir = jpsBootstrapWorkDir.resolve("log");
|
||||
System.setProperty(GlobalOptions.LOG_DIR_OPTION, myJpsLogDir.toString());
|
||||
|
||||
String url = "file://" + FileUtilRt.toSystemIndependentName(jpsBootstrapWorkDir.resolve("out").toString());
|
||||
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(model.getProject()).setOutputUrl(url);
|
||||
|
||||
info("Compilation log directory: " + System.getProperty(GlobalOptions.LOG_DIR_OPTION));
|
||||
System.setProperty(JpsGroovycRunner.GROOVYC_IN_PROCESS, "true")
|
||||
System.setProperty(GroovyRtConstants.GROOVYC_ASM_RESOLVING_ONLY, "false")
|
||||
System.setProperty(GlobalOptions.USE_DEFAULT_FILE_LOGGING_OPTION, "true")
|
||||
myJpsLogDir = jpsBootstrapWorkDir.resolve("log")
|
||||
System.setProperty(GlobalOptions.LOG_DIR_OPTION, myJpsLogDir.toString())
|
||||
val url = "file://" + FileUtilRt.toSystemIndependentName(jpsBootstrapWorkDir.resolve("out").toString())
|
||||
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myModel.project).outputUrl = url
|
||||
info("Compilation log directory: " + System.getProperty(GlobalOptions.LOG_DIR_OPTION))
|
||||
}
|
||||
|
||||
public void buildModules(Set<JpsModule> modules) throws Exception {
|
||||
runBuild(modules.stream().map(JpsNamedElement::getName).collect(Collectors.toSet()), false);
|
||||
@Throws(Exception::class)
|
||||
fun buildModules(modules: Set<JpsModule?>?) {
|
||||
runBuild(modules!!.stream().map { obj: JpsModule? -> obj!!.name }.collect(Collectors.toSet()), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.space.java.jps.SpaceDependencyAuthenticationDataProvider
|
||||
*/
|
||||
public void resolveProjectDependencies() throws Exception {
|
||||
info("Resolving project dependencies...");
|
||||
var spaceUsername = System.getProperty(BuildDependenciesConstants.JPS_AUTH_SPACE_USERNAME);
|
||||
var spacePassword = System.getProperty(BuildDependenciesConstants.JPS_AUTH_SPACE_PASSWORD);
|
||||
@Throws(Exception::class)
|
||||
fun resolveProjectDependencies() {
|
||||
info("Resolving project dependencies...")
|
||||
val spaceUsername = System.getProperty(BuildDependenciesConstants.JPS_AUTH_SPACE_USERNAME)
|
||||
val spacePassword = System.getProperty(BuildDependenciesConstants.JPS_AUTH_SPACE_PASSWORD)
|
||||
if (spaceUsername == null || spaceUsername.isBlank() || spacePassword == null || spacePassword.isBlank()) {
|
||||
if (!DotNetPackagesCredentials.setupSystemCredentials()) {
|
||||
if (!setupSystemCredentials()) {
|
||||
warn("Space credentials are not provided via -D" + BuildDependenciesConstants.JPS_AUTH_SPACE_USERNAME
|
||||
+ " and -D" + BuildDependenciesConstants.JPS_AUTH_SPACE_PASSWORD
|
||||
+ ". Private Space Maven dependencies, if not available locally, will fail to be resolved.");
|
||||
+ ". Private Space Maven dependencies, if not available locally, will fail to be resolved.")
|
||||
}
|
||||
}
|
||||
|
||||
final long buildStart = System.currentTimeMillis();
|
||||
|
||||
List<CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope> scopes = new ArrayList<>();
|
||||
|
||||
CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.Builder builder = CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope.newBuilder();
|
||||
scopes.add(builder.setTypeId("project-dependencies-resolving").setForceBuild(false).setAllTargets(true).build());
|
||||
|
||||
JpsMessageHandler messageHandler = new JpsMessageHandler();
|
||||
|
||||
if (!underTeamCity) {
|
||||
val buildStart = System.currentTimeMillis()
|
||||
val scopes: MutableList<TargetTypeBuildScope> = ArrayList()
|
||||
val builder = TargetTypeBuildScope.newBuilder()
|
||||
scopes.add(builder.setTypeId("project-dependencies-resolving").setForceBuild(false).setAllTargets(true).build())
|
||||
val messageHandler = JpsMessageHandler()
|
||||
if (!JpsBootstrapMain.Companion.underTeamCity) {
|
||||
// Show downloading process on local run, very handy
|
||||
messageHandler.setExplicitlyVerbose();
|
||||
messageHandler.setExplicitlyVerbose()
|
||||
}
|
||||
|
||||
Standalone.runBuild(
|
||||
() -> myModel,
|
||||
{ myModel },
|
||||
myDataStorageRoot.toFile(),
|
||||
messageHandler,
|
||||
scopes,
|
||||
false
|
||||
);
|
||||
|
||||
info("Finished resolving project dependencies in " + (System.currentTimeMillis() - buildStart) + " ms");
|
||||
|
||||
messageHandler.assertNoErrors();
|
||||
)
|
||||
info("Finished resolving project dependencies in " + (System.currentTimeMillis() - buildStart) + " ms")
|
||||
messageHandler.assertNoErrors()
|
||||
}
|
||||
|
||||
private void runBuild(Set<String> modules, boolean rebuild) throws Exception {
|
||||
final long buildStart = System.currentTimeMillis();
|
||||
|
||||
JpsMessageHandler messageHandler = new JpsMessageHandler();
|
||||
|
||||
for (String moduleName : modules) {
|
||||
if (!myModuleNames.contains(moduleName)) {
|
||||
throw new IllegalStateException("Module '" + moduleName + "' was not found");
|
||||
}
|
||||
@Throws(Exception::class)
|
||||
private fun runBuild(modules: Set<String>, rebuild: Boolean) {
|
||||
val buildStart = System.currentTimeMillis()
|
||||
val messageHandler = JpsMessageHandler()
|
||||
for (moduleName in modules) {
|
||||
check(myModuleNames.contains(moduleName)) { "Module '$moduleName' was not found" }
|
||||
}
|
||||
|
||||
Standalone.runBuild(
|
||||
() -> myModel,
|
||||
{ myModel },
|
||||
myDataStorageRoot.toFile(),
|
||||
rebuild,
|
||||
modules,
|
||||
false,
|
||||
Collections.emptyList(),
|
||||
false, emptyList(),
|
||||
false,
|
||||
messageHandler
|
||||
);
|
||||
|
||||
System.out.println("Finished building '" + String.join(" ", modules) + "' in " + (System.currentTimeMillis() - buildStart) + " ms");
|
||||
|
||||
List<String> errors = new ArrayList<>(messageHandler.myErrors);
|
||||
)
|
||||
println("Finished building '" + java.lang.String.join(" ", modules) + "' in " + (System.currentTimeMillis() - buildStart) + " ms")
|
||||
val errors: List<String> = ArrayList(messageHandler.myErrors)
|
||||
if (!errors.isEmpty() && !rebuild) {
|
||||
warn("Incremental build finished with errors. Forcing rebuild. Compilation errors:\n" + String.join("\n", errors));
|
||||
BuildDependenciesUtil.cleanDirectory(myDataStorageRoot);
|
||||
runBuild(modules, true);
|
||||
warn("""
|
||||
Incremental build finished with errors. Forcing rebuild. Compilation errors:
|
||||
${java.lang.String.join("\n", errors)}
|
||||
""".trimIndent())
|
||||
cleanDirectory(myDataStorageRoot)
|
||||
runBuild(modules, true)
|
||||
}
|
||||
else {
|
||||
messageHandler.assertNoErrors();
|
||||
messageHandler.assertNoErrors()
|
||||
}
|
||||
}
|
||||
|
||||
private class JpsMessageHandler implements MessageHandler {
|
||||
private boolean myExplicitlyVerbose;
|
||||
|
||||
private final List<String> myErrors = new CopyOnWriteArrayList<>();
|
||||
private final AtomicReference<String> myLastMessage = new AtomicReference<>();
|
||||
|
||||
public void setExplicitlyVerbose() {
|
||||
myExplicitlyVerbose = true;
|
||||
private inner class JpsMessageHandler : MessageHandler {
|
||||
private var myExplicitlyVerbose = false
|
||||
val myErrors: MutableList<String> = CopyOnWriteArrayList()
|
||||
private val myLastMessage = AtomicReference<String>()
|
||||
fun setExplicitlyVerbose() {
|
||||
myExplicitlyVerbose = true
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(BuildMessage msg) {
|
||||
BuildMessage.Kind kind = msg.getKind();
|
||||
String text = msg.toString();
|
||||
|
||||
switch (kind) {
|
||||
case PROGRESS:
|
||||
case WARNING:
|
||||
String lastMessage = myLastMessage.get();
|
||||
if (text.equals(lastMessage)) {
|
||||
override fun processMessage(msg: BuildMessage) {
|
||||
val kind = msg.kind
|
||||
val text = msg.toString()
|
||||
when (kind) {
|
||||
BuildMessage.Kind.PROGRESS, BuildMessage.Kind.WARNING -> {
|
||||
val lastMessage = myLastMessage.get()
|
||||
if (text == lastMessage) {
|
||||
// Quick and dirty way to remove duplicate verbose messages
|
||||
return;
|
||||
return
|
||||
}
|
||||
else {
|
||||
myLastMessage.set(text);
|
||||
myLastMessage.set(text)
|
||||
}
|
||||
|
||||
if (myExplicitlyVerbose) {
|
||||
info(text);
|
||||
info(text)
|
||||
}
|
||||
else {
|
||||
// Warnings mean little for bootstrapping
|
||||
verbose(text);
|
||||
verbose(text)
|
||||
}
|
||||
break;
|
||||
case ERROR:
|
||||
case INTERNAL_BUILDER_ERROR:
|
||||
// Do not log since we may call rebuild later and teamcity will fail on the first error
|
||||
myErrors.add(text);
|
||||
break;
|
||||
default:
|
||||
if (!msg.getMessageText().isBlank()) {
|
||||
if (myModuleNames.contains(msg.getMessageText())) {
|
||||
verbose(text);
|
||||
}
|
||||
else {
|
||||
info(text);
|
||||
}
|
||||
}
|
||||
|
||||
BuildMessage.Kind.ERROR, BuildMessage.Kind.INTERNAL_BUILDER_ERROR -> // Do not log since we may call rebuild later and teamcity will fail on the first error
|
||||
myErrors.add(text)
|
||||
|
||||
else -> if (!msg.messageText.isBlank()) {
|
||||
if (myModuleNames.contains(msg.messageText)) {
|
||||
verbose(text)
|
||||
}
|
||||
break;
|
||||
else {
|
||||
info(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void assertNoErrors() {
|
||||
List<String> errors = new ArrayList<>(myErrors);
|
||||
fun assertNoErrors() {
|
||||
val errors: List<String> = ArrayList(myErrors)
|
||||
if (!errors.isEmpty()) {
|
||||
System.out.println(new PublishArtifacts(myJpsLogDir + "=>jps-bootstrap-jps-logs.zip").asString());
|
||||
|
||||
for (String error : errors) {
|
||||
error(error);
|
||||
println(PublishArtifacts("$myJpsLogDir=>jps-bootstrap-jps-logs.zip").asString())
|
||||
for (error in errors) {
|
||||
error(error)
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Build finished with errors. See TC artifacts for build log. First error:\n" + errors.get(0));
|
||||
throw IllegalStateException("""
|
||||
Build finished with errors. See TC artifacts for build log. First error:
|
||||
${errors[0]}
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CLASSES_FROM_JPS_BUILD_ENV_NAME = "JPS_BOOTSTRAP_CLASSES_FROM_JPS_BUILD"
|
||||
}
|
||||
}
|
||||
|
||||
+74
-97
@@ -1,125 +1,102 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jpsBootstrap;
|
||||
package org.jetbrains.jpsBootstrap
|
||||
|
||||
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.annotations.NotNull;
|
||||
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.java.JpsJavaSdkType;
|
||||
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 org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
|
||||
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.intellij.build.dependencies.BuildDependenciesLogging.info
|
||||
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.java.JpsJavaSdkType
|
||||
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.JpsProjectLoader
|
||||
import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import kotlin.io.path.inputStream
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
object JpsProjectUtils {
|
||||
fun loadJpsProject(projectHome: Path, jdkHome: Path, kotlincHome: Path): JpsModel {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val m2LocalRepository = Path.of(System.getProperty("user.home"), ".m2", "repository")
|
||||
val model = JpsElementFactory.getInstance().createModel()
|
||||
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info;
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public final class JpsProjectUtils {
|
||||
public static JpsModel loadJpsProject(Path projectHome, Path jdkHome, Path kotlincHome) throws Exception {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
Path m2LocalRepository = Path.of(System.getProperty("user.home"), ".m2", "repository");
|
||||
JpsModel model = JpsElementFactory.getInstance().createModel();
|
||||
JpsPathVariablesConfiguration pathVariablesConfiguration =
|
||||
JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(model.getGlobal());
|
||||
val pathVariablesConfiguration = JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(model.global)
|
||||
pathVariablesConfiguration.addPathVariable(
|
||||
"MAVEN_REPOSITORY", FileUtilRt.toSystemIndependentName(m2LocalRepository.toAbsolutePath().toString()));
|
||||
|
||||
"MAVEN_REPOSITORY", FileUtilRt.toSystemIndependentName(m2LocalRepository.toAbsolutePath().toString()))
|
||||
// Required for various Kotlin compiler plugins
|
||||
pathVariablesConfiguration.addPathVariable("KOTLIN_BUNDLED", kotlincHome.toString());
|
||||
pathVariablesConfiguration.addPathVariable("KOTLIN_BUNDLED", kotlincHome.toString())
|
||||
|
||||
Map<String, String> pathVariables = JpsModelSerializationDataService.computeAllPathVariables(model.getGlobal());
|
||||
JpsProjectLoader.loadProject(model.getProject(), pathVariables, projectHome);
|
||||
System.out.println(
|
||||
"Loaded project " + projectHome + ": " +
|
||||
model.getProject().getModules().size() + " modules, " +
|
||||
model.getProject().getLibraryCollection().getLibraries().size() + " libraries in " +
|
||||
(System.currentTimeMillis() - startTime) + " ms");
|
||||
|
||||
String sdkName = "jdk-home";
|
||||
addSdk(model, sdkName, jdkHome);
|
||||
JpsSdkTableSerializer.setSdkReference(model.getProject().getSdkReferencesTable(), sdkName, JpsJavaSdkType.INSTANCE);
|
||||
|
||||
return model;
|
||||
val pathVariables = JpsModelSerializationDataService.computeAllPathVariables(model.global)
|
||||
JpsProjectLoader.loadProject(model.project, pathVariables, projectHome)
|
||||
println(
|
||||
"Loaded project $projectHome: " +
|
||||
"${model.project.modules.size} modules, " +
|
||||
"${model.project.libraryCollection.libraries.size} libraries " +
|
||||
"in ${System.currentTimeMillis() - startTime} ms")
|
||||
val sdkName = "jdk-home"
|
||||
addSdk(model, sdkName, jdkHome)
|
||||
JpsSdkTableSerializer.setSdkReference(model.project.sdkReferencesTable, sdkName, JpsJavaSdkType.INSTANCE)
|
||||
return model
|
||||
}
|
||||
|
||||
public static JpsModule getModuleByName(JpsModel model, String moduleName) {
|
||||
return model.getProject().getModules()
|
||||
.stream()
|
||||
.filter(m -> moduleName.equals(m.getName()))
|
||||
.findFirst().orElseThrow(() -> new IllegalStateException("Module " + moduleName + " is not found"));
|
||||
fun getModuleByName(model: JpsModel, moduleName: String): JpsModule {
|
||||
return model.project.modules
|
||||
.firstOrNull { it.name == moduleName }
|
||||
?: error("Module '$moduleName' was not found")
|
||||
}
|
||||
|
||||
public static List<File> getModuleRuntimeClasspath(JpsModule module) {
|
||||
JpsJavaDependenciesEnumerator enumerator = getModuleRuntimeClasspathEnumerator(module);
|
||||
|
||||
List<File> roots = new ArrayList<>(enumerator.classes().getRoots());
|
||||
roots.sort(Comparator.comparing(File::toString));
|
||||
|
||||
for (File root : roots) {
|
||||
if (!root.exists()) {
|
||||
throw new IllegalStateException("Classpath element does not exist: " + root);
|
||||
}
|
||||
fun getModuleRuntimeClasspath(module: JpsModule): List<File> {
|
||||
val enumerator = getModuleRuntimeClasspathEnumerator(module)
|
||||
val roots = enumerator.classes().roots.sortedBy { it.path }
|
||||
for (root in roots) {
|
||||
check(root.exists()) { "Classpath element does not exist: $root" }
|
||||
}
|
||||
|
||||
return roots;
|
||||
return roots
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JpsJavaDependenciesEnumerator getModuleRuntimeClasspathEnumerator(JpsModule module) {
|
||||
private fun getModuleRuntimeClasspathEnumerator(module: JpsModule): JpsJavaDependenciesEnumerator {
|
||||
return JpsJavaExtensionService
|
||||
.dependencies(module)
|
||||
.runtimeOnly()
|
||||
.productionOnly()
|
||||
.recursively()
|
||||
.withoutSdk();
|
||||
.withoutSdk()
|
||||
}
|
||||
|
||||
public static Set<JpsModule> getRuntimeModulesClasspath(JpsModule module) {
|
||||
JpsJavaDependenciesEnumerator enumerator = getModuleRuntimeClasspathEnumerator(module);
|
||||
return enumerator.getModules();
|
||||
fun getRuntimeModulesClasspath(module: JpsModule): Set<JpsModule> {
|
||||
val enumerator = getModuleRuntimeClasspathEnumerator(module)
|
||||
return enumerator.modules
|
||||
}
|
||||
|
||||
private static void addSdk(JpsModel model, String sdkName, Path sdkHome) throws IOException {
|
||||
info("Adding SDK '" + sdkName + "' at " + sdkHome);
|
||||
|
||||
JpsJavaExtensionService.getInstance().addJavaSdk(model.getGlobal(), sdkName, sdkHome.toString());
|
||||
JpsLibrary additionalSdk = model.getGlobal().getLibraryCollection().findLibrary(sdkName);
|
||||
if (additionalSdk == null) {
|
||||
throw new IllegalStateException("SDK " + sdkHome + " was not found");
|
||||
}
|
||||
|
||||
for (String moduleUrl : readModulesFromReleaseFile(sdkHome)) {
|
||||
additionalSdk.addRoot(moduleUrl, JpsOrderRootType.COMPILED);
|
||||
private fun addSdk(model: JpsModel, sdkName: String, sdkHome: Path) {
|
||||
info("Adding SDK '$sdkName' at $sdkHome")
|
||||
JpsJavaExtensionService.getInstance().addJavaSdk(model.global, sdkName, sdkHome.toString())
|
||||
val additionalSdk = model.global.libraryCollection.findLibrary(sdkName)
|
||||
?: throw IllegalStateException("SDK $sdkHome was not found")
|
||||
for (moduleUrl in readModulesFromReleaseFile(sdkHome)) {
|
||||
additionalSdk.addRoot(moduleUrl, JpsOrderRootType.COMPILED)
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> 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 fun readModulesFromReleaseFile(jdkDir: Path): List<String> {
|
||||
val releaseFile = jdkDir.resolve("release")
|
||||
|
||||
val p = Properties()
|
||||
releaseFile.inputStream().use { p.load(it) }
|
||||
val modules = p.getProperty("MODULES")
|
||||
|
||||
val jbrBaseUrl = URLUtil.JRT_PROTOCOL + URLUtil.SCHEME_SEPARATOR +
|
||||
FileUtil.toSystemIndependentName(jdkDir.toFile().absolutePath) +
|
||||
URLUtil.JAR_SEPARATOR
|
||||
|
||||
return ContainerUtil.map(StringUtil.split(StringUtil.unquoteString(modules), " ")) { s: String -> jbrBaseUrl + s }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,33 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jpsBootstrap;
|
||||
package org.jetbrains.jpsBootstrap
|
||||
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader;
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesCommunityRoot
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader.downloadFileToCacheLocation
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader.extractFileToCacheLocation
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesDownloader.getUriForMavenArtifact
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info
|
||||
import org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.verbose
|
||||
import java.nio.file.Path
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
object KotlinCompiler {
|
||||
private const val KOTLIN_IDE_MAVEN_REPOSITORY_URL =
|
||||
"https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies"
|
||||
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.info;
|
||||
import static org.jetbrains.intellij.build.dependencies.BuildDependenciesLogging.verbose;
|
||||
|
||||
public final class KotlinCompiler {
|
||||
private static final String KOTLIN_IDE_MAVEN_REPOSITORY_URL = "https://cache-redirector.jetbrains.com/maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies";
|
||||
|
||||
public static Path downloadAndExtractKotlinCompiler(BuildDependenciesCommunityRoot communityRoot) throws Exception {
|
||||
fun downloadAndExtractKotlinCompiler(communityRoot: BuildDependenciesCommunityRoot): Path {
|
||||
// We already have kotlin JPS in the classpath, fetch version from it
|
||||
String kotlincVersion;
|
||||
try (InputStream inputStream = KotlinCompiler.class.getClassLoader().getResourceAsStream("META-INF/compiler.version")) {
|
||||
kotlincVersion = new String(Objects.requireNonNull(inputStream).readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
val kotlincVersion = javaClass.classLoader.getResourceAsStream("META-INF/compiler.version")
|
||||
.use { inputStream -> inputStream!!.readAllBytes().decodeToString() }
|
||||
info("Kotlin compiler version is $kotlincVersion")
|
||||
|
||||
info("Kotlin compiler version is " + kotlincVersion);
|
||||
|
||||
URI kotlincUrl = BuildDependenciesDownloader.getUriForMavenArtifact(
|
||||
val kotlincUrl = getUriForMavenArtifact(
|
||||
KOTLIN_IDE_MAVEN_REPOSITORY_URL,
|
||||
"org.jetbrains.kotlin", "kotlin-dist-for-ide", kotlincVersion, "jar");
|
||||
Path kotlincDist = BuildDependenciesDownloader.downloadFileToCacheLocation(communityRoot, kotlincUrl);
|
||||
Path kotlinc = BuildDependenciesDownloader.extractFileToCacheLocation(communityRoot, kotlincDist);
|
||||
|
||||
verbose("Kotlin compiler is at " + kotlinc);
|
||||
|
||||
return kotlinc;
|
||||
"org.jetbrains.kotlin",
|
||||
"kotlin-dist-for-ide",
|
||||
kotlincVersion,
|
||||
"jar")
|
||||
val kotlincDist = downloadFileToCacheLocation(communityRoot, kotlincUrl)
|
||||
val kotlinc = extractFileToCacheLocation(communityRoot, kotlincDist)
|
||||
verbose("Kotlin compiler is at $kotlinc")
|
||||
return kotlinc
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user