diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/BuildServer.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/BuildServer.kt index 7bf1d89b5bb3..e3ef71f05b23 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/BuildServer.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/BuildServer.kt @@ -56,9 +56,8 @@ fun getIdeSystemProperties(runDir: Path): Map { /** Returns IDE installation directory */ suspend fun buildProductInProcess(request: BuildRequest): Path { return TraceManager.spanBuilder("build ide").setAttribute("request", request.toString()).useWithScope { - val platformPrefix = request.platformPrefix val configuration = createConfiguration(homePath = request.homePath, productionClassOutput = request.productionClassOutput) - val productConfiguration = getProductConfiguration(configuration, platformPrefix) + val productConfiguration = getProductConfiguration(configuration, request.platformPrefix) try { buildProduct(productConfiguration = productConfiguration, request = request) } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt index 8a7c72000105..f42771f4aae7 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/dev/IdeBuilder.kt @@ -186,7 +186,12 @@ internal suspend fun buildProduct(productConfiguration: ProductConfiguration, re } launch { - computeIdeFingerprint(platformDistributionEntriesDeferred, pluginDistributionEntriesDeferred, runDir, request.homePath) + computeIdeFingerprint( + platformDistributionEntriesDeferred = platformDistributionEntriesDeferred, + pluginDistributionEntriesDeferred = pluginDistributionEntriesDeferred, + runDir = runDir, + homePath = request.homePath, + ) } } .invokeOnCompletion { diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildHelper.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildHelper.kt index ab2ca47526b6..77d0440eec1f 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildHelper.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildHelper.kt @@ -24,8 +24,8 @@ import org.jetbrains.intellij.build.io.runJava import java.nio.file.Files import java.nio.file.NoSuchFileException import java.nio.file.Path +import java.nio.file.StandardCopyOption import java.util.function.Predicate -import kotlin.io.path.copyTo import kotlin.time.Duration internal fun span(spanBuilder: SpanBuilder, task: Runnable) { @@ -104,7 +104,7 @@ suspend fun runApplicationStarter( BuildUtils.addVmProperty(jvmArgs, "java.system.class.loader", "com.intellij.util.lang.PathClassLoader") BuildUtils.addVmProperty(jvmArgs, "idea.platform.prefix", context.productProperties.platformPrefix) jvmArgs.addAll(BuildUtils.propertiesToJvmArgs(systemProperties.entries.map { it.key to it.value.toString() })) - jvmArgs.addAll(vmOptions.takeIf { it.isNotEmpty() } ?: listOf("-Xmx1536m")) + jvmArgs.addAll(vmOptions.takeIf { it.isNotEmpty() } ?: listOf("-Xmx2g")) System.getProperty("intellij.build.${arguments.first()}.debug.port")?.let { jvmArgs.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:$it") } @@ -135,7 +135,7 @@ suspend fun runApplicationStarter( val logFile = systemDir.resolve("log").resolve("idea.log") if (Files.exists(logFile)) { val logFileToPublish = Files.createTempFile("idea-", ".log") - logFile.copyTo(target = logFileToPublish, overwrite = true) + Files.copy(logFile, logFileToPublish, StandardCopyOption.REPLACE_EXISTING) context.notifyArtifactBuilt(logFileToPublish) Span.current().addEvent("log file $logFileToPublish attached to build artifacts") } diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt index b756e3274e2f..51ebb11aa01f 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/BuildTasksImpl.kt @@ -29,9 +29,6 @@ import org.jetbrains.idea.maven.aether.ArtifactRepositoryManager import org.jetbrains.idea.maven.aether.ProgressConsumer import org.jetbrains.intellij.build.* import org.jetbrains.intellij.build.TraceManager.spanBuilder -import org.jetbrains.intellij.build.dev.BuildRequest -import org.jetbrains.intellij.build.dev.buildProductInProcess -import org.jetbrains.intellij.build.dev.getIdeSystemProperties import org.jetbrains.intellij.build.impl.productInfo.PRODUCT_INFO_FILE_NAME import org.jetbrains.intellij.build.impl.productInfo.ProductInfoLaunchData import org.jetbrains.intellij.build.impl.productInfo.checkInArchive @@ -67,7 +64,6 @@ import java.util.concurrent.TimeUnit import java.util.zip.Deflater import kotlin.io.NoSuchFileException import kotlin.io.path.* -import kotlin.time.Duration.Companion.seconds internal const val PROPERTIES_FILE_NAME: String = "idea.properties" @@ -106,7 +102,7 @@ class BuildTasksImpl(private val context: BuildContextImpl) : BuildTasks { compilationTasks = compilationTasks, context = context, ) - buildSearchableOptions(distState.platform, context) + buildSearchableOptions(context) buildNonBundledPlugins( pluginsToPublish = pluginsToPublish, compressPluginArchive = context.options.compressZipFiles, @@ -649,7 +645,7 @@ private suspend fun compileModulesForDistribution(context: BuildContext): Distri hasPlatformCoverage( productLayout = productLayout, enabledPluginModules = enabledPluginModules, - context = context + context = context, ) if (context.shouldBuildDistributions()) { @@ -665,40 +661,14 @@ private suspend fun compileModulesForDistribution(context: BuildContext): Distri } val builtinModuleData = spanBuilder("build provided module list").useWithScope { - //val ideClasspath = createIdeClassPath(platform = platform, context = context) - - var homePath: Path? = null - var newClassPath: Collection? = null - val systemProperties = HashMap() - val tempDir = context.paths.tempDir.resolve("builtinModules") - buildProductInProcess( - BuildRequest( - devRootPath = tempDir, - isUnpackedDist = true, - platformPrefix = context.productProperties.platformPrefix ?: "idea", - additionalModules = emptyList(), - homePath = context.paths.projectHome, - platformClassPathConsumer = { classPath, runDir -> - newClassPath = classPath - homePath = runDir - for ((name, value) in getIdeSystemProperties(runDir)) { - systemProperties.put(name, value) - } - } - ) - ) - Files.deleteIfExists(providedModuleFile) + val tempDir = context.paths.tempDir.resolve("builtinModules") // start the product in headless mode using com.intellij.ide.plugins.BundledPluginsLister - runApplicationStarter( - context = context, + createDevIdeBuild(context = context).runProduct( tempDir = tempDir, - ideClasspath = newClassPath!!.map { it.toString() }, - arguments = listOf("listBundledPlugins", providedModuleFile.toString()), - timeout = 30.seconds, - homePath = homePath ?: context.paths.projectHome, - systemProperties = systemProperties, + listOf("listBundledPlugins", providedModuleFile.toString()), ) + context.productProperties.customizeBuiltinModules(context = context, builtinModulesFile = providedModuleFile) try { val builtinModuleData = readBuiltinModulesFile(file = providedModuleFile) @@ -791,7 +761,7 @@ suspend fun buildDistributions(context: BuildContext): Unit = spanBuilder("build "skip building product distributions because " + "'intellij.build.target.os' property is set to '${BuildOptions.OS_NONE}'" ) - buildSearchableOptions(distributionState.platform, context) + buildSearchableOptions(context) buildNonBundledPlugins( pluginsToPublish = pluginsToPublish, compressPluginArchive = context.options.compressZipFiles, @@ -1418,7 +1388,7 @@ fun collectModulesToCompile(context: BuildContext, result: MutableSet) { // Captures information about all available inspections in a JSON format as part of an Inspectopedia project. // This is later used by Qodana and other tools. // Keymaps are extracted as an XML file and also used in authoring help. -internal suspend fun buildAdditionalAuthoringArtifacts(ideClassPath: Set, context: BuildContext) { +internal suspend fun buildAdditionalAuthoringArtifacts(ide: DevIdeBuild, context: BuildContext) { context.executeStep(spanBuilder("build authoring asserts"), BuildOptions.DOC_AUTHORING_ASSETS_STEP) { val commands = listOf( Pair("inspectopedia-generator", "inspections-${context.applicationInfo.productCode.lowercase()}"), @@ -1429,12 +1399,7 @@ internal suspend fun buildAdditionalAuthoringArtifacts(ideClassPath: Set launch { val temporaryStepDirectory = temporaryBuildDirectory.resolve(command.first) val targetPath = temporaryStepDirectory.resolve(command.second) - runApplicationStarter( - context = context, - tempDir = temporaryStepDirectory, - ideClasspath = ideClassPath, - arguments = listOf(command.first, targetPath.toString()) - ) + ide.runProduct(tempDir = temporaryStepDirectory, arguments = listOf(command.first, targetPath.toString())) val targetFile = context.paths.artifactDir.resolve("${command.second}.zip") zipWithCompression( diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DevIdeBuild.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DevIdeBuild.kt new file mode 100644 index 000000000000..ff145a875aab --- /dev/null +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DevIdeBuild.kt @@ -0,0 +1,56 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@file:Suppress("ReplacePutWithAssignment") + +package org.jetbrains.intellij.build.impl + +import org.jetbrains.intellij.build.BuildContext +import org.jetbrains.intellij.build.dev.BuildRequest +import org.jetbrains.intellij.build.dev.buildProductInProcess +import org.jetbrains.intellij.build.dev.getIdeSystemProperties +import org.jetbrains.intellij.build.io.DEFAULT_TIMEOUT +import java.nio.file.Path +import kotlin.time.Duration.Companion.seconds + +internal suspend fun createDevIdeBuild(context: BuildContext): DevIdeBuild { + var newClassPath: Collection? = null + val runDir = buildProductInProcess( + BuildRequest( + devRootPath = context.paths.tempDir.resolve("dev-run"), + isUnpackedDist = true, + platformPrefix = context.productProperties.platformPrefix ?: "idea", + additionalModules = emptyList(), + homePath = context.paths.projectHome, + productionClassOutput = context.classesOutputDirectory.resolve("production"), + platformClassPathConsumer = { classPath, _ -> + newClassPath = classPath + } + ) + ) + return DevIdeBuild(context = context, homePath = runDir, classPath = newClassPath!!) +} + +/** + * Only for use in build scripts, not for dev mode / integrations tests. + */ +internal class DevIdeBuild( + private val context: BuildContext, + private val homePath: Path, + private val classPath: Collection, +) { + suspend fun runProduct( + tempDir: Path, + arguments: List, + systemProperties: Map = emptyMap(), + isLongRunning: Boolean = false, + ) { + runApplicationStarter( + context = context, + tempDir = tempDir, + ideClasspath = classPath.map { it.toString() }, + arguments = arguments, + timeout = if (isLongRunning) DEFAULT_TIMEOUT else 30.seconds, + homePath = homePath, + systemProperties = systemProperties + getIdeSystemProperties(homePath), + ) + } +} \ No newline at end of file diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt index af3e66fce3ca..8a4c38106a53 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.kt @@ -65,10 +65,10 @@ internal suspend fun buildDistribution( context.productProperties.validateLayout(state.platform, context) createBuildBrokenPluginListJob(context) - val flatIdeClassPath = createIdeClassPath(state.platform, context) + val ide = createDevIdeBuild(context) if (context.productProperties.buildDocAuthoringAssets) { launch { - buildAdditionalAuthoringArtifacts(ideClassPath = flatIdeClassPath, context = context) + buildAdditionalAuthoringArtifacts(ide = ide, context = context) } } @@ -76,7 +76,7 @@ internal suspend fun buildDistribution( val entries = coroutineScope { // must be completed before plugin building context.executeStep(spanBuilder("build searchable options index"), BuildOptions.SEARCHABLE_OPTIONS_INDEX_STEP) { - buildSearchableOptions(ideClassPath = flatIdeClassPath, context = context) + buildSearchableOptions(ide = ide, context = context) } val pluginLayouts = getPluginLayoutsByJpsModuleNames( @@ -1359,12 +1359,11 @@ suspend fun createIdeClassPath(platform: PlatformLayout, context: BuildContext): } suspend fun buildSearchableOptions( - platform: PlatformLayout, context: BuildContext, systemProperties: Map = emptyMap(), ): Path? { return buildSearchableOptions( - ideClassPath = createIdeClassPath(platform, context), + ide = createDevIdeBuild(context), context = context, systemProperties = systemProperties, ) @@ -1373,8 +1372,8 @@ suspend fun buildSearchableOptions( /** * Build index which is used to search options in the Settings dialog. */ -suspend fun buildSearchableOptions( - ideClassPath: Set, +private suspend fun buildSearchableOptions( + ide: DevIdeBuild, context: BuildContext, systemProperties: Map = emptyMap(), ): Path? { @@ -1406,13 +1405,11 @@ suspend fun buildSearchableOptions( } // Start the product in headless mode using com.intellij.ide.ui.search.TraverseUIStarter. // It'll process all UI elements in the `Settings` dialog and build an index for them. - runApplicationStarter( - context = context, + ide.runProduct( tempDir = context.paths.tempDir.resolve("searchableOptions"), - ideClasspath = ideClassPath, arguments = listOf("traverseUI", targetDirectory.toString(), "true"), - vmOptions = listOf("-Xmx2g"), systemProperties = systemProperties, + isLongRunning = true, ) check(Files.isDirectory(targetDirectory)) { "Failed to build searchable options index: $targetDirectory does not exist. See log above for error output from traverseUI run."