From cd651be4610e70b96d28d41248f2990958569ad1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Thu, 16 May 2019 17:25:51 +0300 Subject: [PATCH] [JS IR BE] Migrate JS BE to common klib utils --- build.gradle.kts | 2 + .../common/arguments/K2JSCompilerArguments.kt | 5 + .../jetbrains/kotlin/cli/js/K2JsIrCompiler.kt | 109 +++----------- .../kotlin/ir/backend/js/compiler.kt | 8 +- .../ir/serialization.common/build.gradle.kts | 1 + .../serialization/IrModuleSerializer.kt | 1 + .../common/serialization/KlibWriter.kt | 11 -- compiler/ir/serialization.js/build.gradle.kts | 8 +- .../jetbrains/kotlin/ir/backend/js/klib.kt | 142 +++++++++--------- .../ir/JsDescriptorReferenceDeserializer.kt | 1 - .../js/lower/serialization/ir/JsIrLinker.kt | 20 +-- .../JsKlibMetadataSerializationUtil.kt | 95 ++---------- .../JsKlibMetadataSerializerProtocol.kt | 12 +- .../test/GenerateIrRuntime.kt | 17 +-- compiler/testData/cli/js/jsExtraHelp.out | 2 + .../library/impl/KotlinLibraryLayoutImpl.kt | 2 +- .../library/impl/KotlinLibraryWriterImpl.kt | 2 +- .../jetbrains/kotlin/utils/LibraryUtils.kt | 22 +++ .../kotlin/js/test/BasicIrBoxTest.kt | 27 ++-- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 4 +- 20 files changed, 180 insertions(+), 311 deletions(-) delete mode 100644 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KlibWriter.kt diff --git a/build.gradle.kts b/build.gradle.kts index 833766685a5..8190c36b0a2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -225,6 +225,8 @@ extra["compilerModules"] = arrayOf( ":compiler:backend.js", ":compiler:ir.serialization.common", ":compiler:ir.serialization.js", + ":kotlin-util-io", + ":kotlin-util-klib", ":compiler:backend-common", ":compiler:backend", ":compiler:plugin-api", diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt index fcab56fa876..18ae303d72b 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt @@ -114,6 +114,11 @@ class K2JSCompilerArguments : CommonCompilerArguments() { ) var irProduceOnly: String? by NullableStringFreezableVar(null) + @Argument( + value = "-Xir-legacy-gradle-plugin-compatibility", + description = "Make KLIB generation compatible with legacy gradle plugin" + ) + var irLegacyGradlePluginCompatimbility: Boolean by FreezableVar(false) @GradleOption(DefaultValues.BooleanTrueDefault::class) @Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays") diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index b960ab370d0..c38ceef0e51 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -28,14 +28,12 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer -import org.jetbrains.kotlin.ir.backend.js.KlibModuleRef -import org.jetbrains.kotlin.ir.backend.js.compile -import org.jetbrains.kotlin.ir.backend.js.generateKLib -import org.jetbrains.kotlin.ir.backend.js.jsPhases +import org.jetbrains.kotlin.ir.backend.js.* import org.jetbrains.kotlin.js.config.EcmaVersion import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding +import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.serialization.js.ModuleKind @@ -44,7 +42,6 @@ import org.jetbrains.kotlin.utils.KotlinPaths import org.jetbrains.kotlin.utils.join import java.io.File import java.io.IOException -import java.util.zip.ZipFile enum class ProduceKind { DEFAULT, // Determine what to produce based on js-v1 options @@ -61,68 +58,6 @@ class K2JsIrCompiler : CLICompiler() { return K2JSCompilerArguments() } - private fun extractKlibFromZip(library: String, messageCollector: MessageCollector): File? { - val zipLib = ZipFile(library) - val tempDir = createTempDir(File(library).name, "klibjar") - tempDir.deleteOnExit() - var extractedKlibDir: File? = null - for (entry in zipLib.entries()) { - if (!entry.isDirectory) { - zipLib.getInputStream(entry).use { input -> - val outputEntryFile = File(tempDir, entry.name) - outputEntryFile.parentFile.mkdirs() - outputEntryFile.outputStream().use { output -> - input.copyTo(output) - } - } - } else { - if (entry.name.endsWith("KLIB/")) { - extractedKlibDir = File(tempDir, entry.name) - messageCollector.report(INFO, "Klib $library is extracted into $extractedKlibDir") - } - } - } - - return extractedKlibDir - } - - private fun loadIrLibrary(library: String, messageCollector: MessageCollector): KlibModuleRef? { - val libraryFile = File(library) - var klibDir = when { - FileUtil.isJarOrZip(libraryFile) -> { - extractKlibFromZip(library, messageCollector) ?: return null - } - !libraryFile.isDirectory -> { - messageCollector.report(ERROR, "Klib $library must be a directory") - return null - } - else -> - libraryFile - } - - var klibFiles = klibDir.listFiles() - if (klibFiles.isEmpty()) { - messageCollector.report(STRONG_WARNING, "Klib $library directory is empty") - return null - } - - // Sometines gradle gives us a directory with klib directory inside - val klibDirInsideDir = klibFiles.find { it.name.endsWith("KLIB") } - if (klibDirInsideDir != null) { - klibDir = klibDirInsideDir - klibFiles = klibDir.listFiles() - } - - val metadataFile = klibFiles.find { it.extension == "klm" } - - if (metadataFile == null) { - messageCollector.report(STRONG_WARNING, "No metadata file (.klm) for klib: $klibDir") - return null - } - - return KlibModuleRef(metadataFile.nameWithoutExtension, klibDir.absolutePath) - } - override fun doExecute( arguments: K2JSCompilerArguments, configuration: CompilerConfiguration, @@ -144,7 +79,7 @@ class K2JsIrCompiler : CLICompiler() { arguments.pluginOptions, configuration ) - if (pluginLoadResult != ExitCode.OK) return pluginLoadResult + if (pluginLoadResult != OK) return pluginLoadResult val libraries: List = configureLibraries(arguments.libraries) val friendLibraries: List = configureLibraries(arguments.friendModules) @@ -204,11 +139,11 @@ class K2JsIrCompiler : CLICompiler() { val mainCallArguments = if (K2JsArgumentConstants.NO_CALL == arguments.main) null else emptyList() val loadedLibrariesNames = mutableSetOf() - val dependencies = mutableListOf() - val friendDependencies = mutableListOf() + val dependencies = mutableListOf() + val friendDependencies = mutableListOf() for (library in libraries) { - val irLib = loadIrLibrary(library, messageCollector) ?: continue + val irLib = loadKlib(library) if (irLib.moduleName !in loadedLibrariesNames) { dependencies.add(irLib) loadedLibrariesNames.add(irLib.moduleName) @@ -223,6 +158,24 @@ class K2JsIrCompiler : CLICompiler() { messageCollector.report(ERROR, "Unknown produce kind: ${arguments.irProduceOnly}. Valid values are: js, klib") } + if (produceKind == ProduceKind.KLIB || (produceKind == ProduceKind.DEFAULT && arguments.metaInfo)) { + val outputKlibPath = + if (arguments.irLegacyGradlePluginCompatimbility) + File(outputFilePath).parent + else + "$outputFilePath.klib" + + generateKLib( + project = config.project, + files = sourcesFiles, + configuration = config.configuration, + allDependencies = dependencies, + friendDependencies = friendDependencies, + outputKlibPath = outputKlibPath, + nopack = arguments.irLegacyGradlePluginCompatimbility + ) + } + if (produceKind == ProduceKind.JS || produceKind == ProduceKind.DEFAULT) { val phaseConfig = createPhaseConfig(jsPhases, arguments, messageCollector) @@ -231,7 +184,6 @@ class K2JsIrCompiler : CLICompiler() { sourcesFiles, configuration, phaseConfig, - immediateDependencies = dependencies, allDependencies = dependencies, friendDependencies = friendDependencies, mainArguments = mainCallArguments @@ -240,19 +192,6 @@ class K2JsIrCompiler : CLICompiler() { outputFile.writeText(compiledModule) } - if (produceKind == ProduceKind.KLIB || (produceKind == ProduceKind.DEFAULT && arguments.metaInfo)) { - val outputKlibPath = "$outputFilePath.KLIB" - generateKLib( - project = config.project, - files = sourcesFiles, - configuration = config.configuration, - immediateDependencies = dependencies, - allDependencies = dependencies, - friendDependencies = friendDependencies, - outputKlibPath = outputKlibPath - ) - } - return OK } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index 36e91a1017e..7e74fd10b4f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransf import org.jetbrains.kotlin.ir.backend.js.utils.JsMainFunctionDetector import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.patchDeclarationParents +import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.psi.KtFile fun compile( @@ -20,13 +21,12 @@ fun compile( files: List, configuration: CompilerConfiguration, phaseConfig: PhaseConfig, - immediateDependencies: List, - allDependencies: List, - friendDependencies: List, + allDependencies: List, + friendDependencies: List, mainArguments: List? ): String { val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) = - loadIr(project, files, configuration, immediateDependencies, allDependencies, friendDependencies) + loadIr(project, files, configuration, allDependencies, friendDependencies) val moduleDescriptor = moduleFragment.descriptor diff --git a/compiler/ir/serialization.common/build.gradle.kts b/compiler/ir/serialization.common/build.gradle.kts index 64888ef16b5..81646f3c533 100644 --- a/compiler/ir/serialization.common/build.gradle.kts +++ b/compiler/ir/serialization.common/build.gradle.kts @@ -7,6 +7,7 @@ dependencies { // TODO: decouple from backend.common compile(project(":compiler:ir.backend.common")) compile(project(":compiler:ir.tree")) + compile(project(":kotlin-util-klib")) } sourceSets { diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt index 1484a0eac09..3441f31d5f8 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleSerializer.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.library.CombinedIrFileWriter import org.jetbrains.kotlin.backend.common.library.DeclarationId +import org.jetbrains.kotlin.library.SerializedIr import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind.* import org.jetbrains.kotlin.descriptors.Modality diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KlibWriter.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KlibWriter.kt deleted file mode 100644 index ca0854d0177..00000000000 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KlibWriter.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.backend.common.serialization - -class SerializedIr ( - val module: ByteArray, - val combinedDeclarationFilePath: String -) diff --git a/compiler/ir/serialization.js/build.gradle.kts b/compiler/ir/serialization.js/build.gradle.kts index 33d0ac87916..ebd8b883828 100644 --- a/compiler/ir/serialization.js/build.gradle.kts +++ b/compiler/ir/serialization.js/build.gradle.kts @@ -159,7 +159,7 @@ val generateFullRuntimeKLib by task { buildKLib(sources = listOf(fullRuntimeSources.outputs.files.singleFile.path), dependencies = emptyList(), - outPath = "$buildDir/fullRuntime/klib/JS_IR_RUNTIME.klm", + outPath = "$buildDir/fullRuntime/klib", commonSources = listOf("common", "src", "unsigned").map { "$buildDir/fullRuntime/src/libraries/stdlib/$it" } ) } @@ -169,7 +169,7 @@ val generateReducedRuntimeKLib by task { buildKLib(sources = listOf(reducedRuntimeSources.outputs.files.singleFile.path), dependencies = emptyList(), - outPath = "$buildDir/reducedRuntime/klib/JS_IR_RUNTIME.klm", + outPath = "$buildDir/reducedRuntime/klib", commonSources = listOf("common", "src", "unsigned").map { "$buildDir/reducedRuntime/src/libraries/stdlib/$it" } ) } @@ -183,8 +183,8 @@ val generateKotlinTestKLib by task { buildKLib( sources = listOf("$rootDir/libraries/kotlin.test/js/src/main") + kotlinTestCommonSources, - dependencies = listOf("${generateFullRuntimeKLib.outputs.files.singleFile.path}/JS_IR_RUNTIME.klm"), - outPath = "$buildDir/kotlin.test/klib/kotlin.test.klm", + dependencies = listOf("${generateFullRuntimeKLib.outputs.files.singleFile.path}/klib"), + outPath = "$buildDir/kotlin.test/klib", commonSources = kotlinTestCommonSources ) } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index d83c0c44723..3dae9b95f48 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -7,25 +7,22 @@ package org.jetbrains.kotlin.ir.backend.js import com.intellij.openapi.project.Project import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable +import org.jetbrains.kotlin.library.impl.buildKoltinLibrary import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable -import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsDeclarationTable import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.newJsDescriptorUniqId -import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataModuleDescriptor -import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataSerializationUtil -import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataVersion -import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.createJsKlibMetadataPackageFragmentProvider import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.* import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns @@ -34,6 +31,11 @@ import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult +import org.jetbrains.kotlin.konan.KonanVersionImpl +import org.jetbrains.kotlin.konan.MetaVersion +import org.jetbrains.kotlin.konan.properties.propertyList +import org.jetbrains.kotlin.library.* +import org.jetbrains.kotlin.library.impl.createKotlinLibrary import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.psi.KtFile @@ -44,28 +46,30 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.utils.DFS -import java.io.File -import java.nio.file.Files.move -import java.nio.file.Paths -import java.nio.file.StandardCopyOption +import org.jetbrains.kotlin.konan.file.File as KFile -data class KlibModuleRef( - val moduleName: String, - val klibPath: String -) -internal val JS_KLIBRARY_CAPABILITY = ModuleDescriptor.Capability("JS KLIBRARY") -internal val moduleHeaderFileName = "module.kji" -internal val declarationsDirName = "ir/" +val KotlinLibrary.moduleName: String + get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME) + +// Considering library built-ins if it has no dependencies. +// All non-built-ins libraries must have built-ins as a dependency. +val KotlinLibrary.isBuiltIns: Boolean + get() = manifestProperties + .propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true) + .isEmpty() + +fun loadKlib(klibPath: String) = + createKotlinLibrary(KFile(KFile(klibPath).absolutePath)) + +internal val JS_KLIBRARY_CAPABILITY = ModuleDescriptor.Capability("JS KLIBRARY") + private val emptyLoggingContext = object : LoggingContext { override var inVerbosePhase = false override fun log(message: () -> String) {} } -private fun metadataFileName(moduleName: String) = "$moduleName.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}" - private val CompilerConfiguration.metadataVersion get() = get(CommonConfigurationKeys.METADATA_VERSION) as? JsKlibMetadataVersion ?: JsKlibMetadataVersion.INSTANCE @@ -73,12 +77,12 @@ fun generateKLib( project: Project, files: List, configuration: CompilerConfiguration, - immediateDependencies: List, - allDependencies: List, - friendDependencies: List, - outputKlibPath: String -): KlibModuleRef { - val depsDescriptors = ModulesStructure(project, files, configuration, immediateDependencies, allDependencies, friendDependencies) + allDependencies: List, + friendDependencies: List, + outputKlibPath: String, + nopack: Boolean +) { + val depsDescriptors = ModulesStructure(project, files, configuration, allDependencies, friendDependencies) val psi2IrContext = runAnalysisAndPreparePsi2Ir(depsDescriptors) @@ -94,11 +98,10 @@ fun generateKLib( configuration.languageVersionSettings, psi2IrContext.bindingContext, outputKlibPath, - immediateDependencies, - moduleFragment + allDependencies, + moduleFragment, + nopack ) - - return KlibModuleRef(moduleName, outputKlibPath) } data class IrModuleInfo( @@ -113,11 +116,10 @@ fun loadIr( project: Project, files: List, configuration: CompilerConfiguration, - immediateDependencies: List, - allDependencies: List, - friendDependencies: List + allDependencies: List, + friendDependencies: List ): IrModuleInfo { - val depsDescriptors = ModulesStructure(project, files, configuration, immediateDependencies, allDependencies, friendDependencies) + val depsDescriptors = ModulesStructure(project, files, configuration, allDependencies, friendDependencies) val psi2IrContext = runAnalysisAndPreparePsi2Ir(depsDescriptors) @@ -127,7 +129,7 @@ fun loadIr( val deserializer = JsIrLinker(moduleDescriptor, emptyLoggingContext, irBuiltIns, symbolTable) - val deserializedModuleFragments = depsDescriptors.sortedImmediateDependencies.map { + val deserializedModuleFragments = allDependencies.map { deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!! } @@ -154,16 +156,16 @@ private fun GeneratorContext.generateModuleFragment(files: List, deseria private fun loadKlibMetadataParts( - moduleId: KlibModuleRef + moduleId: KotlinLibrary ): JsKlibMetadataParts { - val metadataFile = File(moduleId.klibPath, metadataFileName(moduleId.moduleName)) - val serializer = JsKlibMetadataSerializationUtil - return serializer.readModuleAsProto(metadataFile.readBytes()) + return JsKlibMetadataSerializationUtil.readModuleAsProto(moduleId.moduleHeaderData) } +val ModuleDescriptor.kotlinLibrary get() = this.getCapability(JS_KLIBRARY_CAPABILITY)!! + private fun loadKlibMetadata( parts: JsKlibMetadataParts, - moduleId: KlibModuleRef, + moduleId: KotlinLibrary, isBuiltIn: Boolean, lookupTracker: LookupTracker, storageManager: LockBasedStorageManager, @@ -178,7 +180,7 @@ private fun loadKlibMetadata( Name.special("<${moduleId.moduleName}>"), storageManager, builtIns, - capabilities = mapOf(JS_KLIBRARY_CAPABILITY to File(moduleId.klibPath)) + capabilities = mapOf(JS_KLIBRARY_CAPABILITY to moduleId) ) if (isBuiltIn) builtIns.builtInsModule = md val currentModuleFragmentProvider = createJsKlibMetadataPackageFragmentProvider( @@ -203,26 +205,21 @@ private class ModulesStructure( private val project: Project, private val files: List, val compilerConfiguration: CompilerConfiguration, - immediateDependencies: List, - private val allDependencies: List, - private val friendDependencies: List + private val allDependencies: List, + private val friendDependencies: List ) { - private val deserializedModuleParts: Map = + private val deserializedModuleParts: Map = allDependencies.associateWith { loadKlibMetadataParts(it) } - fun findModuleByName(name: String): KlibModuleRef = + fun findModuleByName(name: String): KotlinLibrary = allDependencies.find { it.moduleName == name } ?: error("Module is not found: $name") - val moduleDependencies: Map> = + val moduleDependencies: Map> = deserializedModuleParts.mapValues { (_, parts) -> parts.importedModules.map(::findModuleByName) } - val sortedImmediateDependencies: List = - DFS.topologicalOrder(immediateDependencies) { moduleDependencies.getValue(it) } - .reversed() - - val builtInsDep = sortedImmediateDependencies.firstOrNull() + val builtInsDep = allDependencies.find { it.isBuiltIns } fun runAnalysis(): JsAnalysisResult { val analysisResult = @@ -230,7 +227,7 @@ private class ModulesStructure( files, project, compilerConfiguration, - sortedImmediateDependencies.map { getModuleDescriptor(it) }, + allDependencies.map { getModuleDescriptor(it) }, friendModuleDescriptors = friendDependencies.map { getModuleDescriptor(it) }, thisIsBuiltInsModule = builtInModuleDescriptor == null, customBuiltInsModule = builtInModuleDescriptor @@ -249,9 +246,9 @@ private class ModulesStructure( private val storageManager: LockBasedStorageManager = LockBasedStorageManager("ModulesStructure") private var runtimeModule: ModuleDescriptorImpl? = null - private val descriptors = mutableMapOf() + private val descriptors = mutableMapOf() - fun getModuleDescriptor(current: KlibModuleRef): ModuleDescriptorImpl = descriptors.getOrPut(current) { + fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) { val parts = loadKlibMetadataParts(current) val isBuiltIns = parts.importedModules.isEmpty() loadKlibMetadata( @@ -282,8 +279,9 @@ fun serializeModuleIntoKlib( languageVersionSettings: LanguageVersionSettings, bindingContext: BindingContext, klibPath: String, - dependencies: List, - moduleFragment: IrModuleFragment + dependencies: List, + moduleFragment: IrModuleFragment, + nopack: Boolean ) { val declarationTable = JsDeclarationTable(moduleFragment.irBuiltins, DescriptorTable()) @@ -292,7 +290,7 @@ fun serializeModuleIntoKlib( val moduleDescription = JsKlibMetadataModuleDescriptor(moduleName, dependencies.map { it.moduleName }, moduleFragment.descriptor) - val serializedData = serializer.serializeMetadata( + val serializedMetadata = serializer.serializeMetadata( bindingContext, moduleDescription, languageVersionSettings, @@ -302,19 +300,21 @@ fun serializeModuleIntoKlib( index?.let { newJsDescriptorUniqId(it) } } - val klibDir = File(klibPath).also { - it.deleteRecursively() - it.mkdirs() - } + val abiVersion = KotlinAbiVersion.CURRENT + val compilerVersion = KonanVersionImpl(MetaVersion.DEV, 1, 3, 0, -1) + val libraryVersion = "JSIR" - val moduleFile = File(klibDir, moduleHeaderFileName) - moduleFile.writeBytes(serializedIr.module) + val versions = KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion) - val irDeclarationDir = File(klibDir, declarationsDirName).also { it.mkdir() } - val irCombinedFile = File(irDeclarationDir, "irCombined.knd") - move(Paths.get(serializedIr.combinedDeclarationFilePath), Paths.get(irCombinedFile.path), StandardCopyOption.REPLACE_EXISTING) - - File(klibDir, "${moduleDescription.name}.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}").also { - it.writeBytes(serializedData.asByteArray()) - } + buildKoltinLibrary( + linkDependencies = dependencies, + ir = serializedIr, + metadata = serializedMetadata, + dataFlowGraph = null, + manifestProperties = null, + moduleName = moduleName, + nopack = nopack, + output = klibPath, + versions = versions + ) } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsDescriptorReferenceDeserializer.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsDescriptorReferenceDeserializer.kt index 6782692a387..5c56b077070 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsDescriptorReferenceDeserializer.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsDescriptorReferenceDeserializer.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir import org.jetbrains.kotlin.backend.common.serialization.DescriptorReferenceDeserializer import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware -import org.jetbrains.kotlin.backend.common.serialization.UniqId import org.jetbrains.kotlin.backend.common.serialization.UniqIdKey import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt index 98a4db831bf..173e6c341fa 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt @@ -6,29 +6,23 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir import org.jetbrains.kotlin.backend.common.LoggingContext -import org.jetbrains.kotlin.backend.common.library.CombinedIrFileReader -import org.jetbrains.kotlin.backend.common.library.DeclarationId import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.ir.backend.js.JS_KLIBRARY_CAPABILITY -import org.jetbrains.kotlin.ir.backend.js.moduleHeaderFileName +import org.jetbrains.kotlin.ir.backend.js.kotlinLibrary import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.util.SymbolTable -import java.io.File class JsIrLinker( currentModule: ModuleDescriptor, logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable -) : KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null, 0x1_0000_0000L), +) : KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null, 0x1_0000_0000L), DescriptorUniqIdAware by JsDescriptorUniqIdAware { private val FUNCTION_INDEX_START: Long = indexAfterKnownBuiltins - val moduleToReaderMap = mutableMapOf() - override fun getPrimitiveTypeOrNull(symbol: IrClassifierSymbol, hasQuestionMark: Boolean) = builtIns.getPrimitiveTypeOrNullByDescriptor(symbol.descriptor, hasQuestionMark) @@ -36,15 +30,11 @@ class JsIrLinker( JsDescriptorReferenceDeserializer(currentModule, builtIns, FUNCTION_INDEX_START) override fun reader(moduleDescriptor: ModuleDescriptor, uniqId: UniqId): ByteArray { - val irFileReader = moduleToReaderMap.getOrPut(moduleDescriptor) { - val irFile = File(moduleDescriptor.getCapability(JS_KLIBRARY_CAPABILITY)!!, "ir/irCombined.knd") - CombinedIrFileReader(irFile) - } - return irFileReader.declarationBytes(DeclarationId(uniqId.index, uniqId.isLocal)) + return moduleDescriptor.kotlinLibrary.irDeclaration(uniqId.index, uniqId.isLocal) } - override val ModuleDescriptor.irHeader: ByteArray? get() = - this.getCapability(JS_KLIBRARY_CAPABILITY)?.let { File(it, moduleHeaderFileName).readBytes() } + override val ModuleDescriptor.irHeader: ByteArray? + get() = this.kotlinLibrary.irHeader override fun declareForwardDeclarations() { // since for `knownBuiltIns` such as FunctionN it is possible to have unbound symbols after deserialization diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializationUtil.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializationUtil.kt index cb28b372245..de66ebf4b97 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializationUtil.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializationUtil.kt @@ -5,10 +5,9 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata -import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.name.FqName @@ -21,27 +20,25 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.AnnotationSerializer import org.jetbrains.kotlin.serialization.DescriptorSerializer -import org.jetbrains.kotlin.serialization.StringTableImpl import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream -import java.util.zip.GZIPInputStream -import java.util.zip.GZIPOutputStream object JsKlibMetadataSerializationUtil { - const val CLASS_METADATA_FILE_EXTENSION: String = "klm" - fun serializeMetadata( bindingContext: BindingContext, jsDescriptor: JsKlibMetadataModuleDescriptor, languageVersionSettings: LanguageVersionSettings, metadataVersion: JsKlibMetadataVersion, - declarationTableHandler: ((DeclarationDescriptor) -> JsKlibMetadataProtoBuf.DescriptorUniqId?) + declarationTableHandler: (DeclarationDescriptor) -> JsKlibMetadataProtoBuf.DescriptorUniqId? ): SerializedMetadata { + val libraryProto = JsKlibMetadataProtoBuf.Library.newBuilder() + jsDescriptor.imported.forEach { libraryProto.addImportedModule(it) } + val serializedFragments = HashMap() val module = jsDescriptor.data + val fragments = mutableListOf>() + val fragmentNames = mutableListOf() for (fqName in getPackagesFqNames(module).sortedBy { it.asString() }) { val fragment = serializeDescriptors( @@ -55,39 +52,14 @@ object JsKlibMetadataSerializationUtil { } } - return SerializedMetadata(serializedFragments, jsDescriptor, languageVersionSettings) - } - - class SerializedMetadata( - private val serializedFragments: Map, - private val jsDescriptor: JsKlibMetadataModuleDescriptor, - private val languageVersionSettings: LanguageVersionSettings - ) { - - fun asByteArray(): ByteArray = - ByteArrayOutputStream().apply { - GZIPOutputStream(this).use { stream -> - serializeHeader( - jsDescriptor.data, - packageFqName = null, - languageVersionSettings = languageVersionSettings - ).writeDelimitedTo(stream) - asLibrary().writeTo(stream) - } - }.toByteArray() - - private fun asLibrary(): JsKlibMetadataProtoBuf.Library { - jsDescriptor.imported - val builder = JsKlibMetadataProtoBuf.Library.newBuilder() - - jsDescriptor.imported.forEach { builder.addImportedModule(it) } - - for ((_, fragment) in serializedFragments.entries.sortedBy { (fqName, _) -> fqName.asString() }) { - builder.addPackageFragment(fragment) - } - - return builder.build() + for ((fqName, fragment) in serializedFragments.entries.sortedBy { (fqName, _) -> fqName.asString() }) { + libraryProto.addPackageFragment(fragment) + fragments.add(listOf(fragment.toByteArray())) + fragmentNames.add(fqName.asString()) } + + val libraryAsByteArray = libraryProto.build().toByteArray() + return SerializedMetadata(libraryAsByteArray, fragments, fragmentNames) } fun serializeDescriptors( @@ -174,38 +146,6 @@ object JsKlibMetadataSerializationUtil { private fun ProtoBuf.PackageFragment.isEmpty(): Boolean = class_Count == 0 && `package`.let { it.functionCount == 0 && it.propertyCount == 0 && it.typeAliasCount == 0 } - fun serializeHeader( - module: ModuleDescriptor, packageFqName: FqName?, languageVersionSettings: LanguageVersionSettings - ): JsKlibMetadataProtoBuf.Header { - val header = JsKlibMetadataProtoBuf.Header.newBuilder() - - if (packageFqName != null) { - header.packageFqName = packageFqName.asString() - } - - if (languageVersionSettings.isPreRelease()) { - header.flags = 1 - } - - val experimentalAnnotationFqNames = languageVersionSettings.getFlag(AnalysisFlags.experimental) - if (experimentalAnnotationFqNames.isNotEmpty()) { - val stringTable = StringTableImpl() - for (fqName in experimentalAnnotationFqNames) { - val descriptor = module.resolveClassByFqName(FqName(fqName), NoLookupLocation.FOR_ALREADY_TRACKED) ?: continue - header.addAnnotation(ProtoBuf.Annotation.newBuilder().apply { - id = stringTable.getFqNameIndex(descriptor) - }) - } - val (strings, qualifiedNames) = stringTable.buildProto() - header.strings = strings - header.qualifiedNames = qualifiedNames - } - - // TODO: write JS code binary version - - return header.build() - } - private fun getPackagesFqNames(module: ModuleDescriptor): Set { return mutableSetOf().apply { getSubPackagesFqNames(module.getPackage(FqName.ROOT), this) @@ -228,11 +168,8 @@ object JsKlibMetadataSerializationUtil { @JvmStatic fun readModuleAsProto(metadata: ByteArray): JsKlibMetadataParts { - val (header, content) = GZIPInputStream(ByteArrayInputStream(metadata)).use { stream -> - JsKlibMetadataProtoBuf.Header.parseDelimitedFrom(stream, JsKlibMetadataSerializerProtocol.extensionRegistry) to - JsKlibMetadataProtoBuf.Library.parseFrom(stream, JsKlibMetadataSerializerProtocol.extensionRegistry) - } - + val header = JsKlibMetadataProtoBuf.Header.parseFrom(metadata, JsKlibMetadataSerializerProtocol.extensionRegistry) + val content = JsKlibMetadataProtoBuf.Library.parseFrom(metadata, JsKlibMetadataSerializerProtocol.extensionRegistry) return JsKlibMetadataParts(header, content.packageFragmentList, content.importedModuleList) } } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializerProtocol.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializerProtocol.kt index ad9f1ae3a3e..345540e74a6 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializerProtocol.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/JsKlibMetadataSerializerProtocol.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol @@ -24,12 +22,4 @@ object JsKlibMetadataSerializerProtocol : SerializerExtensionProtocol( JsKlibMetadataProtoBuf.parameterAnnotation, JsKlibMetadataProtoBuf.typeAnnotation, JsKlibMetadataProtoBuf.typeParameterAnnotation -) { - fun getKjsmFilePath(packageFqName: FqName): String { - val shortName = if (packageFqName.isRoot) Name.identifier("root-package") else packageFqName.shortName() - - return packageFqName.child(shortName).asString().replace('.', '/') + - "." + - JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION - } -} +) diff --git a/compiler/ir/serialization.js/test/GenerateIrRuntime.kt b/compiler/ir/serialization.js/test/GenerateIrRuntime.kt index c8d1fd48202..53eb68bdb5d 100644 --- a/compiler/ir/serialization.js/test/GenerateIrRuntime.kt +++ b/compiler/ir/serialization.js/test/GenerateIrRuntime.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource import org.jetbrains.kotlin.serialization.js.ModuleKind @@ -58,10 +59,10 @@ fun buildKLib( moduleName: String, sources: List, outputPath: String, - dependencies: List, + dependencies: List, commonSources: List -): KlibModuleRef { - return generateKLib( +) { + generateKLib( project = environment.project, files = sources.map { source -> val file = createPsiFile(source) @@ -71,10 +72,10 @@ fun buildKLib( file }, configuration = buildConfiguration(environment, moduleName), - immediateDependencies = dependencies, allDependencies = dependencies, friendDependencies = emptyList(), - outputKlibPath = outputPath + outputKlibPath = outputPath, + nopack = true ) } @@ -114,12 +115,10 @@ fun main(args: Array) { val name = outputPath.takeLastWhile { it != '/' } - if (!name.endsWith(".klm")) error("invalid output file name") - val dependencyKLibs = dependencies.map { val file = File(it) - KlibModuleRef(file.name.dropLast(4), file.parent) + loadKlib(file.path) } - buildKLib(name.dropLast(4), listOfKtFilesFrom(inputFiles), File(outputPath).parent, dependencyKLibs, listOfKtFilesFrom(commonSources)) + buildKLib(name.dropLast(4), listOfKtFilesFrom(inputFiles), outputPath, dependencyKLibs, listOfKtFilesFrom(commonSources)) } diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 4fc32bc1bbe..5b23723341d 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -3,6 +3,8 @@ where advanced options include: -Xfriend-modules= Paths to friend modules -Xfriend-modules-disabled Disable internal declaration export -Xir Use IR backend + -Xir-legacy-gradle-plugin-compatibility + Make KLIB generation compatible with legacy gradle plugin -Xir-produce-only={ klib, js } Type of output to produce. Overrides -meta-info argument. -Xtyped-arrays Translate primitive arrays to JS typed arrays -Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryLayoutImpl.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryLayoutImpl.kt index 10236ef1573..7c7b35e6545 100644 --- a/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryLayoutImpl.kt +++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryLayoutImpl.kt @@ -139,7 +139,7 @@ internal fun zippedKotlinLibraryChecks(klibFile: File) { check(klibFile.isFile) { "Expected $klibFile to be a regular file." } val extension = klibFile.extension - check(extension.isEmpty() || extension == KLIB_FILE_EXTENSION) { + check(extension.isEmpty() || extension == KLIB_FILE_EXTENSION || extension == "jar") { "KLIB path has unexpected extension: $klibFile" } } \ No newline at end of file diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryWriterImpl.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryWriterImpl.kt index 88c6f505f01..2c5453559d6 100644 --- a/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryWriterImpl.kt +++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/impl/KotlinLibraryWriterImpl.kt @@ -85,7 +85,7 @@ class KoltinLibraryWriterImpl( ) : BaseWriter by base, MetadataWriter by metadata, IrWriter by ir, KotlinLibraryWriter -internal fun buildKoltinLibrary( +fun buildKoltinLibrary( linkDependencies: List, metadata: SerializedMetadata, ir: SerializedIr, diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt b/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt index e45d61495c8..1b4b183bcd6 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt @@ -17,12 +17,14 @@ package org.jetbrains.kotlin.utils import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.VirtualFile import java.io.* import java.util.* import java.util.jar.Attributes import java.util.jar.JarFile import java.util.jar.Manifest +import java.util.zip.ZipFile object LibraryUtils { private val LOG = Logger.getInstance(LibraryUtils::class.java) @@ -65,6 +67,26 @@ object LibraryUtils { return checkAttributeValue(library, TITLE_KOTLIN_JAVASCRIPT_STDLIB, Attributes.Name.IMPLEMENTATION_TITLE) } + private fun isZippedKlib(candidate: File): Boolean { + if (candidate.extension == "klib") return true + var manifestFound = false + var irFound = false + for (entry in ZipFile(candidate).entries()) { + if (entry.name == "manifest") manifestFound = true + if (entry.name == "ir/") irFound = true + } + return manifestFound && irFound + } + + fun isKotlinJavascriptIrLibrary(candidate: File): Boolean { + return when { + FileUtil.isJarOrZip(candidate) -> isZippedKlib(candidate) + !File(candidate, "manifest").isFile -> false + !File(candidate, "ir").isDirectory -> false + else -> true + } + } + private fun getManifestFromJar(library: File): Manifest? { if (!library.canRead()) return null diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index a8f884af327..99602444c0f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.js.test import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap -import org.jetbrains.kotlin.ir.backend.js.KlibModuleRef +import org.jetbrains.kotlin.ir.backend.js.loadKlib import org.jetbrains.kotlin.ir.backend.js.compile import org.jetbrains.kotlin.ir.backend.js.generateKLib import org.jetbrains.kotlin.ir.backend.js.jsPhases @@ -18,9 +18,9 @@ import org.jetbrains.kotlin.js.facade.TranslationUnit import org.jetbrains.kotlin.test.TargetBackend import java.io.File -private val fullRuntimeKlib = KlibModuleRef("JS_IR_RUNTIME", "compiler/ir/serialization.js/build/fullRuntime/klib") -private val defaultRuntimeKlib = KlibModuleRef("JS_IR_RUNTIME", "compiler/ir/serialization.js/build/reducedRuntime/klib") -private val kotlinTestKLib = KlibModuleRef("kotlin.test", "compiler/ir/serialization.js/build/kotlin.test/klib") +private val fullRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/fullRuntime/klib") +private val defaultRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/reducedRuntime/klib") +private val kotlinTestKLib = loadKlib("compiler/ir/serialization.js/build/kotlin.test/klib") abstract class BasicIrBoxTest( pathToTestDir: String, @@ -43,7 +43,7 @@ abstract class BasicIrBoxTest( // TODO Design incremental compilation for IR and add test support override val incrementalCompilationChecksEnabled = false - private val compilationCache = mutableMapOf() + private val compilationCache = mutableMapOf() override fun doTest(filePath: String, expectedResult: String, mainCallParameters: MainCallParameters, coroutinesPackage: String) { compilationCache.clear() @@ -73,16 +73,10 @@ abstract class BasicIrBoxTest( val runtimeKlibs = if (needsFullIrRuntime) listOf(fullRuntimeKlib, kotlinTestKLib) else listOf(defaultRuntimeKlib) - val libraries = config.configuration[JSConfigurationKeys.LIBRARIES]!!.map { File(it).name } val transitiveLibraries = config.configuration[JSConfigurationKeys.TRANSITIVE_LIBRARIES]!!.map { File(it).name } - // TODO: Add proper depencencies - val dependencies = runtimeKlibs + libraries.map { - compilationCache[it] ?: error("Can't find compiled module for dependency $it") - } - val allDependencies = runtimeKlibs + transitiveLibraries.map { - compilationCache[it] ?: error("Can't find compiled module for dependency $it") + loadKlib(compilationCache[it] ?: error("Can't find compiled module for dependency $it")) } val actualOutputFile = outputFile.absolutePath.let { @@ -112,7 +106,6 @@ abstract class BasicIrBoxTest( files = filesToCompile, configuration = config.configuration, phaseConfig = phaseConfig, - immediateDependencies = dependencies, allDependencies = allDependencies, friendDependencies = emptyList(), mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null } @@ -122,17 +115,17 @@ abstract class BasicIrBoxTest( outputFile.write(wrappedCode) } else { - val module = generateKLib( + generateKLib( project = config.project, files = filesToCompile, configuration = config.configuration, - immediateDependencies = dependencies, allDependencies = allDependencies, friendDependencies = emptyList(), - outputKlibPath = actualOutputFile + outputKlibPath = actualOutputFile, + nopack = true ) - compilationCache[outputFile.name.replace(".js", ".meta.js")] = module + compilationCache[outputFile.name.replace(".js", ".meta.js")] = actualOutputFile } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 396e028724d..e8736009168 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -563,8 +563,7 @@ open class Kotlin2JsCompile : AbstractKotlinCompile(), Ko private val libraryFilter: (File) -> Boolean get() = if ("-Xir" in kotlinOptions.freeCompilerArgs) { - // TODO: Detect IR libraries - { true } + LibraryUtils::isKotlinJavascriptIrLibrary } else { LibraryUtils::isKotlinJavascriptLibrary } @@ -578,6 +577,7 @@ open class Kotlin2JsCompile : AbstractKotlinCompile(), Ko if ("-Xir" in args.freeArgs) { logger.kotlinDebug("Using JS IR backend") incremental = false + args.freeArgs += "-Xir-legacy-gradle-plugin-compatibility" } val dependencies = compileClasspath