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
This commit is contained in:
Dmitriy Dolovov
2018-08-22 14:01:20 +03:00
committed by GitHub
parent 0f00b39fda
commit f0cfbb9918
47 changed files with 610 additions and 720 deletions
+2 -1
View File
@@ -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
@@ -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<K2NativeCompilerArguments>() {
@@ -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<KonanPackageFragment>
): List<PackageFragmentDescriptor>
}
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<FqName>
) : InteropLibrary {
override fun createSyntheticPackages(
module: ModuleDescriptor,
konanPackageFragments: List<KonanPackageFragment>
): List<PackageFragmentDescriptor> {
val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName }
val result = mutableListOf<PackageFragmentDescriptor>()
// 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
}
}
@@ -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<LibraryReaderImpl> by lazy {
internal val immediateLibraries: List<KonanLibraryReader> 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 <T: KonanLibraryReader> List<T>.purgeUnneeded(config: KonanConfig): List<T> =
this.filter{ (!it.isDefaultLibrary && !config.purgeUserLibs) || it.isNeededForLink }
@@ -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
}
@@ -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<String>
val includedPaths: List<String>
val linkerOpts: List<String>
val unresolvedDependencies: List<String>
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
}
@@ -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)
@@ -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<String>,
target: KonanTarget,
abiVersion: Int = 1,
abiVersion: Int = KONAN_CURRENT_ABI_VERSION,
noStdLib: Boolean = false,
noDefaultLibs: Boolean = false,
logger: ((String) -> Unit)?): List<LibraryReaderImpl> {
logger: ((String) -> Unit)?): List<KonanLibraryReader> {
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<String>,
return resolvedLibraries.distinctBy { it.libraryFile.absolutePath }
}
private fun warnOnLibraryDuplicates(resolvedLibraries: List<File>,
logger: ((String) -> Unit)? ) {
private fun warnOnLibraryDuplicates(resolvedLibraries: List<File>, logger: ((String) -> Unit)? ) {
if (logger == null) return
@@ -56,38 +62,46 @@ private fun warnOnLibraryDuplicates(resolvedLibraries: List<File>,
}
}
fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<LibraryReaderImpl>,
/**
* For each of the given [immediateLibraries] fills in `resolvedDependencies` field with the
* [KonanLibraryReader]s the library !!directly!! depends on.
*/
fun SearchPathResolver.resolveLibrariesRecursive(immediateLibraries: List<KonanLibraryReader>,
target: KonanTarget,
abiVersion: Int) {
val cache = mutableMapOf<File, LibraryReaderImpl>()
val cache = mutableMapOf<File, KonanLibraryReader>()
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<LibraryReaderImpl>.withResolvedDependencies(): List<LibraryReaderImpl> {
val result = mutableSetOf<LibraryReaderImpl>()
/**
* 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<KonanLibraryReader>.withResolvedDependencies(): List<KonanLibraryReader> {
val result = mutableSetOf<KonanLibraryReader>()
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<LibraryReaderImpl>.withResolvedDependencies(): List<LibraryReaderImpl>
fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List<String>,
target: KonanTarget,
abiVersion: Int = 1,
abiVersion: Int = KONAN_CURRENT_ABI_VERSION,
noStdLib: Boolean = false,
noDefaultLibs: Boolean = false): List<LibraryReaderImpl> {
noDefaultLibs: Boolean = false): List<KonanLibraryReader> {
val immediateLibraries = resolveImmediateLibraries(
libraryNames = libraryNames,
target = target,
@@ -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<String> 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.")
}
@@ -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<String>
get() = (realFiles.kotlinDir.listFilesOrEmpty + realFiles.nativeDir.listFilesOrEmpty)
.map { it.absolutePath }
override val includedPaths: List<String>
get() = (realFiles.includedDir.listFilesOrEmpty).map { it.absolutePath }
override val linkerOpts: List<String>
get() = manifestProperties.propertyList("linkerOpts", target!!.visibleName)
override val unresolvedDependencies: List<String>
get() = manifestProperties.propertyList("depends")
val resolvedDependencies = mutableListOf<LibraryReaderImpl>()
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 <T: KonanLibraryReader> List<T>.purgeUnneeded(config: KonanConfig): List<T> =
this.filter{ (!it.isDefaultLibrary && !config.purgeUserLibs) || it.isNeededForLink }
@@ -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.*
@@ -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()
}
@@ -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 {
@@ -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
@@ -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<LibraryReaderImpl>()
private val usedLibraries = mutableSetOf<KonanLibraryReader>()
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<LibraryReaderImpl>.topoSort(): List<LibraryReaderImpl> {
var sorted = mutableListOf<LibraryReaderImpl>()
val visited = mutableSetOf<LibraryReaderImpl>()
val tempMarks = mutableSetOf<LibraryReaderImpl>()
private fun List<KonanLibraryReader>.topoSort(): List<KonanLibraryReader> {
var sorted = mutableListOf<KonanLibraryReader>()
val visited = mutableSetOf<KonanLibraryReader>()
val tempMarks = mutableSetOf<KonanLibraryReader>()
fun visit(node: LibraryReaderImpl, result: MutableList<LibraryReaderImpl>) {
fun visit(node: KonanLibraryReader, result: MutableList<KonanLibraryReader>) {
if (visited.contains(node)) return
if (tempMarks.contains(node)) error("Cyclic dependency in library graph.")
tempMarks.add(node)
@@ -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)
@@ -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
@@ -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()
}
}
@@ -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<String>,
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)
@@ -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
@@ -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.
@@ -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
+1 -1
View File
@@ -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')
}
+2 -2
View File
@@ -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 \
+2 -2
View File
@@ -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 ^
@@ -1 +0,0 @@
rootProject.name = "konan.metadata.serializer"
@@ -19,7 +19,7 @@ repositories {
sourceSets {
main.kotlin {
srcDir 'src/main/kotlin'
srcDir 'src'
}
}
@@ -0,0 +1 @@
rootProject.name = "konan.serializer"
@@ -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
}
@@ -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<String>
val unresolvedDependencies: List<String>
val bitcodePaths: List<String>
val includedPaths: List<String>
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<KonanLibraryReader>
fun markPackageAccessed(fqName: String)
}
@@ -0,0 +1,6 @@
package org.jetbrains.kotlin.konan.library
interface MetadataReader {
fun loadSerializedModule(library: KonanLibrary): ByteArray
fun loadSerializedPackageFragment(library: KonanLibrary, fqName: String): ByteArray
}
@@ -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()
}
@@ -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<String> 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.")
}
@@ -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<String>
get() = (realFiles.kotlinDir.listFilesOrEmpty + realFiles.nativeDir.listFilesOrEmpty).map { it.absolutePath }
override val includedPaths: List<String>
get() = realFiles.includedDir.listFilesOrEmpty.map { it.absolutePath }
override val linkerOpts: List<String>
get() = manifestProperties.propertyList("linkerOpts", target!!.visibleName)
override val unresolvedDependencies: List<String>
get() = manifestProperties.propertyList("depends")
override val resolvedDependencies = mutableListOf<KonanLibraryReader>()
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)
}
@@ -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)
}
}
@@ -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
@@ -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()
}
}
@@ -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<String>,
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<KonanPackageFragment>
): List<PackageFragmentDescriptor> {
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<PackageFragmentDescriptor>()
// 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
}
}
@@ -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<Name> by lazy {
val result = mutableSetOf<Name>()
result.addAll(loadClassNames())
protoForNames.getPackage().typeAliasList.mapTo(result) { nameResolver.getName(it.name) }
@@ -80,15 +67,14 @@ class KonanPackageFragment(
private fun loadClassNames(): Collection<Name> {
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
}
}
@@ -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
)
@@ -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.")
}
@@ -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<FqName>
module: ModuleDescriptor,
fqName: FqName,
declarations: List<FqName>
) : 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<KonanPackageFragment>, module: ModuleDescriptor, fqName: FqName
targets: List<KonanPackageFragment>,
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("}")
@@ -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<ModuleDescriptorImpl>()
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
+1 -1
View File
@@ -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")) {
@@ -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
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.konan.util.suffixIfNot
interface SearchPathResolver {
val searchRoots: List<File>
fun resolve(givenPath: String): File
fun defaultLinks(nostdlib: Boolean, noDefaultLibs: Boolean): List<File>
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<File>
}
fun defaultResolver(repositories: List<String>, 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<File> 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<File>
get() = listOf(distHead, distPlatformHead)
.filterNotNull()
.filter{ it.exists }
get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists }
override fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<File> {
override fun defaultLinks(nostdlib: Boolean, noDefaultLibs: Boolean): List<File> {
val defaultLibs = defaultRoots.flatMap{ it.listFiles }
.filterNot { it.name.removeSuffixIfPresent(".klib") == "stdlib" }
.map { File(it.absolutePath) }
val result = mutableListOf<File>()
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
}
}
@@ -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<String>): Array<String> {
)
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