From f0cfbb9918949c94bb5b76064acd963f61158b22 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov <41585329+ddolovov@users.noreply.github.com> Date: Wed, 22 Aug 2018 14:01:20 +0300 Subject: [PATCH] move Kotlin/Native metadata deserialization and KLIB reader to a separate module (#1908) 1. move Kotlin/Native metadata deserialization and KLIB reader to a separate module 2. decouple KLIB reader from ModuleDescriptor creation --- backend.native/build.gradle | 3 +- .../org/jetbrains/kotlin/cli/bc/K2Native.kt | 6 +- .../kotlin/backend/konan/InteropUtils.kt | 51 ------- .../kotlin/backend/konan/KonanConfig.kt | 12 +- .../backend/konan/library/KonanLibrary.kt | 56 ------- .../konan/library/KonanLibraryReader.kt | 43 ------ .../konan/library/KonanLibraryWriter.kt | 1 + .../library/SearchPathResolverExtensions.kt | 50 ++++--- .../konan/library/impl/KonanLibrary.kt | 116 --------------- .../library/impl/KonanLibraryReaderImpl.kt | 108 -------------- .../library/impl/KonanLibraryWriterImpl.kt | 4 +- .../konan/library/impl/MetadataReaderImpl.kt | 30 ---- .../konan/library/impl/MetadataWriterImpl.kt | 3 +- .../backend/konan/llvm/BinaryInterface.kt | 2 +- .../kotlin/backend/konan/llvm/ContextUtils.kt | 17 +-- .../konan/optimizations/DFGSerializer.kt | 5 +- .../serialization/IrDescriptorDeserializer.kt | 1 + .../serialization/KonanMetadataVersion.kt | 32 ---- .../serialization/KonanSerializationUtil.kt | 108 +------------- .../serialization/KonanSerializerExtension.kt | 19 +-- .../LocalDeclarationDeserializer.kt | 2 + .../konan/serialization/SerializeIr.kt | 1 + build.gradle | 2 +- cmd/run_konan | 4 +- cmd/run_konan.bat | 4 +- .../konan.metadata.serializer/settings.gradle | 1 - .../build.gradle | 2 +- extracted/konan.serializer/settings.gradle | 1 + .../kotlin/konan/library/KonanLibrary.kt | 44 ++++++ .../konan/library/KonanLibraryReader.kt | 28 ++++ .../konan/library/KonanMetadataReader.kt | 6 + .../library/impl/DefaultMetadataReaderImpl.kt | 12 ++ .../konan/library/impl/KonanLibraryImpl.kt | 85 +++++++++++ .../library/impl/KonanLibraryReaderImpl.kt | 83 +++++++++++ .../konan}/KonanClassDataFinder.kt | 29 +--- .../konan/KonanDeserializationUtils.kt | 11 ++ .../konan/KonanMetadataVersion.kt | 16 ++ .../konan/KonanModuleDescriptorFactory.kt | 139 ++++++++++++++++++ .../konan}/KonanPackageFragment.kt | 60 +++----- .../konan/KonanSerializerProtocol.kt | 19 +++ .../konan/NullFlexibleTypeDeserializer.kt | 14 ++ .../SyntheticPackageFragmentDescriptors.kt | 31 ++-- .../org/jetbrains/kotlin/cli/klib/main.kt | 21 +-- settings.gradle | 2 +- .../org/jetbrains/kotlin/konan/file/File.kt | 2 + .../konan/library/SearchPathResolver.kt | 38 +++-- .../kotlin/cli/utilities/InteropCompiler.kt | 6 +- 47 files changed, 610 insertions(+), 720 deletions(-) delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibrary.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataReaderImpl.kt delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMetadataVersion.kt delete mode 100644 extracted/konan.metadata.serializer/settings.gradle rename extracted/{konan.metadata.serializer => konan.serializer}/build.gradle (95%) create mode 100644 extracted/konan.serializer/settings.gradle create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibrary.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibraryReader.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanMetadataReader.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/DefaultMetadataReaderImpl.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryImpl.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryReaderImpl.kt rename {backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization => extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan}/KonanClassDataFinder.kt (57%) create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializationUtils.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanMetadataVersion.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanModuleDescriptorFactory.kt rename {backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization => extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan}/KonanPackageFragment.kt (58%) create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanSerializerProtocol.kt create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/NullFlexibleTypeDeserializer.kt rename backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt => extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SyntheticPackageFragmentDescriptors.kt (72%) diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 9367a31d87a..2b2a41c6fd5 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -140,11 +140,12 @@ dependencies { compilerCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" compilerCompile "org.jetbrains.kotlin:konan.descriptors:$konanVersion" compilerCompile "org.jetbrains.kotlin:konan.metadata:$konanVersion" - compilerCompile "org.jetbrains.kotlin:konan.metadata.serializer:$konanVersion" + compilerCompile "org.jetbrains.kotlin:konan.serializer:$konanVersion" cli_bcCompile kotlinCompilerModule cli_bcCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" cli_bcCompile sourceSets.compiler.output + cli_bcCompile "org.jetbrains.kotlin:konan.serializer:$konanVersion" bc_frontendCompile kotlinCompilerModule diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index fc216e50d95..92e3d4b954f 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -20,7 +20,6 @@ import com.intellij.openapi.Disposable import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable import org.jetbrains.kotlin.backend.konan.* -import org.jetbrains.kotlin.backend.konan.serialization.KonanMetadataVersion import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.CLITool import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager @@ -32,7 +31,9 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser -import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.konan.KonanVersion import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.target.CompilerOutputKind @@ -40,6 +41,7 @@ import org.jetbrains.kotlin.konan.util.profile import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.utils.KotlinPaths +import org.jetbrains.kotlin.serialization.konan.KonanMetadataVersion private class K2NativeCompilerPerformanceManager: CommonCompilerPerformanceManager("Kotlin to Native Compiler") class K2Native : CLICompiler() { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index dd01cced683..1d7f6a89a05 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -16,14 +16,8 @@ package org.jetbrains.kotlin.backend.konan -import org.jetbrains.kotlin.backend.konan.descriptors.ClassifierAliasingPackageFragmentDescriptor -import org.jetbrains.kotlin.backend.konan.descriptors.ExportedForwardDeclarationsPackageFragmentDescriptor -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader -import org.jetbrains.kotlin.backend.konan.serialization.KonanPackageFragment import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.konan.interop.InteropFqNames import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.FqName @@ -32,25 +26,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.util.OperatorNameConventions -interface InteropLibrary { - fun createSyntheticPackages( - module: ModuleDescriptor, - konanPackageFragments: List - ): List -} - -fun createInteropLibrary(reader: KonanLibraryReader): InteropLibrary? { - if (reader.manifestProperties.getProperty("interop") != "true") return null - val pkg = reader.manifestProperties.getProperty("package") - ?: error("Inconsistent manifest: interop library ${reader.libraryName} should have `package` specified") - val exportForwardDeclarations = reader.manifestProperties - .getProperty("exportForwardDeclarations").split(' ') - .map { it.trim() }.filter { it.isNotEmpty() } - .map { FqName(it) } - - return InteropLibraryImpl(FqName(pkg), exportForwardDeclarations) -} - internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives: ClassDescriptor) { val packageScope = builtIns.builtInsModule.getPackage(InteropFqNames.packageName).memberScope @@ -183,29 +158,3 @@ private fun MemberScope.getContributedClass(name: String): ClassDescriptor = private fun MemberScope.getContributedFunctions(name: String) = this.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS) - -private class InteropLibraryImpl( - private val packageFqName: FqName, - private val exportForwardDeclarations: List -) : InteropLibrary { - override fun createSyntheticPackages( - module: ModuleDescriptor, - konanPackageFragments: List - ): List { - val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName } - - val result = mutableListOf() - - // Allow references to forwarding declarations to be resolved into classifiers declared in this library: - listOf(InteropFqNames.cNamesStructs, InteropFqNames.objCNamesClasses, InteropFqNames.objCNamesProtocols).mapTo(result) { fqName -> - ClassifierAliasingPackageFragmentDescriptor(interopPackageFragments, module, fqName) - } - // TODO: use separate namespaces for structs, enums, Objective-C protocols etc. - - result.add(ExportedForwardDeclarationsPackageFragmentDescriptor( - module, packageFqName, exportForwardDeclarations - )) - - return result - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 8fc3e3b819c..b209fc8f662 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -17,9 +17,6 @@ package org.jetbrains.kotlin.backend.konan import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader -import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl -import org.jetbrains.kotlin.backend.konan.library.impl.purgeUnneeded import org.jetbrains.kotlin.backend.konan.library.resolveImmediateLibraries import org.jetbrains.kotlin.backend.konan.library.resolveLibrariesRecursive import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies @@ -35,9 +32,11 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.konan.interop.createForwardDeclarationsModule import org.jetbrains.kotlin.konan.TempFiles import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.KonanLibraryReader import org.jetbrains.kotlin.konan.library.defaultResolver import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.util.profile +import org.jetbrains.kotlin.serialization.konan.DefaultKonanModuleDescriptorFactory import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager @@ -94,7 +93,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES) private val resolver = defaultResolver(repositories, target, distribution) - internal val immediateLibraries: List by lazy { + internal val immediateLibraries: List by lazy { val result = resolver.resolveImmediateLibraries(libraryNames, target, currentAbiVersion, configuration.getBoolean(KonanConfigKeys.NOSTDLIB), @@ -136,7 +135,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration for (klib in libraries) { profile("Loading ${klib.libraryName}") { // MutableModuleContext needs ModuleDescriptorImpl, rather than ModuleDescriptor. - val moduleDescriptor = klib.moduleDescriptor(specifics) + val moduleDescriptor = DefaultKonanModuleDescriptorFactory.createModuleDescriptor(klib, specifics) allMetadata.add(moduleDescriptor) friendLibsSet?.apply { if (contains(klib.libraryFile)) @@ -175,3 +174,6 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String) = this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message) + +private fun List.purgeUnneeded(config: KonanConfig): List = + this.filter{ (!it.isDefaultLibrary && !config.purgeUserLibs) || it.isNeededForLink } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt deleted file mode 100644 index b09c8c3759d..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.library - -import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.util.visibleName - -// This scheme describes the Konan Library (klib) layout. -interface KonanLibraryLayout { - val libDir: File - val target: KonanTarget? - // This is a default implementation. Can't make it an assignment. - get() = null - val manifestFile - get() = File(libDir, "manifest") - val resourcesDir - get() = File(libDir, "resources") - val targetsDir - get() = File(libDir, "targets") - val targetDir - get() = File(targetsDir, target!!.visibleName) - val kotlinDir - get() = File(targetDir, "kotlin") - val nativeDir - get() = File(targetDir, "native") - val includedDir - get() = File(targetDir, "included") - val linkdataDir - get() = File(libDir, "linkdata") - val moduleHeaderFile - get() = File(linkdataDir, "module") - val dataFlowGraphFile - get() = File(linkdataDir, "module_data_flow_graph") - fun packageFile(packageName: String) - = File(linkdataDir, if (packageName == "") "root_package.knm" else "package_$packageName.knm") -} - -interface KonanLibrary: KonanLibraryLayout { - val libraryName: String -} - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt deleted file mode 100644 index 862f80c639b..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryReader.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.library - -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.konan.properties.Properties - -interface KonanLibraryReader { - val libraryName: String - val uniqueName: String - val bitcodePaths: List - val includedPaths: List - val linkerOpts: List - val unresolvedDependencies: List - val dataFlowGraph: ByteArray? - val isDefaultLibrary: Boolean get() = false - val isNeededForLink: Boolean get() = true - val manifestProperties: Properties - val moduleHeaderData: ByteArray - fun packageMetadata(fqName: String): ByteArray - fun markPackageAccessed(fqName: String) - fun moduleDescriptor(specifics: LanguageVersionSettings): ModuleDescriptor -} - -interface MetadataReader { - fun loadSerializedModule(): ByteArray - fun loadSerializedPackageFragment(fqName: String): ByteArray -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt index 32c3da04060..43311c16f4c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.backend.konan.library import llvm.LLVMModuleRef +import org.jetbrains.kotlin.konan.library.KonanLibraryReader interface KonanLibraryWriter { fun addLinkData(linkData: LinkData) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolverExtensions.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolverExtensions.kt index 06b0ca42966..6a72bd9488d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolverExtensions.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolverExtensions.kt @@ -16,22 +16,29 @@ package org.jetbrains.kotlin.backend.konan.library -import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.KonanLibraryReader import org.jetbrains.kotlin.konan.library.SearchPathResolver +import org.jetbrains.kotlin.konan.library.impl.LibraryReaderImpl import org.jetbrains.kotlin.konan.target.KonanTarget +const val KONAN_CURRENT_ABI_VERSION = 1 + +/** + * Returns the list of [KonanLibraryReader]s given the list of user provided [libraryNames] along with + * other parameters: [target], [abiVersion], [noStdLib], [noDefaultLibs]. + */ fun SearchPathResolver.resolveImmediateLibraries(libraryNames: List, target: KonanTarget, - abiVersion: Int = 1, + abiVersion: Int = KONAN_CURRENT_ABI_VERSION, noStdLib: Boolean = false, noDefaultLibs: Boolean = false, - logger: ((String) -> Unit)?): List { + logger: ((String) -> Unit)?): List { val userProvidedLibraries = libraryNames .map { resolve(it) } .map{ LibraryReaderImpl(it, abiVersion, target) } - val defaultLibraries = defaultLinks(nostdlib = noStdLib, noDefaultLibs = noDefaultLibs).map { + val defaultLibraries = defaultLinks(noStdLib = noStdLib, noDefaultLibs = noDefaultLibs).map { LibraryReaderImpl(it, abiVersion, target, isDefaultLibrary = true) } @@ -44,8 +51,7 @@ fun SearchPathResolver.resolveImmediateLibraries(libraryNames: List, return resolvedLibraries.distinctBy { it.libraryFile.absolutePath } } -private fun warnOnLibraryDuplicates(resolvedLibraries: List, - logger: ((String) -> Unit)? ) { +private fun warnOnLibraryDuplicates(resolvedLibraries: List, logger: ((String) -> Unit)? ) { if (logger == null) return @@ -56,38 +62,46 @@ private fun warnOnLibraryDuplicates(resolvedLibraries: List, } } -fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List, +/** + * For each of the given [immediateLibraries] fills in `resolvedDependencies` field with the + * [KonanLibraryReader]s the library !!directly!! depends on. + */ +fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List, target: KonanTarget, abiVersion: Int) { - val cache = mutableMapOf() + val cache = mutableMapOf() cache.putAll(immediateLibraries.map { it.libraryFile.absoluteFile to it }) var newDependencies = cache.values.toList() do { - newDependencies = newDependencies.map { library: LibraryReaderImpl -> + newDependencies = newDependencies.map { library: KonanLibraryReader -> library.unresolvedDependencies .map { resolve(it).absoluteFile } - .map { + .mapNotNull { if (it in cache) { library.resolvedDependencies.add(cache[it]!!) null } else { val reader = LibraryReaderImpl(it, abiVersion, target) - cache.put(it,reader) - library.resolvedDependencies.add(reader) + cache[it] = reader + library.resolvedDependencies.add(reader) reader } - }.filterNotNull() + } } .flatten() } while (newDependencies.isNotEmpty()) } -fun List.withResolvedDependencies(): List { - val result = mutableSetOf() +/** + * For the given list of [KonanLibraryReader]s returns the list of [KonanLibraryReader]s + * that includes the same libraries plus all their (transitive) dependencies. + */ +fun List.withResolvedDependencies(): List { + val result = mutableSetOf() result.addAll(this) var newDependencies = result.toList() do { newDependencies = newDependencies - .map { it -> it.resolvedDependencies } .flatten() + .map { it -> it.resolvedDependencies }.flatten() .filter { it !in result } result.addAll(newDependencies) } while (newDependencies.isNotEmpty()) @@ -96,9 +110,9 @@ fun List.withResolvedDependencies(): List fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List, target: KonanTarget, - abiVersion: Int = 1, + abiVersion: Int = KONAN_CURRENT_ABI_VERSION, noStdLib: Boolean = false, - noDefaultLibs: Boolean = false): List { + noDefaultLibs: Boolean = false): List { val immediateLibraries = resolveImmediateLibraries( libraryNames = libraryNames, target = target, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibrary.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibrary.kt deleted file mode 100644 index cd856e58982..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibrary.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.library.impl - -import org.jetbrains.kotlin.backend.konan.library.KonanLibrary -import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent -import org.jetbrains.kotlin.konan.file.* -import org.jetbrains.kotlin.konan.target.KonanTarget - -open class ZippedKonanLibrary(val klibFile: File, override val target: KonanTarget? = null): KonanLibrary { - init { - if (!klibFile.exists) { - error("Could not find $klibFile.") - } - if (!klibFile.isFile) { - error("Expected $klibFile to be a regular file.") - } - } - - override val libraryName = klibFile.path.removeSuffixIfPresent(".klib") - - override val libDir by lazy { - klibFile.asZipRoot - } - - fun unpackTo(newDir: File) { - if (newDir.exists) { - if (newDir.isDirectory) - newDir.deleteRecursively() - else - newDir.delete() - } - libDir.recursiveCopyTo(newDir) - if (!newDir.exists) error("Could not unpack $klibFile as $newDir.") - } -} - -// This class automatically extracts pieces of -// the library on first access. Use it if you need -// to pass extracted files to an external tool. -// Otherwise, stick to ZippedKonanLibrary. -class FileExtractor(zippedLibrary: KonanLibrary): KonanLibrary by zippedLibrary { - - override val manifestFile: File by lazy { - extract(super.manifestFile) - } - - override val resourcesDir: File by lazy { - extractDir(super.resourcesDir) - } - - override val includedDir: File by lazy { - extractDir(super.includedDir) - } - - override val kotlinDir: File by lazy { - extractDir(super.kotlinDir) - } - - override val nativeDir: File by lazy { - extractDir(super.nativeDir) - } - - override val linkdataDir: File by lazy { - extractDir(super.linkdataDir) - } - - fun extract(file: File): File { - val temporary = createTempFile(file.name) - file.copyTo(temporary) - temporary.deleteOnExit() - return temporary - } - - fun extractDir(directory: File): File { - val temporary = createTempDir(directory.name) - directory.recursiveCopyTo(temporary) - temporary.deleteOnExitRecursively() - return temporary - } -} - -class UnzippedKonanLibrary(override val libDir: File, override val target: KonanTarget? = null): KonanLibrary { - override val libraryName = libDir.path - - val targetList: List by lazy { - targetsDir.listFiles.map{it.name} - } -} - -fun KonanLibrary(klib: File, target: KonanTarget? = null) = - if (klib.isFile) ZippedKonanLibrary(klib, target) - else UnzippedKonanLibrary(klib, target) - -val KonanLibrary.realFiles - get() = when (this) { - is ZippedKonanLibrary -> FileExtractor(this) - // Unpacked library just provides its own files. - is UnzippedKonanLibrary -> this - else -> error("Provide an extractor for your container.") - } - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt deleted file mode 100644 index 26e4f5f3781..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryReaderImpl.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.library.impl - -import org.jetbrains.kotlin.backend.konan.KonanConfig -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader -import org.jetbrains.kotlin.backend.konan.serialization.emptyPackages -import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule -import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.properties.* -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions -import org.jetbrains.kotlin.konan.util.substitute - -class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int, - val target: KonanTarget? = null, override val isDefaultLibrary: Boolean = false) - : KonanLibraryReader { - - // For the zipped libraries inPlace gives files from zip file system - // whereas realFiles extracts them to /tmp. - // For unzipped libraries inPlace and realFiles are the same - // providing files in the library directory. - private val inPlace = KonanLibrary(libraryFile, target) - private val realFiles = inPlace.realFiles - - private val reader = MetadataReaderImpl(inPlace) - - override val manifestProperties: Properties by lazy { - val properties = inPlace.manifestFile.loadProperties() - if (target != null) substitute(properties, defaultTargetSubstitutions(target)) - properties - } - - val abiVersion: String - get() { - val manifestAbiVersion = manifestProperties.getProperty("abi_version") - if ("$currentAbiVersion" != manifestAbiVersion) - error("ABI version mismatch. Compiler expects: $currentAbiVersion, the library is $manifestAbiVersion") - return manifestAbiVersion - } - - val targetList = inPlace.targetsDir.listFiles.map{it.name} - override val dataFlowGraph by lazy { inPlace.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null } } - - override val libraryName - get() = inPlace.libraryName - - override val uniqueName - get() = manifestProperties.propertyString("unique_name")!! - - override val bitcodePaths: List - get() = (realFiles.kotlinDir.listFilesOrEmpty + realFiles.nativeDir.listFilesOrEmpty) - .map { it.absolutePath } - - override val includedPaths: List - get() = (realFiles.includedDir.listFilesOrEmpty).map { it.absolutePath } - - override val linkerOpts: List - get() = manifestProperties.propertyList("linkerOpts", target!!.visibleName) - - override val unresolvedDependencies: List - get() = manifestProperties.propertyList("depends") - - val resolvedDependencies = mutableListOf() - - override val moduleHeaderData: ByteArray by lazy { - reader.loadSerializedModule() - } - - override var isNeededForLink: Boolean = false - private set - - private val emptyPackages by lazy { emptyPackages(moduleHeaderData) } - - override fun markPackageAccessed(fqName: String) { - if (!isNeededForLink // fast path - && !emptyPackages.contains(fqName)) { - isNeededForLink = true - } - } - - override fun packageMetadata(fqName: String): ByteArray { - return reader.loadSerializedPackageFragment(fqName) - } - - override fun moduleDescriptor(specifics: LanguageVersionSettings) - = deserializeModule(specifics, this) - -} - -internal fun List.purgeUnneeded(config: KonanConfig): List = - this.filter{ (!it.isDefaultLibrary && !config.purgeUserLibs) || it.isNeededForLink } - diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt index e493b05943a..1d37af3e2c5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/KonanLibraryWriterImpl.kt @@ -16,10 +16,10 @@ package org.jetbrains.kotlin.backend.konan.library.impl -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader +import org.jetbrains.kotlin.konan.library.KonanLibraryReader import llvm.LLVMModuleRef import llvm.LLVMWriteBitcodeToFile -import org.jetbrains.kotlin.backend.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.konan.file.* diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataReaderImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataReaderImpl.kt deleted file mode 100644 index f3d4c165280..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataReaderImpl.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.library.impl - -import org.jetbrains.kotlin.backend.konan.library.KonanLibrary -import org.jetbrains.kotlin.backend.konan.library.MetadataReader - -class MetadataReaderImpl(library: KonanLibrary) : MetadataReader, KonanLibrary by library { - - override fun loadSerializedModule(): ByteArray { - return moduleHeaderFile.readBytes() - } - - override fun loadSerializedPackageFragment(fqName: String) - = packageFile(fqName).readBytes() -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt index b15dab5bba4..142861304c9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/impl/MetadataWriterImpl.kt @@ -16,9 +16,8 @@ package org.jetbrains.kotlin.backend.konan.library.impl -import org.jetbrains.kotlin.backend.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.LinkData -import org.jetbrains.kotlin.konan.file.File internal class MetadataWriterImpl(library: KonanLibrary): KonanLibrary by library { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt index 943565ca849..d4ebacb5dd2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BinaryInterface.kt @@ -20,7 +20,7 @@ import llvm.LLVMTypeRef import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.isInlined -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader +import org.jetbrains.kotlin.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index c233b633478..34d736cd98d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -25,8 +25,7 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.findPackage import org.jetbrains.kotlin.backend.konan.hash.GlobalHash import org.jetbrains.kotlin.backend.konan.irasdescriptors.* -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader -import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl +import org.jetbrains.kotlin.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies import org.jetbrains.kotlin.descriptors.konan.CompiledKonanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin @@ -324,7 +323,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { return function } - private val usedLibraries = mutableSetOf() + private val usedLibraries = mutableSetOf() val imports = object : LlvmImports { @@ -340,7 +339,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { error("$reader (${reader.libraryName}) is used but not requested") } - usedLibraries.add(reader as LibraryReaderImpl) + usedLibraries.add(reader) } } @@ -351,12 +350,12 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { .topoSort() } - private fun List.topoSort(): List { - var sorted = mutableListOf() - val visited = mutableSetOf() - val tempMarks = mutableSetOf() + private fun List.topoSort(): List { + var sorted = mutableListOf() + val visited = mutableSetOf() + val tempMarks = mutableSetOf() - fun visit(node: LibraryReaderImpl, result: MutableList) { + fun visit(node: KonanLibraryReader, result: MutableList) { if (visited.contains(node)) return if (tempMarks.contains(node)) error("Cyclic dependency in library graph.") tempMarks.add(node) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt index e5f78889daa..5fb6b405f73 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt @@ -16,10 +16,10 @@ package org.jetbrains.kotlin.backend.konan.optimizations -import org.jetbrains.kotlin.backend.common.reportWarning import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.serialization.konan.DefaultKonanModuleDescriptorFactory import sun.misc.Unsafe import kotlin.reflect.KClass import kotlin.reflect.full.memberProperties @@ -948,7 +948,8 @@ internal object DFGSerializer { } if (libraryDataFlowGraph != null) { - val module = DataFlowIR.Module(library.moduleDescriptor(specifics)) + val module = DataFlowIR.Module( + DefaultKonanModuleDescriptorFactory.createModuleDescriptor(library, specifics)) val reader = ArraySlice(libraryDataFlowGraph) val dataLayoutHash = reader.readLong() val expectedHash = computeDataLayoutHash(Module::class) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt index 7ae3a5e4052..9001d4b84bf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/IrDescriptorDeserializer.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.deserialization.descriptors.* +import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.isError diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMetadataVersion.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMetadataVersion.kt deleted file mode 100644 index 7d85973af59..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanMetadataVersion.kt +++ /dev/null @@ -1,32 +0,0 @@ -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion - - -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -class KonanMetadataVersion(vararg numbers: Int): BinaryVersion(*numbers){ - override fun isCompatible(): Boolean = this.major == 1 && this.minor == 0 - companion object { - @JvmField - val INSTANCE = KonanMetadataVersion(1, 0, 0) - - @JvmField - val INVALID_VERSION = KonanMetadataVersion() - } - -} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 01aa44c5673..f86a5d55e93 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -17,32 +17,18 @@ package org.jetbrains.kotlin.backend.konan.serialization import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.createInteropLibrary import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.LinkData -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin -import org.jetbrains.kotlin.descriptors.konan.createKonanModuleDescriptor -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf -import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf.* -import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer -import org.jetbrains.kotlin.serialization.deserialization.* -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.storage.StorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.SimpleType /* * This is Konan specific part of public descriptor @@ -55,92 +41,6 @@ import org.jetbrains.kotlin.types.SimpleType * with MemberDeserializer class. */ -/* ------------ Deserializer part ------------------------------------------*/ - -object NullFlexibleTypeDeserializer : FlexibleTypeDeserializer { - override fun create(proto: ProtoBuf.Type, flexibleId: String, - lowerBound: SimpleType, upperBound: SimpleType): KotlinType { - error("Illegal use of flexible type deserializer.") - } -} - -fun createKonanPackageFragmentProvider( - reader: KonanLibraryReader, - fragmentNames: List, - storageManager: StorageManager, module: ModuleDescriptor, - configuration: DeserializationConfiguration): PackageFragmentProvider { - - val packageFragments = fragmentNames.map{ - KonanPackageFragment(it, reader, storageManager, module) - } - - val interopLibrary = createInteropLibrary(reader) - - val syntheticInteropPackageFragments = - interopLibrary?.createSyntheticPackages(module, packageFragments) ?: emptyList() - - val provider = PackageFragmentProviderImpl(packageFragments + syntheticInteropPackageFragments) - - val notFoundClasses = NotFoundClasses(storageManager, module) - - val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(module, notFoundClasses, KonanSerializerProtocol) - - val components = DeserializationComponents( - storageManager, module, configuration, - DeserializedClassDataFinder(provider), - annotationAndConstantLoader, - provider, - LocalClassifierTypeSettings.Default, - ErrorReporter.DO_NOTHING, - LookupTracker.DO_NOTHING, NullFlexibleTypeDeserializer, - emptyList(), notFoundClasses, ContractDeserializer.DEFAULT, extensionRegistryLite = KonanSerializerProtocol.extensionRegistry ) - - for (packageFragment in packageFragments) { - packageFragment.initialize(components) - } - - return provider -} - -public fun parsePackageFragment(packageData: ByteArray): LinkDataPackageFragment = - LinkDataPackageFragment.parseFrom(packageData, - KonanSerializerProtocol.extensionRegistry) - -public fun parseModuleHeader(libraryData: ByteArray): LinkDataLibrary = - LinkDataLibrary.parseFrom(libraryData, - KonanSerializerProtocol.extensionRegistry) - -public fun emptyPackages(libraryData: ByteArray) - = parseModuleHeader(libraryData).emptyPackageList - -internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, - reader: KonanLibraryReader): ModuleDescriptorImpl { - - val libraryProto = parseModuleHeader(reader.moduleHeaderData) - - val moduleName = libraryProto.moduleName - - val storageManager = LockBasedStorageManager() - val moduleDescriptor = createKonanModuleDescriptor( - Name.special(moduleName), storageManager, - origin = DeserializedKonanModuleOrigin(reader) - ) - val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) - - val provider = createKonanPackageFragmentProvider( - reader, - libraryProto.packageFragmentNameList, - storageManager, - moduleDescriptor, deserializationConfiguration) - - moduleDescriptor.initialize(provider) - - return moduleDescriptor -} - - -/* ------------ Serializer part ------------------------------------------*/ - internal class KonanSerializationUtil(val context: Context, metadataVersion: BinaryVersion) { val serializerExtension = KonanSerializerExtension(context, metadataVersion) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt index 3b149ad3a0b..d2c3c8826b6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt @@ -22,10 +22,9 @@ import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable -import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase -import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol +import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol import org.jetbrains.kotlin.types.KotlinType internal class KonanSerializerExtension(val context: Context, override val metadataVersion: BinaryVersion) : @@ -105,22 +104,6 @@ internal class KonanSerializerExtension(val context: Context, override val metad } } -object KonanSerializerProtocol : SerializerExtensionProtocol( - ExtensionRegistryLite.newInstance().apply { - KonanProtoBuf.registerAllExtensions(this) - }, - KonanProtoBuf.packageFqName, - KonanProtoBuf.constructorAnnotation, - KonanProtoBuf.classAnnotation, - KonanProtoBuf.functionAnnotation, - KonanProtoBuf.propertyAnnotation, - KonanProtoBuf.enumEntryAnnotation, - KonanProtoBuf.compileTimeValue, - KonanProtoBuf.parameterAnnotation, - KonanProtoBuf.typeAnnotation, - KonanProtoBuf.typeParameterAnnotation -) - internal interface IrAwareExtension { fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: KonanDescriptorSerializer): String diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt index 5cd2c8cb65f..6c44cd68b5d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationDeserializer.kt @@ -28,6 +28,8 @@ import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor +import org.jetbrains.kotlin.serialization.konan.KonanMetadataVersion +import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment // This class knows how to construct contexts for // MemberDeserializer to deserialize descriptors declared in IR. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt index ceceaf8dcb0..4bd1de94950 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt @@ -52,6 +52,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.parents import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassConstructorDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor diff --git a/build.gradle b/build.gradle index 9fffc062098..6a3acb73607 100644 --- a/build.gradle +++ b/build.gradle @@ -259,7 +259,7 @@ task distCompiler(type: Copy) { into('konan/lib') } - from(file("${gradle.includedBuild('konan.metadata.serializer').projectDir}/build/libs")) { + from(file("${gradle.includedBuild('konan.serializer').projectDir}/build/libs")) { into('konan/lib') } diff --git a/cmd/run_konan b/cmd/run_konan index cad895ef5e2..c9338eb2cda 100755 --- a/cmd/run_konan +++ b/cmd/run_konan @@ -87,10 +87,10 @@ INTEROP_JAR="${KONAN_HOME}/konan/lib/Runtime.jar" SHARED_JAR="${KONAN_HOME}/konan/lib/shared.jar" EXTRACTED_DESCRIPTORS_JAR="${KONAN_HOME}/konan/lib/konan.descriptors.jar" EXTRACTED_METADATA_JAR="${KONAN_HOME}/konan/lib/konan.metadata.jar" -EXTRACTED_METADATA_SERIALIZER_JAR="${KONAN_HOME}/konan/lib/konan.metadata.serializer.jar" +EXTRACTED_SERIALIZER_JAR="${KONAN_HOME}/konan/lib/konan.serializer.jar" KLIB_JAR="${KONAN_HOME}/konan/lib/klib.jar" UTILITIES_JAR="${KONAN_HOME}/konan/lib/utilities.jar" -KONAN_CLASSPATH="$KOTLIN_JAR:$KOTLIN_STDLIB_JAR:$KOTLIN_REFLECT_JAR:$KOTLIN_SCRIPT_RUNTIME_JAR:$INTEROP_JAR:$STUB_GENERATOR_JAR:$INTEROP_INDEXER_JAR:$KONAN_JAR:$KLIB_JAR:$UTILITIES_JAR:$SHARED_JAR:$EXTRACTED_DESCRIPTORS_JAR:$EXTRACTED_METADATA_JAR:$EXTRACTED_METADATA_SERIALIZER_JAR" +KONAN_CLASSPATH="$KOTLIN_JAR:$KOTLIN_STDLIB_JAR:$KOTLIN_REFLECT_JAR:$KOTLIN_SCRIPT_RUNTIME_JAR:$INTEROP_JAR:$STUB_GENERATOR_JAR:$INTEROP_INDEXER_JAR:$KONAN_JAR:$KLIB_JAR:$UTILITIES_JAR:$SHARED_JAR:$EXTRACTED_DESCRIPTORS_JAR:$EXTRACTED_METADATA_JAR:$EXTRACTED_SERIALIZER_JAR" TOOL_CLASS=org.jetbrains.kotlin.cli.utilities.MainKt LIBCLANG_DISABLE_CRASH_RECOVERY=1 \ diff --git a/cmd/run_konan.bat b/cmd/run_konan.bat index 41ae7126374..70319fdcc1c 100644 --- a/cmd/run_konan.bat +++ b/cmd/run_konan.bat @@ -57,7 +57,7 @@ set "KONAN_LIB=%_KONAN_HOME%\konan\lib" set "SHARED_JAR=%KONAN_LIB%\shared.jar" set "EXTRACTED_DESCRIPTORS_JAR=%KONAN_LIB%\konan.descriptors.jar" set "EXTRACTED_METADATA_JAR=%KONAN_LIB%\konan.metadata.jar" -set "EXTRACTED_METADATA_SERIALIZER_JAR=%KONAN_LIB%\konan.metadata.serializer.jar" +set "EXTRACTED_SERIALIZER_JAR=%KONAN_LIB%\konan.serializer.jar" set "INTEROP_INDEXER_JAR=%KONAN_LIB%\Indexer.jar" set "INTEROP_RUNTIME_JAR=%KONAN_LIB%\Runtime.jar" set "KLIB_JAR=%KONAN_LIB%\klib.jar" @@ -69,7 +69,7 @@ set "KOTLIN_SCRIPT_RUNTIME_JAR=%KONAN_LIB%\kotlin-script-runtime.jar" set "STUB_GENERATOR_JAR=%KONAN_LIB%\StubGenerator.jar" set "UTILITIES_JAR=%KONAN_LIB%\utilities.jar" -set "KONAN_CLASSPATH=%KOTLIN_JAR%;%KOTLIN_STDLIB_JAR%;%KOTLIN_REFLECT_JAR%;%KOTLIN_SCRIPT_RUNTIME_JAR%;%INTEROP_RUNTIME_JAR%;%KONAN_JAR%;%STUB_GENERATOR_JAR%;%INTEROP_INDEXER_JAR%;%SHARED_JAR%;%EXTRACTED_DESCRIPTORS_JAR%;%EXTRACTED_METADATA_JAR%;%EXTRACTED_METADATA_SERIALIZER_JAR%;%KLIB_JAR%;%UTILITIES_JAR%" +set "KONAN_CLASSPATH=%KOTLIN_JAR%;%KOTLIN_STDLIB_JAR%;%KOTLIN_REFLECT_JAR%;%KOTLIN_SCRIPT_RUNTIME_JAR%;%INTEROP_RUNTIME_JAR%;%KONAN_JAR%;%STUB_GENERATOR_JAR%;%INTEROP_INDEXER_JAR%;%SHARED_JAR%;%EXTRACTED_DESCRIPTORS_JAR%;%EXTRACTED_METADATA_JAR%;%EXTRACTED_SERIALIZER_JAR%;%KLIB_JAR%;%UTILITIES_JAR%" set JAVA_OPTS=-ea ^ -Xmx3G ^ diff --git a/extracted/konan.metadata.serializer/settings.gradle b/extracted/konan.metadata.serializer/settings.gradle deleted file mode 100644 index bc8cffdb99b..00000000000 --- a/extracted/konan.metadata.serializer/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "konan.metadata.serializer" diff --git a/extracted/konan.metadata.serializer/build.gradle b/extracted/konan.serializer/build.gradle similarity index 95% rename from extracted/konan.metadata.serializer/build.gradle rename to extracted/konan.serializer/build.gradle index 578969ddeaa..98ceaa224a5 100644 --- a/extracted/konan.metadata.serializer/build.gradle +++ b/extracted/konan.serializer/build.gradle @@ -19,7 +19,7 @@ repositories { sourceSets { main.kotlin { - srcDir 'src/main/kotlin' + srcDir 'src' } } diff --git a/extracted/konan.serializer/settings.gradle b/extracted/konan.serializer/settings.gradle new file mode 100644 index 00000000000..001026741f2 --- /dev/null +++ b/extracted/konan.serializer/settings.gradle @@ -0,0 +1 @@ +rootProject.name = "konan.serializer" diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibrary.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibrary.kt new file mode 100644 index 00000000000..6d432866eba --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibrary.kt @@ -0,0 +1,44 @@ +package org.jetbrains.kotlin.konan.library + +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.KonanTarget + +// This scheme describes the Kotlin/Native Library (klib) layout. +interface KonanLibraryLayout { + + val libDir: File + val target: KonanTarget? + // This is a default implementation. Can't make it an assignment. + get() = null + + val manifestFile + get() = File(libDir, "manifest") + val resourcesDir + get() = File(libDir, "resources") + + val targetsDir + get() = File(libDir, "targets") + val targetDir + get() = File(targetsDir, target!!.visibleName) + + val kotlinDir + get() = File(targetDir, "kotlin") + val nativeDir + get() = File(targetDir, "native") + val includedDir + get() = File(targetDir, "included") + + val linkdataDir + get() = File(libDir, "linkdata") + val moduleHeaderFile + get() = File(linkdataDir, "module") + val dataFlowGraphFile + get() = File(linkdataDir, "module_data_flow_graph") + + fun packageFile(packageName: String) + = File(linkdataDir, if (packageName == "") "root_package.knm" else "package_$packageName.knm") +} + +interface KonanLibrary: KonanLibraryLayout { + val libraryName: String +} diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibraryReader.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibraryReader.kt new file mode 100644 index 00000000000..64c3d33e1aa --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanLibraryReader.kt @@ -0,0 +1,28 @@ +package org.jetbrains.kotlin.konan.library + +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.properties.Properties + +interface KonanLibraryReader { + + val libraryFile: File + val libraryName: String + + val manifestProperties: Properties + val uniqueName: String + val linkerOpts: List + val unresolvedDependencies: List + val bitcodePaths: List + val includedPaths: List + + val dataFlowGraph: ByteArray? + val moduleHeaderData: ByteArray + fun packageMetadata(fqName: String): ByteArray + + val isDefaultLibrary: Boolean get() = false + + // FIXME: ddol: to be refactored into some global resolution context + val isNeededForLink: Boolean get() = true + val resolvedDependencies: MutableList + fun markPackageAccessed(fqName: String) +} diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanMetadataReader.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanMetadataReader.kt new file mode 100644 index 00000000000..e6f0b43c0e2 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/KonanMetadataReader.kt @@ -0,0 +1,6 @@ +package org.jetbrains.kotlin.konan.library + +interface MetadataReader { + fun loadSerializedModule(library: KonanLibrary): ByteArray + fun loadSerializedPackageFragment(library: KonanLibrary, fqName: String): ByteArray +} diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/DefaultMetadataReaderImpl.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/DefaultMetadataReaderImpl.kt new file mode 100644 index 00000000000..b3bd2b5de05 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/DefaultMetadataReaderImpl.kt @@ -0,0 +1,12 @@ +package org.jetbrains.kotlin.konan.library.impl + +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.MetadataReader + +object DefaultMetadataReaderImpl : MetadataReader { + + override fun loadSerializedModule(library: KonanLibrary): ByteArray = library.moduleHeaderFile.readBytes() + + override fun loadSerializedPackageFragment(library: KonanLibrary, fqName: String): ByteArray = + library.packageFile(fqName).readBytes() +} diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryImpl.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryImpl.kt new file mode 100644 index 00000000000..c5279fc24ca --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryImpl.kt @@ -0,0 +1,85 @@ +package org.jetbrains.kotlin.konan.library.impl + +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent +import org.jetbrains.kotlin.konan.file.* +import org.jetbrains.kotlin.konan.target.KonanTarget + +const val KLIB_FILE_EXTENSION = "klib" +const val KLIB_FILE_EXTENSION_WITH_DOT = ".$KLIB_FILE_EXTENSION" + +class ZippedKonanLibrary(val klibFile: File, override val target: KonanTarget? = null): KonanLibrary { + init { + check(klibFile.exists) { "Could not find $klibFile." } + check(klibFile.isFile) { "Expected $klibFile to be a regular file." } + + val extension = klibFile.extension + check(extension.isEmpty() || extension == KLIB_FILE_EXTENSION) { "Unexpected file extension: $extension" } + } + + override val libraryName = klibFile.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT) + + override val libDir by lazy { klibFile.asZipRoot } + + fun unpackTo(newDir: File) { + if (newDir.exists) { + if (newDir.isDirectory) + newDir.deleteRecursively() + else + newDir.delete() + } + libDir.recursiveCopyTo(newDir) + check(newDir.exists) { "Could not unpack $klibFile as $newDir." } + } +} + +// This class automatically extracts pieces of +// the library on first access. Use it if you need +// to pass extracted files to an external tool. +// Otherwise, stick to ZippedKonanLibrary. +private class FileExtractor(zippedLibrary: KonanLibrary): KonanLibrary by zippedLibrary { + + override val manifestFile: File by lazy { extract(super.manifestFile) } + + override val resourcesDir: File by lazy { extractDir(super.resourcesDir) } + + override val includedDir: File by lazy { extractDir(super.includedDir) } + + override val kotlinDir: File by lazy { extractDir(super.kotlinDir) } + + override val nativeDir: File by lazy { extractDir(super.nativeDir) } + + override val linkdataDir: File by lazy { extractDir(super.linkdataDir) } + + fun extract(file: File): File { + val temporary = createTempFile(file.name) + file.copyTo(temporary) + temporary.deleteOnExit() + return temporary + } + + fun extractDir(directory: File): File { + val temporary = createTempDir(directory.name) + directory.recursiveCopyTo(temporary) + temporary.deleteOnExitRecursively() + return temporary + } +} + +class UnzippedKonanLibrary(override val libDir: File, override val target: KonanTarget? = null): KonanLibrary { + override val libraryName = libDir.path + + val targetList: List by lazy { targetsDir.listFiles.map { it.name } } +} + +fun KonanLibrary(klib: File, target: KonanTarget? = null) = + if (klib.isFile) ZippedKonanLibrary(klib, target) else UnzippedKonanLibrary(klib, target) + +internal val KonanLibrary.realFiles + get() = when (this) { + is ZippedKonanLibrary -> FileExtractor(this) + // Unpacked library just provides its own files. + is UnzippedKonanLibrary -> this + else -> error("Provide an extractor for your container.") + } + diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryReaderImpl.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryReaderImpl.kt new file mode 100644 index 00000000000..9207340ccf2 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/impl/KonanLibraryReaderImpl.kt @@ -0,0 +1,83 @@ +package org.jetbrains.kotlin.konan.library.impl + +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.library.KonanLibraryReader +import org.jetbrains.kotlin.konan.library.MetadataReader +import org.jetbrains.kotlin.konan.properties.Properties +import org.jetbrains.kotlin.konan.properties.loadProperties +import org.jetbrains.kotlin.konan.properties.propertyList +import org.jetbrains.kotlin.konan.properties.propertyString +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions +import org.jetbrains.kotlin.konan.util.substitute +import org.jetbrains.kotlin.serialization.konan.emptyPackages + +class LibraryReaderImpl( + override val libraryFile: File, + val currentAbiVersion: Int, + val target: KonanTarget? = null, + override val isDefaultLibrary: Boolean = false, + private val metadataReader: MetadataReader = DefaultMetadataReaderImpl +) : KonanLibraryReader { + + // For the zipped libraries inPlace gives files from zip file system + // whereas realFiles extracts them to /tmp. + // For unzipped libraries inPlace and realFiles are the same + // providing files in the library directory. + private val inPlace = KonanLibrary(libraryFile, target) + private val realFiles = inPlace.realFiles + + override val manifestProperties: Properties by lazy { + val properties = inPlace.manifestFile.loadProperties() + if (target != null) substitute(properties, defaultTargetSubstitutions(target)) + properties + } + + val abiVersion: String + get() { + val manifestAbiVersion = manifestProperties.getProperty("abi_version") + check("$currentAbiVersion" == manifestAbiVersion) { + "ABI version mismatch. Compiler expects: $currentAbiVersion, the library is $manifestAbiVersion" + } + return manifestAbiVersion + } + + val targetList = inPlace.targetsDir.listFiles.map { it.name } + override val dataFlowGraph by lazy { inPlace.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null } } + + override val libraryName + get() = inPlace.libraryName + + override val uniqueName + get() = manifestProperties.propertyString("unique_name")!! + + override val bitcodePaths: List + get() = (realFiles.kotlinDir.listFilesOrEmpty + realFiles.nativeDir.listFilesOrEmpty).map { it.absolutePath } + + override val includedPaths: List + get() = realFiles.includedDir.listFilesOrEmpty.map { it.absolutePath } + + override val linkerOpts: List + get() = manifestProperties.propertyList("linkerOpts", target!!.visibleName) + + override val unresolvedDependencies: List + get() = manifestProperties.propertyList("depends") + + override val resolvedDependencies = mutableListOf() + + override val moduleHeaderData: ByteArray by lazy { metadataReader.loadSerializedModule(inPlace) } + + override var isNeededForLink: Boolean = false + private set + + private val emptyPackages by lazy { emptyPackages(moduleHeaderData) } + + override fun markPackageAccessed(fqName: String) { + if (!isNeededForLink // fast path + && !emptyPackages.contains(fqName)) { + isNeededForLink = true + } + } + + override fun packageMetadata(fqName: String) = metadataReader.loadSerializedPackageFragment(inPlace, fqName) +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanClassDataFinder.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanClassDataFinder.kt similarity index 57% rename from backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanClassDataFinder.kt rename to extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanClassDataFinder.kt index a9f8d66c27a..e91c8a18c23 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanClassDataFinder.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanClassDataFinder.kt @@ -1,24 +1,8 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.konan.serialization +package org.jetbrains.kotlin.serialization.konan import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.metadata.deserialization.NameResolver +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder @@ -28,19 +12,18 @@ class KonanClassDataFinder( private val fragment: KonanProtoBuf.LinkDataPackageFragment, private val nameResolver: NameResolver ) : ClassDataFinder { + override fun findClassData(classId: ClassId): ClassData? { val proto = fragment.classes - val nameList = proto.getClassNameList() + val nameList = proto.classNameList - val index = nameList.indexOfFirst { - nameResolver.getClassId(it) == classId } + val index = nameList.indexOfFirst { nameResolver.getClassId(it) == classId } if (index == -1) error("Could not find serialized class $classId") val foundClass = proto.getClasses(index) ?: error("Could not find data for serialized class $classId") + /* TODO: binary version supposed to be read from protobuf. */ return ClassData(nameResolver, foundClass, KonanMetadataVersion.INSTANCE, SourceElement.NO_SOURCE) } } - - diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializationUtils.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializationUtils.kt new file mode 100644 index 00000000000..1b085123ee6 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanDeserializationUtils.kt @@ -0,0 +1,11 @@ +package org.jetbrains.kotlin.serialization.konan + +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf + +fun parsePackageFragment(packageData: ByteArray): KonanProtoBuf.LinkDataPackageFragment = + KonanProtoBuf.LinkDataPackageFragment.parseFrom(packageData, KonanSerializerProtocol.extensionRegistry) + +fun parseModuleHeader(libraryData: ByteArray): KonanProtoBuf.LinkDataLibrary = + KonanProtoBuf.LinkDataLibrary.parseFrom(libraryData, KonanSerializerProtocol.extensionRegistry) + +fun emptyPackages(libraryData: ByteArray) = parseModuleHeader(libraryData).emptyPackageList diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanMetadataVersion.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanMetadataVersion.kt new file mode 100644 index 00000000000..0b432d604d1 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanMetadataVersion.kt @@ -0,0 +1,16 @@ +package org.jetbrains.kotlin.serialization.konan + +import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion + +class KonanMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) { + + override fun isCompatible(): Boolean = this.major == 1 && this.minor == 0 + + companion object { + @JvmField + val INSTANCE = KonanMetadataVersion(1, 0, 0) + + @JvmField + val INVALID_VERSION = KonanMetadataVersion() + } +} diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanModuleDescriptorFactory.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanModuleDescriptorFactory.kt new file mode 100644 index 00000000000..81820ab2ccc --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanModuleDescriptorFactory.kt @@ -0,0 +1,139 @@ +package org.jetbrains.kotlin.serialization.konan + +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.createKonanModuleDescriptor +import org.jetbrains.kotlin.descriptors.konan.interop.InteropFqNames +import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.konan.library.KonanLibraryReader +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration +import org.jetbrains.kotlin.serialization.deserialization.* +import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.storage.StorageManager + +// FIXME: ddol: this is a temporary solution, to be refactored into some global resolution context +interface KonanModuleDescriptorFactory { + + fun createModuleDescriptor( + libraryReader: KonanLibraryReader, + specifics: LanguageVersionSettings, + storageManager: StorageManager = LockBasedStorageManager() + ): ModuleDescriptor +} + +object DefaultKonanModuleDescriptorFactory: KonanModuleDescriptorFactory { + + override fun createModuleDescriptor( + libraryReader: KonanLibraryReader, + specifics: LanguageVersionSettings, + storageManager: StorageManager + ): ModuleDescriptorImpl { + + val libraryProto = parseModuleHeader(libraryReader.moduleHeaderData) + + val moduleName = libraryProto.moduleName + + val moduleDescriptor = createKonanModuleDescriptor( + Name.special(moduleName), + storageManager, + origin = DeserializedKonanModuleOrigin(libraryReader) + ) + val deserializationConfiguration = CompilerDeserializationConfiguration(specifics) + + val provider = createPackageFragmentProvider( + libraryReader, + libraryProto.packageFragmentNameList, + storageManager, + moduleDescriptor, + deserializationConfiguration) + + moduleDescriptor.initialize(provider) + + return moduleDescriptor + } + + private fun createPackageFragmentProvider( + libraryReader: KonanLibraryReader, + fragmentNames: List, + storageManager: StorageManager, + moduleDescriptor: ModuleDescriptor, + configuration: DeserializationConfiguration + ): PackageFragmentProvider { + + val deserializedPackageFragments = fragmentNames.map{ + KonanPackageFragment(it, libraryReader, storageManager, moduleDescriptor) + } + + val syntheticPackageFragments = getSyntheticPackageFragments( + libraryReader, + moduleDescriptor, + deserializedPackageFragments) + + val provider = PackageFragmentProviderImpl(deserializedPackageFragments + syntheticPackageFragments) + + val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) + + val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl( + moduleDescriptor, + notFoundClasses, + KonanSerializerProtocol) + + val components = DeserializationComponents( + storageManager, + moduleDescriptor, + configuration, + DeserializedClassDataFinder(provider), + annotationAndConstantLoader, + provider, + LocalClassifierTypeSettings.Default, + ErrorReporter.DO_NOTHING, + LookupTracker.DO_NOTHING, + NullFlexibleTypeDeserializer, + emptyList(), + notFoundClasses, + ContractDeserializer.DEFAULT, + extensionRegistryLite = KonanSerializerProtocol.extensionRegistry) + + for (packageFragment in deserializedPackageFragments) { + packageFragment.initialize(components) + } + + return provider + } + + private fun getSyntheticPackageFragments( + libraryReader: KonanLibraryReader, + moduleDescriptor: ModuleDescriptor, + konanPackageFragments: List + ): List { + + if (libraryReader.manifestProperties.getProperty("interop") != "true") return emptyList() + + val packageFqName = libraryReader.manifestProperties.getProperty("package")?.let { FqName(it) } + ?: error("Inconsistent manifest: interop library ${libraryReader.libraryName} should have `package` specified") + + val exportForwardDeclarations = libraryReader.manifestProperties.getProperty("exportForwardDeclarations") + .split(' ') + .map { it.trim() } + .filter { it.isNotEmpty() } + .map { FqName(it) } + + val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName } + + val result = mutableListOf() + + // Allow references to forwarding declarations to be resolved into classifiers declared in this library: + listOf(InteropFqNames.cNamesStructs, InteropFqNames.objCNamesClasses, InteropFqNames.objCNamesProtocols).mapTo(result) { fqName -> + ClassifierAliasingPackageFragmentDescriptor(interopPackageFragments, moduleDescriptor, fqName) + } + // TODO: use separate namespaces for structs, enums, Objective-C protocols etc. + + result.add(ExportedForwardDeclarationsPackageFragmentDescriptor(moduleDescriptor, packageFqName, exportForwardDeclarations)) + + return result + } +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt similarity index 58% rename from backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt rename to extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt index 5ebc54b5775..5168132d24f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanPackageFragment.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt @@ -1,30 +1,13 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +package org.jetbrains.kotlin.serialization.konan -package org.jetbrains.kotlin.backend.konan.serialization - -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.konan.library.KonanLibraryReader +import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf -import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment -import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl -import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents +import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.serialization.deserialization.getName @@ -33,7 +16,8 @@ import org.jetbrains.kotlin.storage.StorageManager class KonanPackageFragment( val fqNameString: String, val reader: KonanLibraryReader, - storageManager: StorageManager, module: ModuleDescriptor + storageManager: StorageManager, + module: ModuleDescriptor ) : DeserializedPackageFragment(FqName(fqNameString), storageManager, module) { lateinit var components: DeserializationComponents @@ -48,12 +32,11 @@ class KonanPackageFragment( parsePackageFragment(reader.packageMetadata(fqNameString)) } - val proto: KonanProtoBuf.LinkDataPackageFragment get() = protoForNames.also { - reader.markPackageAccessed(fqNameString) - } + val proto: KonanProtoBuf.LinkDataPackageFragment + get() = protoForNames.also { reader.markPackageAccessed(fqNameString) } private val nameResolver by lazy { - NameResolverImpl(protoForNames.getStringTable(), protoForNames.getNameTable()) + NameResolverImpl(protoForNames.stringTable, protoForNames.nameTable) } override val classDataFinder by lazy { @@ -62,14 +45,18 @@ class KonanPackageFragment( private val memberScope_ by lazy { /* TODO: we fake proto binary versioning for now. */ - DeserializedPackageMemberScope(this, proto.getPackage(), - nameResolver, KonanMetadataVersion.INSTANCE,/* containerSource = */ null, - components, { loadClassNames() }) + DeserializedPackageMemberScope( + this, + proto.getPackage(), + nameResolver, + KonanMetadataVersion.INSTANCE, + /* containerSource = */ null, + components) { loadClassNames() } } override fun getMemberScope(): DeserializedPackageMemberScope = memberScope_ - private val classifierNames by lazy { + private val classifierNames: Set by lazy { val result = mutableSetOf() result.addAll(loadClassNames()) protoForNames.getPackage().typeAliasList.mapTo(result) { nameResolver.getName(it.name) } @@ -80,15 +67,14 @@ class KonanPackageFragment( private fun loadClassNames(): Collection { - val classNameList = protoForNames.getClasses().getClassNameList() + val classNameList = protoForNames.classes.classNameList - val names = classNameList.mapNotNull { + val names = classNameList.mapNotNull { val classId = nameResolver.getClassId(it) - val shortName = classId.getShortClassName() + val shortName = classId.shortClassName if (!classId.isNestedClass) shortName else null - } + } - return names + return names } } - diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanSerializerProtocol.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanSerializerProtocol.kt new file mode 100644 index 00000000000..df68bd79ef2 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanSerializerProtocol.kt @@ -0,0 +1,19 @@ +package org.jetbrains.kotlin.serialization.konan + +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf +import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite +import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol + +object KonanSerializerProtocol : SerializerExtensionProtocol( + ExtensionRegistryLite.newInstance().apply { KonanProtoBuf.registerAllExtensions(this) }, + KonanProtoBuf.packageFqName, + KonanProtoBuf.constructorAnnotation, + KonanProtoBuf.classAnnotation, + KonanProtoBuf.functionAnnotation, + KonanProtoBuf.propertyAnnotation, + KonanProtoBuf.enumEntryAnnotation, + KonanProtoBuf.compileTimeValue, + KonanProtoBuf.parameterAnnotation, + KonanProtoBuf.typeAnnotation, + KonanProtoBuf.typeParameterAnnotation +) diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/NullFlexibleTypeDeserializer.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/NullFlexibleTypeDeserializer.kt new file mode 100644 index 00000000000..bd66919af48 --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/NullFlexibleTypeDeserializer.kt @@ -0,0 +1,14 @@ +package org.jetbrains.kotlin.serialization.konan + +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer +import org.jetbrains.kotlin.types.SimpleType + +object NullFlexibleTypeDeserializer : FlexibleTypeDeserializer { + + override fun create( + proto: ProtoBuf.Type, + flexibleId: String, + lowerBound: SimpleType, + upperBound: SimpleType) = error("Illegal use of flexible type deserializer.") +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SyntheticPackageFragmentDescriptors.kt similarity index 72% rename from backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt rename to extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SyntheticPackageFragmentDescriptors.kt index ef403a78c69..7c4baaa7682 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/InteropDescriptors.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SyntheticPackageFragmentDescriptors.kt @@ -1,22 +1,5 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +package org.jetbrains.kotlin.serialization.konan -package org.jetbrains.kotlin.backend.konan.descriptors - -import org.jetbrains.kotlin.backend.konan.serialization.KonanPackageFragment import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl @@ -33,7 +16,9 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult * redirect "$pkg.$name" to e.g. "cnames.structs.$name". */ class ExportedForwardDeclarationsPackageFragmentDescriptor( - module: ModuleDescriptor, fqName: FqName, declarations: List + module: ModuleDescriptor, + fqName: FqName, + declarations: List ) : PackageFragmentDescriptorImpl(module, fqName) { private val memberScope = object : MemberScopeImpl() { @@ -51,7 +36,7 @@ class ExportedForwardDeclarationsPackageFragmentDescriptor( p.println(this::class.java.simpleName, " {") p.pushIndent() - // TODO + p.println("declarations = $declarations") p.popIndent() p.println("}") @@ -66,7 +51,9 @@ class ExportedForwardDeclarationsPackageFragmentDescriptor( * The package fragment that redirects all requests for classifier lookup to its targets. */ class ClassifierAliasingPackageFragmentDescriptor( - targets: List, module: ModuleDescriptor, fqName: FqName + targets: List, + module: ModuleDescriptor, + fqName: FqName ) : PackageFragmentDescriptorImpl(module, fqName) { private val memberScope = object : MemberScopeImpl() { @@ -84,7 +71,7 @@ class ClassifierAliasingPackageFragmentDescriptor( p.println(this::class.java.simpleName, " {") p.pushIndent() - p.println("targets = " + targets) + p.println("targets = $targets") p.popIndent() p.println("}") diff --git a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt index b8b6eda0268..e1cc29c6f48 100644 --- a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt +++ b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt @@ -17,10 +17,7 @@ package org.jetbrains.kotlin.cli.klib // TODO: Extract `library` package as a shared jar? -import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl -import org.jetbrains.kotlin.backend.konan.library.impl.UnzippedKonanLibrary -import org.jetbrains.kotlin.backend.konan.library.impl.ZippedKonanLibrary -import org.jetbrains.kotlin.backend.konan.serialization.parseModuleHeader +import org.jetbrains.kotlin.backend.konan.library.KONAN_CURRENT_ABI_VERSION import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl @@ -28,10 +25,16 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.konan.isKonanStdlib import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.library.KonanLibrarySearchPathResolver +import org.jetbrains.kotlin.konan.library.impl.KLIB_FILE_EXTENSION_WITH_DOT +import org.jetbrains.kotlin.konan.library.impl.LibraryReaderImpl +import org.jetbrains.kotlin.konan.library.impl.UnzippedKonanLibrary +import org.jetbrains.kotlin.konan.library.impl.ZippedKonanLibrary import org.jetbrains.kotlin.konan.target.Distribution import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.konan.util.DependencyProcessor import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf +import org.jetbrains.kotlin.serialization.konan.DefaultKonanModuleDescriptorFactory +import org.jetbrains.kotlin.serialization.konan.parseModuleHeader import java.lang.System.out import kotlin.system.exitProcess @@ -117,7 +120,7 @@ class Library(val name: String, val requestedRepository: String?, val target: St } fun install() { - Library(File(name).name.removeSuffix(".klib"), requestedRepository, target).remove(true) + Library(File(name).name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT), requestedRepository, target).remove(true) val library = ZippedKonanLibrary(libraryInCurrentDir(name)) val newLibDir = File(repository, library.libraryName.File().name) @@ -144,7 +147,7 @@ class Library(val name: String, val requestedRepository: String?, val target: St fun contents(output: Appendable = out) { val reader = LibraryReaderImpl(libraryInRepoOrCurrentDir(repository, name), currentAbiVersion) val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion) - val module = reader.moduleDescriptor(versionSpec) + val module = DefaultKonanModuleDescriptorFactory.createModuleDescriptor(reader, versionSpec) val defaultModules = mutableListOf() if (!module.isKonanStdlib()) { val resolver = KonanLibrarySearchPathResolver(emptyList(), @@ -154,7 +157,8 @@ class Library(val name: String, val requestedRepository: String?, val target: St skipCurrentDir = true) resolver.defaultLinks(false, true) .mapTo(defaultModules) { - LibraryReaderImpl(it, currentAbiVersion).moduleDescriptor(versionSpec) + DefaultKonanModuleDescriptorFactory.createModuleDescriptor( + LibraryReaderImpl(it, currentAbiVersion), versionSpec) } } @@ -166,8 +170,7 @@ class Library(val name: String, val requestedRepository: String?, val target: St } } -// TODO: need to do something here. -val currentAbiVersion = 1 +val currentAbiVersion = KONAN_CURRENT_ABI_VERSION val currentLanguageVersion = LanguageVersion.LATEST_STABLE val currentApiVersion = ApiVersion.LATEST_STABLE diff --git a/settings.gradle b/settings.gradle index 28126975131..5f57f3c244b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -35,7 +35,7 @@ include ':platformLibs' includeBuild 'shared' includeBuild 'extracted/konan.descriptors' includeBuild 'extracted/konan.metadata' -includeBuild 'extracted/konan.metadata.serializer' +includeBuild 'extracted/konan.serializer' includeBuild 'tools/kotlin-native-gradle-plugin' if (hasProperty("kotlinProjectPath")) { diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt index d6cb3510dcb..170b8f68422 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt @@ -37,6 +37,8 @@ data class File constructor(internal val javaPath: Path) { get() = File(absolutePath) val name: String get() = javaPath.fileName.toString() + val extension: String + get() = name.substringAfterLast('.', "") val parent: String get() = javaPath.parent.toString() val parentFile: File diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt index 2a76ea72cbc..8c70ecb270b 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.konan.util.suffixIfNot interface SearchPathResolver { val searchRoots: List fun resolve(givenPath: String): File - fun defaultLinks(nostdlib: Boolean, noDefaultLibs: Boolean): List + fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List } fun defaultResolver(repositories: List, target: KonanTarget): SearchPathResolver = @@ -30,7 +30,7 @@ class KonanLibrarySearchPathResolver( val distributionKlib: String?, val localKonanDir: String?, val skipCurrentDir: Boolean = false -): SearchPathResolver { +) : SearchPathResolver { val localHead: File? get() = localKonanDir?.File()?.klib @@ -45,7 +45,7 @@ class KonanLibrarySearchPathResolver( get() = if (!skipCurrentDir) File.userDir else null private val repoRoots: List by lazy { - repositories.map{File(it)} + repositories.map { File(it) } } // This is the place where we specify the order of library search. @@ -69,13 +69,13 @@ class KonanLibrarySearchPathResolver( override fun resolve(givenPath: String): File { val given = File(givenPath) if (given.isAbsolute) { - found(given)?.apply{ return this } + found(given)?.apply { return this } } else { - searchRoots.forEach{ - found(File(it, givenPath))?.apply{return this} + searchRoots.forEach { + found(File(it, givenPath))?.apply { return this } } } - error("Could not find \"$givenPath\" in ${searchRoots.map{it.absolutePath}}.") + error("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.") } private val File.klib @@ -83,17 +83,23 @@ class KonanLibrarySearchPathResolver( // The libraries from the default root are linked automatically. val defaultRoots: List - get() = listOf(distHead, distPlatformHead) - .filterNotNull() - .filter{ it.exists } + get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists } + + override fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List { - override fun defaultLinks(nostdlib: Boolean, noDefaultLibs: Boolean): List { - val defaultLibs = defaultRoots.flatMap{ it.listFiles } - .filterNot { it.name.removeSuffixIfPresent(".klib") == "stdlib" } - .map { File(it.absolutePath) } val result = mutableListOf() - if (!nostdlib) result.add(resolve("stdlib")) - if (!noDefaultLibs) result.addAll(defaultLibs) + + if (!noStdLib) { + result.add(resolve("stdlib")) + } + + if (!noDefaultLibs) { + val defaultLibs = defaultRoots.flatMap { it.listFiles } + .filterNot { it.name.removeSuffixIfPresent(".klib") == "stdlib" } + .map { File(it.absolutePath) } + result.addAll(defaultLibs) + } + return result } } diff --git a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt index 97518c68c18..2df9eef06c9 100644 --- a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt +++ b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt @@ -16,12 +16,9 @@ package org.jetbrains.kotlin.cli.utilities -import org.jetbrains.kotlin.backend.konan.library.impl.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.resolveLibrariesRecursive -import org.jetbrains.kotlin.konan.TempFiles import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.library.defaultResolver -import org.jetbrains.kotlin.konan.properties.loadProperties import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.native.interop.gen.jvm.interop import org.jetbrains.kotlin.utils.addIfNotNull @@ -75,8 +72,7 @@ fun invokeInterop(flavor: String, args: Array): Array { ) val importArgs = allLibraries.flatMap { - val library = KonanLibrary(it.libraryFile) - val manifestProperties = library.manifestFile.loadProperties() + val manifestProperties = it.manifestProperties // TODO: handle missing properties? manifestProperties["package"]?.let { val pkg = it as String