mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-02 00:57:59 +07:00
IJPL-866 separate product modules on a class loader level (part 6 - compilation options)
GitOrigin-RevId: 315f7e1401d07a156402909b93d21ccbce63a60d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
91c5d45655
commit
a7a3c0af43
@@ -153,17 +153,23 @@ suspend inline fun BuildContext.executeStep(spanBuilder: SpanBuilder,
|
||||
@Serializable
|
||||
class BuiltinModulesFileData(
|
||||
@JvmField val plugins: MutableList<String> = mutableListOf(),
|
||||
@JvmField var modules: List<ModuleDescriptor> = emptyList(),
|
||||
@JvmField var layout: List<ProductInfoLayoutItem> = emptyList(),
|
||||
@JvmField val fileExtensions: MutableList<String> = mutableListOf(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class ModuleDescriptor(
|
||||
data class ProductInfoLayoutItem(
|
||||
@JvmField val name: String,
|
||||
@JvmField val isAlias: Boolean = false,
|
||||
@JvmField val kind: ProductInfoLayoutItemKind,
|
||||
@JvmField val classPath: List<String> = emptyList(),
|
||||
)
|
||||
|
||||
@Suppress("EnumEntryName")
|
||||
@Serializable
|
||||
enum class ProductInfoLayoutItemKind {
|
||||
plugin, pluginAlias, productModuleV2, moduleV2
|
||||
}
|
||||
|
||||
sealed interface DistFileContent {
|
||||
fun readAsStringForDebug(): String
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ fun reorderJar(relativePath: String, file: Path) {
|
||||
}
|
||||
}
|
||||
|
||||
private val excludedLibJars = java.util.Set.of(PlatformJarNames.TEST_FRAMEWORK_JAR, "junit.jar")
|
||||
internal val excludedLibJars: Set<String> = java.util.Set.of(PlatformJarNames.TEST_FRAMEWORK_JAR, "junit.jar")
|
||||
|
||||
fun generateClasspath(homeDir: Path, libDir: Path): List<String> {
|
||||
spanBuilder("generate classpath")
|
||||
|
||||
@@ -144,7 +144,11 @@ internal suspend fun buildProduct(request: BuildRequest, createProductProperties
|
||||
}
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
Files.writeString(runDir.resolve("core-classpath.txt"), classPath.joinToString(separator = "\n"))
|
||||
val cp = classPath
|
||||
.asSequence()
|
||||
.filter { !excludedLibJars.contains(it.fileName.toString()) }
|
||||
.joinToString(separator = "\n")
|
||||
Files.writeString(runDir.resolve("core-classpath.txt"), cp)
|
||||
}
|
||||
|
||||
request.platformClassPathConsumer?.invoke(classPath, runDir)
|
||||
@@ -363,6 +367,13 @@ internal suspend fun createBuildContext(
|
||||
spanBuilder("create build context").useWithScope {
|
||||
// we cannot inject a proper build time as it is a part of resources, so, set to the first day of the current month
|
||||
val buildOptionsTemplate = request.buildOptionsTemplate
|
||||
val useCompiledClassesFromProjectOutput = buildOptionsTemplate?.useCompiledClassesFromProjectOutput ?: true
|
||||
val classOutDir = if (useCompiledClassesFromProjectOutput) {
|
||||
request.productionClassOutput.parent.toString()
|
||||
}
|
||||
else {
|
||||
buildOptionsTemplate?.classOutDir ?: System.getProperty(PROJECT_CLASSES_OUTPUT_DIRECTORY_PROPERTY)
|
||||
}
|
||||
val options = BuildOptions(
|
||||
jarCacheDir = jarCacheDir,
|
||||
buildDateInSeconds = getBuildDateInSeconds(),
|
||||
@@ -370,10 +381,10 @@ internal suspend fun createBuildContext(
|
||||
validateImplicitPlatformModule = false,
|
||||
skipDependencySetup = true,
|
||||
|
||||
useCompiledClassesFromProjectOutput = buildOptionsTemplate?.useCompiledClassesFromProjectOutput ?: true,
|
||||
pathToCompiledClassesArchivesMetadata = buildOptionsTemplate?.pathToCompiledClassesArchivesMetadata,
|
||||
pathToCompiledClassesArchive = buildOptionsTemplate?.pathToCompiledClassesArchive,
|
||||
classOutDir = buildOptionsTemplate?.classOutDir ?: System.getProperty(PROJECT_CLASSES_OUTPUT_DIRECTORY_PROPERTY),
|
||||
useCompiledClassesFromProjectOutput = useCompiledClassesFromProjectOutput,
|
||||
pathToCompiledClassesArchivesMetadata = buildOptionsTemplate?.pathToCompiledClassesArchivesMetadata?.takeIf { !useCompiledClassesFromProjectOutput },
|
||||
pathToCompiledClassesArchive = buildOptionsTemplate?.pathToCompiledClassesArchive?.takeIf { !useCompiledClassesFromProjectOutput },
|
||||
classOutDir = classOutDir,
|
||||
|
||||
validateModuleStructure = false,
|
||||
cleanOutDir = false,
|
||||
|
||||
+9
-9
@@ -8,7 +8,7 @@ import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import org.jetbrains.intellij.build.BuiltinModulesFileData
|
||||
import org.jetbrains.intellij.build.ModuleDescriptor
|
||||
import org.jetbrains.intellij.build.ProductInfoLayoutItemKind
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
@@ -18,24 +18,24 @@ fun readBuiltinModulesFile(file: Path): BuiltinModulesFileData {
|
||||
|
||||
fun customizeBuiltinModulesAllowOnlySpecified(
|
||||
builtinModulesFile: Path,
|
||||
moduleNames: List<String>?,
|
||||
pluginAliases: Set<String>?,
|
||||
pluginNames: List<String>?,
|
||||
fileExtensions: List<String>?,
|
||||
) {
|
||||
Span.current().addEvent("File $builtinModulesFile before modification:\n" + Files.readString(builtinModulesFile))
|
||||
|
||||
val root = readBuiltinModulesFile(builtinModulesFile)
|
||||
if (moduleNames != null) {
|
||||
val existingValues = root.modules.associateByTo(HashMap(root.modules.size)) { it.name }
|
||||
val newList = ArrayList<ModuleDescriptor>(moduleNames.size)
|
||||
for (name in moduleNames) {
|
||||
if (pluginAliases != null) {
|
||||
val existingValues = root.layout.associateByTo(HashMap(root.layout.size)) { it.name }
|
||||
for (name in pluginAliases) {
|
||||
val item = existingValues.get(name)
|
||||
requireNotNull(item) {
|
||||
"Value '$name' in '$moduleNames' was not found across existing values in $builtinModulesFile:\n" + Files.readString(builtinModulesFile)
|
||||
"Value '$name' in '$pluginAliases' was not found across existing values in $builtinModulesFile:\n" + Files.readString(builtinModulesFile)
|
||||
}
|
||||
newList.add(item)
|
||||
}
|
||||
root.modules = newList
|
||||
root.layout = root.layout.filter {
|
||||
if (it.kind == ProductInfoLayoutItemKind.pluginAlias) pluginAliases.contains(it.name) else true
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginNames != null) {
|
||||
|
||||
@@ -16,10 +16,9 @@ import java.net.URL
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
|
||||
fun collectCompatiblePluginsToPublish(builtinModuleData: BuiltinModulesFileData, context: BuildContext, result: MutableSet<PluginLayout>) {
|
||||
val availableModulesAndPlugins = HashSet<String>(builtinModuleData.modules.size + builtinModuleData.plugins.size)
|
||||
availableModulesAndPlugins.addAll(builtinModuleData.plugins)
|
||||
builtinModuleData.modules.mapTo(availableModulesAndPlugins) { it.name }
|
||||
internal fun collectCompatiblePluginsToPublish(builtinModuleData: BuiltinModulesFileData, context: BuildContext, result: MutableSet<PluginLayout>) {
|
||||
val availableModulesAndPlugins = HashSet<String>(builtinModuleData.layout.size)
|
||||
builtinModuleData.layout.mapTo(availableModulesAndPlugins) { it.name }
|
||||
|
||||
val descriptorMap = collectPluginDescriptors(skipImplementationDetailPlugins = true,
|
||||
skipBundledPlugins = true,
|
||||
|
||||
+17
-8
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.intellij.build.impl.compilation
|
||||
|
||||
import com.intellij.openapi.util.io.NioFiles
|
||||
@@ -45,18 +45,27 @@ internal object CompiledClasses {
|
||||
messages.error("'${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVE}' is specified, " +
|
||||
"so 'incremental compilation' option cannot be enabled")
|
||||
}
|
||||
if (options.pathToCompiledClassesArchive != null && options.useCompiledClassesFromProjectOutput) {
|
||||
messages.error("'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, " +
|
||||
"so '${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVE}' cannot be used")
|
||||
|
||||
if (options.useCompiledClassesFromProjectOutput) {
|
||||
if (options.pathToCompiledClassesArchive != null) {
|
||||
messages.error(
|
||||
"'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, " +
|
||||
"so '${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVE}' cannot be used"
|
||||
)
|
||||
}
|
||||
if (options.pathToCompiledClassesArchivesMetadata != null) {
|
||||
messages.error(
|
||||
"'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, " +
|
||||
"so '${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVES_METADATA}' cannot be used to fetch compile output"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (options.pathToCompiledClassesArchivesMetadata != null && options.incrementalCompilation) {
|
||||
messages.error("'${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVES_METADATA}' is specified, " +
|
||||
"so 'incremental compilation' option cannot be used")
|
||||
}
|
||||
if (options.pathToCompiledClassesArchivesMetadata != null && options.useCompiledClassesFromProjectOutput) {
|
||||
messages.error("'${BuildOptions.USE_COMPILED_CLASSES_PROPERTY}' is specified, " +
|
||||
"so '${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVES_METADATA}' cannot be used to fetch compile output")
|
||||
}
|
||||
|
||||
if (options.pathToCompiledClassesArchive != null && options.pathToCompiledClassesArchivesMetadata != null) {
|
||||
messages.error("'${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVE}' is specified, " +
|
||||
"so '${BuildOptions.INTELLIJ_BUILD_COMPILER_CLASSES_ARCHIVES_METADATA}' cannot be used to fetch compile output")
|
||||
|
||||
+5
-11
@@ -7,6 +7,8 @@ import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jetbrains.intellij.build.BuildContext
|
||||
import org.jetbrains.intellij.build.BuiltinModulesFileData
|
||||
import org.jetbrains.intellij.build.ProductInfoLayoutItem
|
||||
import org.jetbrains.intellij.build.ProductInfoLayoutItemKind
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.attribute.FileTime
|
||||
@@ -55,10 +57,8 @@ internal fun generateProductInfoJson(
|
||||
bundledPlugins = builtinModules?.plugins ?: emptyList(),
|
||||
fileExtensions = builtinModules?.fileExtensions ?: emptyList(),
|
||||
|
||||
modules = (builtinModules?.modules?.asSequence() ?: emptySequence()).filter { it.isAlias }.map { it.name }.toList(),
|
||||
modulesV2 = (builtinModules?.modules?.asSequence() ?: emptySequence()).filter { !it.isAlias }.map {
|
||||
ProductInfoModuleV2(name = it.name, classPath = it.classPath)
|
||||
}.toList(),
|
||||
modules = (builtinModules?.layout?.asSequence() ?: emptySequence()).filter { it.kind == ProductInfoLayoutItemKind.pluginAlias }.map { it.name }.toList(),
|
||||
layout = builtinModules?.layout ?: emptyList(),
|
||||
|
||||
flavors = jbrFlavors + productFlavors,
|
||||
)
|
||||
@@ -90,17 +90,11 @@ data class ProductInfoData(
|
||||
val bundledPlugins: List<String>,
|
||||
// it is not modules, but plugin aliases
|
||||
val modules: List<String>,
|
||||
val modulesV2: List<ProductInfoModuleV2>,
|
||||
val layout: List<ProductInfoLayoutItem>,
|
||||
val fileExtensions: List<String>,
|
||||
val flavors: List<ProductFlavorData> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ProductInfoModuleV2(
|
||||
@JvmField val name: String,
|
||||
@JvmField val classPath: List<String> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ProductFlavorData(@JvmField val id: String)
|
||||
|
||||
|
||||
@@ -187,11 +187,11 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"modulesV2": {
|
||||
"layout": {
|
||||
"description": "IDs of product modules (non-removable bundled plugins)",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"flavors": {
|
||||
@@ -199,14 +199,27 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id"],
|
||||
"additionalProperties": false,
|
||||
"minItems": 0,
|
||||
"properties": {
|
||||
"id": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"classPath": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"kind"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.util.io.jackson.array
|
||||
import com.intellij.util.io.jackson.obj
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.io.OutputStreamWriter
|
||||
import java.io.Writer
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -41,18 +42,29 @@ private class BundledPluginsLister : ModernApplicationStarter() {
|
||||
}
|
||||
JsonFactory().createGenerator(out).use { writer ->
|
||||
val plugins = PluginManagerCore.getPluginSet().enabledPlugins
|
||||
val modules = HashSet<ModuleDescriptor>()
|
||||
val layout = HashSet<LayoutItemDescriptor>()
|
||||
val pluginIds = ArrayList<String>(plugins.size)
|
||||
val homeDir = Path.of(PathManager.getHomePath())
|
||||
for (plugin in plugins) {
|
||||
layout.add(LayoutItemDescriptor(
|
||||
name = plugin.pluginId.idString,
|
||||
kind = ProductInfoLayoutItemKind.plugin,
|
||||
classPath = plugin.jarFiles?.map { it.relativeTo(homeDir).invariantSeparatorsPathString } ?: emptyList()
|
||||
))
|
||||
|
||||
pluginIds.add(plugin.pluginId.idString)
|
||||
plugin.pluginAliases.mapTo(modules) {
|
||||
ModuleDescriptor(name = it.idString, isAlias = true, classPath = emptyList())
|
||||
plugin.pluginAliases.mapTo(layout) {
|
||||
LayoutItemDescriptor(name = it.idString, kind = ProductInfoLayoutItemKind.pluginAlias, classPath = emptyList())
|
||||
}
|
||||
plugin.content.modules.mapTo(modules) {
|
||||
ModuleDescriptor(
|
||||
plugin.content.modules.mapTo(layout) {
|
||||
LayoutItemDescriptor(
|
||||
name = it.name,
|
||||
isAlias = false,
|
||||
kind = if (plugin.pluginId == PluginManagerCore.CORE_ID) {
|
||||
ProductInfoLayoutItemKind.productModuleV2
|
||||
}
|
||||
else {
|
||||
ProductInfoLayoutItemKind.moduleV2
|
||||
},
|
||||
classPath = it.requireDescriptor().jarFiles?.map {
|
||||
file -> file.relativeTo(homeDir).invariantSeparatorsPathString
|
||||
} ?: emptyList(),
|
||||
@@ -72,13 +84,11 @@ private class BundledPluginsLister : ModernApplicationStarter() {
|
||||
extensions.sort()
|
||||
|
||||
writer.obj {
|
||||
writer.array("modules") {
|
||||
for (module in modules.sortedBy { it.name }) {
|
||||
writer.array("layout") {
|
||||
for (module in layout.sortedBy { it.name }) {
|
||||
writer.obj {
|
||||
writer.writeStringField("name", module.name)
|
||||
if (module.isAlias) {
|
||||
writer.writeBooleanField("isAlias", module.isAlias)
|
||||
}
|
||||
writer.writeStringField("kind", module.kind.name)
|
||||
if (module.classPath.isNotEmpty()) {
|
||||
writeList(writer, "classPath", module.classPath)
|
||||
}
|
||||
@@ -103,12 +113,18 @@ private class BundledPluginsLister : ModernApplicationStarter() {
|
||||
}
|
||||
}
|
||||
|
||||
private class ModuleDescriptor(
|
||||
private class LayoutItemDescriptor(
|
||||
@JvmField val name: String,
|
||||
@JvmField val isAlias: Boolean = false,
|
||||
@JvmField val kind: ProductInfoLayoutItemKind,
|
||||
@JvmField val classPath: List<String> = emptyList(),
|
||||
)
|
||||
|
||||
@Suppress("EnumEntryName")
|
||||
@Serializable
|
||||
private enum class ProductInfoLayoutItemKind {
|
||||
plugin, pluginAlias, productModuleV2, moduleV2
|
||||
}
|
||||
|
||||
private fun writeList(writer: JsonGenerator, name: String, elements: Collection<String>) {
|
||||
writer.array(name) {
|
||||
for (module in elements) {
|
||||
|
||||
Reference in New Issue
Block a user