From bd6aedce3338bb1e8312e3dd57c3f5db77d1c6f7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Karpukhin Date: Mon, 4 May 2026 23:05:15 +0200 Subject: [PATCH] IJPL-242344 ij-light: Add a way to start IJ Light from installers GitOrigin-RevId: d2dba6305bafefaaed23cc22d6ba4d66fa23a032 --- .../build/impl/LinuxDistributionBuilder.kt | 9 ++-- .../build/impl/MacDistributionBuilder.kt | 9 ++-- .../build/impl/WindowsDistributionBuilder.kt | 9 ++-- .../impl/productInfo/ProductInfoGenerator.kt | 51 +++++++++++++++++++ .../pluginInitContextSelectPluginsToLoad.kt | 3 +- 5 files changed, 71 insertions(+), 10 deletions(-) diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt index 2c6d64cdee78..f2989855bf3f 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/LinuxDistributionBuilder.kt @@ -24,6 +24,7 @@ import org.jetbrains.intellij.build.impl.OsSpecificDistributionBuilder.Companion import org.jetbrains.intellij.build.impl.client.getAdditionalEmbeddedClientVmOptions import org.jetbrains.intellij.build.impl.productInfo.PRODUCT_INFO_FILE_NAME import org.jetbrains.intellij.build.impl.productInfo.generateEmbeddedFrontendLaunchData +import org.jetbrains.intellij.build.impl.productInfo.generateIjLightLaunchData import org.jetbrains.intellij.build.impl.productInfo.generateProductInfoJson import org.jetbrains.intellij.build.impl.productInfo.resolveProductInfoJsonSibling import org.jetbrains.intellij.build.impl.productInfo.validateProductJson @@ -402,10 +403,12 @@ class LinuxDistributionBuilder( stdioRedirectArg = context.productProperties.stdioRedirectArg, startupWmClass = getLinuxFrameClass(context), customCommands = run { + val vmOptionsFilePath: (BuildContext) -> String = { + "bin/${it.add64IfNeeded(it.productProperties.baseFileName)}.vmoptions" + } val base = listOfNotNull( - generateEmbeddedFrontendLaunchData(arch, OsFamily.LINUX, context) { - "bin/${it.add64IfNeeded(it.productProperties.baseFileName)}.vmoptions" - }, + generateEmbeddedFrontendLaunchData(arch, OsFamily.LINUX, context, vmOptionsFilePath), + generateIjLightLaunchData(arch, OsFamily.LINUX, context, vmOptionsFilePath), generateQodanaLaunchData(context, arch, OsFamily.LINUX), generateStdioMcpRunnerLaunchData(context, OsFamily.LINUX) ) diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt index 01c8956f0063..a1fec45b460e 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/MacDistributionBuilder.kt @@ -32,6 +32,7 @@ import org.jetbrains.intellij.build.impl.OsSpecificDistributionBuilder.Companion import org.jetbrains.intellij.build.impl.macOS.MachOUuid import org.jetbrains.intellij.build.impl.productInfo.PRODUCT_INFO_FILE_NAME import org.jetbrains.intellij.build.impl.productInfo.generateEmbeddedFrontendLaunchData +import org.jetbrains.intellij.build.impl.productInfo.generateIjLightLaunchData import org.jetbrains.intellij.build.impl.productInfo.generateProductInfoJson import org.jetbrains.intellij.build.impl.productInfo.resolveProductInfoJsonSibling import org.jetbrains.intellij.build.impl.productInfo.validateProductJson @@ -421,10 +422,12 @@ class MacDistributionBuilder( mainClass = context.ideMainClassName, stdioRedirectArg = context.productProperties.stdioRedirectArg, customCommands = run { + val vmOptionsFilePath: (BuildContext) -> String = { + "${toRoot}bin/${it.productProperties.baseFileName}.vmoptions" + } val base = listOfNotNull( - generateEmbeddedFrontendLaunchData(arch, OsFamily.MACOS, context) { - "${toRoot}bin/${it.productProperties.baseFileName}.vmoptions" - }, + generateEmbeddedFrontendLaunchData(arch, OsFamily.MACOS, context, vmOptionsFilePath), + generateIjLightLaunchData(arch, OsFamily.MACOS, context, vmOptionsFilePath), generateQodanaLaunchData(context, arch, OsFamily.MACOS), generateStdioMcpRunnerLaunchData(context, OsFamily.MACOS) ) diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt index 2054b4db1222..6584f1e8670a 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/WindowsDistributionBuilder.kt @@ -30,6 +30,7 @@ import org.jetbrains.intellij.build.executeStep import org.jetbrains.intellij.build.impl.OsSpecificDistributionBuilder.Companion.suffix import org.jetbrains.intellij.build.impl.productInfo.PRODUCT_INFO_FILE_NAME import org.jetbrains.intellij.build.impl.productInfo.generateEmbeddedFrontendLaunchData +import org.jetbrains.intellij.build.impl.productInfo.generateIjLightLaunchData import org.jetbrains.intellij.build.impl.productInfo.generateProductInfoJson import org.jetbrains.intellij.build.impl.productInfo.resolveProductInfoJsonSibling import org.jetbrains.intellij.build.impl.productInfo.validateProductJson @@ -547,10 +548,12 @@ internal class WindowsDistributionBuilder( mainClass = context.ideMainClassName, stdioRedirectArg = context.productProperties.stdioRedirectArg, customCommands = run { + val vmOptionsFilePath: (BuildContext) -> String = { clientCtx -> + "bin/${clientCtx.add64IfNeeded(clientCtx.productProperties.baseFileName)}.exe.vmoptions" + } val base = listOfNotNull( - generateEmbeddedFrontendLaunchData(arch, OsFamily.WINDOWS, context) { clientCtx -> - "bin/${clientCtx.add64IfNeeded(clientCtx.productProperties.baseFileName)}.exe.vmoptions" - }, + generateEmbeddedFrontendLaunchData(arch, OsFamily.WINDOWS, context, vmOptionsFilePath), + generateIjLightLaunchData(arch, OsFamily.WINDOWS, context, vmOptionsFilePath), generateQodanaLaunchData(context, arch, OsFamily.WINDOWS), generateStdioMcpRunnerLaunchData(context, OsFamily.WINDOWS) ) diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/productInfo/ProductInfoGenerator.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/productInfo/ProductInfoGenerator.kt index 279dc847a6f6..6d05ae39543f 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/impl/productInfo/ProductInfoGenerator.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/impl/productInfo/ProductInfoGenerator.kt @@ -13,6 +13,7 @@ import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import org.jetbrains.intellij.build.BuildContext import org.jetbrains.intellij.build.BuiltinModulesFileData +import org.jetbrains.intellij.build.JarPackagerDependencyHelper import org.jetbrains.intellij.build.JvmArchitecture import org.jetbrains.intellij.build.OsFamily import org.jetbrains.intellij.build.impl.Git @@ -141,6 +142,56 @@ internal suspend fun generateEmbeddedFrontendLaunchData( ) } +private suspend fun BuildContext.ijLightInitialPluginIds(): List = listOf( + "com.intellij", + findFrontendCustomizationPluginId(this), + "com.jetbrains.remoteDevelopment", + "intellij.platform.ijent.impl", + "org.jetbrains.plugins.textmate", + "org.jetbrains.plugins.terminal", + "com.intellij.modules.jcef", +) + +internal suspend fun generateIjLightLaunchData( + arch: JvmArchitecture, + os: OsFamily, + ideContext: BuildContext, + vmOptionsFilePath: (BuildContext) -> String, +): CustomCommandLaunchData? { + val clientContext = ideContext.getEmbeddedFrontendProductContext() + ?: ideContext.takeIf { it.productProperties.platformPrefix == "JetBrainsClient" } + ?: return null + + val explicitPluginIds = clientContext.ijLightInitialPluginIds().joinToString(",") + + return CustomCommandLaunchData( + commands = listOf("ijLight"), + vmOptionsFilePath = vmOptionsFilePath(clientContext), + bootClassPathJarNames = clientContext.bootClassPathJarNames, + additionalJvmArguments = clientContext.getAdditionalJvmArguments(os, arch) + + getAdditionalEmbeddedClientVmOptions(os, ideContext) + + "-Didea.load.plugins.id=$explicitPluginIds" + + "-Dintellij.platform.use.proxies.for.open.services=true" + + "-Didea.vfs.max-file-length-to-cache=0", + mainClass = clientContext.ideMainClassName, + envVarBaseName = "JETBRAINS_CLIENT", + dataDirectoryName = clientContext.systemSelector, + ) +} + +private suspend fun findFrontendCustomizationPluginId(clientContext: BuildContext): String { + val rootModule = clientContext.productProperties.rootModuleForModularLoader + val candidates = clientContext.getBundledPluginModules().filter { + it != rootModule && (it.endsWith(".frontend.split.customization") || it.endsWith(".frontend.customization")) + } + if (candidates.size != 1) { + clientContext.messages.logErrorAndThrow("Expected exactly one frontend customization plugin module for ${clientContext.productProperties.rootModuleForModularLoader}, got $candidates") + } + val pluginModuleName = candidates.single() + val helper = JarPackagerDependencyHelper(clientContext.outputProvider) + return helper.getPluginIdByModule(clientContext.outputProvider.findRequiredModule(pluginModuleName)) +} + /** * See 'IJI-2228 Publish product-info.json next to installers'. * diff --git a/platform/core-impl/src/com/intellij/ide/plugins/pluginInitContextSelectPluginsToLoad.kt b/platform/core-impl/src/com/intellij/ide/plugins/pluginInitContextSelectPluginsToLoad.kt index 82fbe98ce947..7fc20b2b724b 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/pluginInitContextSelectPluginsToLoad.kt +++ b/platform/core-impl/src/com/intellij/ide/plugins/pluginInitContextSelectPluginsToLoad.kt @@ -135,7 +135,8 @@ private fun PluginInitializationContext.selectFromExplicitSubset( onPluginExcluded: (PluginMainDescriptor, PluginNonLoadReason) -> Unit, ): List { val compatiblePlugins = selectMostRecentCompatible(discoveredPlugins, onPluginExcluded) - val pluginIdsSubset = essentialPlugins + explicitPluginSubsetToLoad!! + val explicitSubset = explicitPluginSubsetToLoad ?: emptySet() + val pluginIdsSubset = essentialPlugins + explicitSubset val pluginSubset = compatiblePlugins.filter { it.pluginId in pluginIdsSubset } val ambiguousPluginSet = AmbiguousPluginSet.build(compatiblePlugins) val requiredModules = PluginDependencyAnalysis.getRequiredTransitiveModules(