From 12f2a727a350e1cf634e77bb1fe40702382d6b60 Mon Sep 17 00:00:00 2001 From: Leonid Shalupov Date: Mon, 23 Jan 2023 13:07:49 +0100 Subject: [PATCH] jps-bootstrap: convert jps-bootstrap to Kotlin GitOrigin-RevId: 3c7549a2452bffe1d95f5f3a8961a49cb6bbdb7a --- .../jps-bootstrap/jps-bootstrap-classpath.xml | 19 +- .../jpsBootstrap/ClassesFromCompileInc.kt | 142 ++--- .../jpsBootstrap/JpsBootstrapMain.kt | 576 +++++++++--------- .../jpsBootstrap/JpsBootstrapUtil.kt | 213 +++---- .../org/jetbrains/jpsBootstrap/JpsBuild.kt | 290 ++++----- .../jetbrains/jpsBootstrap/JpsProjectUtils.kt | 171 +++--- .../jetbrains/jpsBootstrap/KotlinCompiler.kt | 53 +- 7 files changed, 651 insertions(+), 813 deletions(-) diff --git a/platform/jps-bootstrap/jps-bootstrap-classpath.xml b/platform/jps-bootstrap/jps-bootstrap-classpath.xml index 47e54fbceba2..738fd16928b6 100644 --- a/platform/jps-bootstrap/jps-bootstrap-classpath.xml +++ b/platform/jps-bootstrap/jps-bootstrap-classpath.xml @@ -71,9 +71,6 @@ - - - - + - - - - - - - + diff --git a/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/ClassesFromCompileInc.kt b/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/ClassesFromCompileInc.kt index b467ab7352b6..e527df1c0cb3 100644 --- a/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/ClassesFromCompileInc.kt +++ b/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/ClassesFromCompileInc.kt @@ -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 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 productionModuleOutputs = downloadProductionPartsFromMetadataJson(manifest, communityRoot, modules); - assignModuleOutputs(project, productionModuleOutputs); + @Throws(IOException::class, InterruptedException::class) + fun downloadProjectClasses(project: JpsProject, communityRoot: BuildDependenciesCommunityRoot, modules: Collection?) { + 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 productionModuleOutputs) { - Path nonExistentPath = Path.of( + private fun assignModuleOutputs(project: JpsProject, productionModuleOutputs: Map) { + 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 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 downloadProductionPartsFromMetadataJson(Path metadataJson, BuildDependenciesCommunityRoot communityRoot, Collection 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?): Map { + 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>> = 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>> tasks = new ArrayList<>(); - for (final JpsModule module : modules) { - Callable> 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 files; + var files: Map? = null } } diff --git a/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/JpsBootstrapMain.kt b/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/JpsBootstrapMain.kt index 830e8880a839..adeaf6b8b046 100644 --- a/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/JpsBootstrapMain.kt +++ b/platform/jps-bootstrap/src/main/java/org/jetbrains/jpsBootstrap/JpsBootstrapMain.kt @@ -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?) { + 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? = 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