KLIB reader: better isolation of implementation details (#1917)
KLIB reader: - better isolation of implementation details - rename entities closer to their meaning: KonanLibrary -> KonanLibraryLayout, KonanLibraryReader -> KonanLibrary
This commit is contained in:
@@ -1,44 +1,64 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
// This scheme describes the Kotlin/Native Library (klib) layout.
|
||||
interface KonanLibraryLayout {
|
||||
const val KLIB_PROPERTY_ABI_VERSION = "abi_version"
|
||||
const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name"
|
||||
const val KLIB_PROPERTY_LINKED_OPTS = "linkerOpts"
|
||||
const val KLIB_PROPERTY_DEPENDS = "depends"
|
||||
const val KLIB_PROPERTY_INTEROP = "interop"
|
||||
const val KLIB_PROPERTY_PACKAGE = "package"
|
||||
const val KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS = "exportForwardDeclarations"
|
||||
const val KLIB_PROPERTY_INCLUDED_HEADERS = "includedHeaders"
|
||||
|
||||
val libDir: File
|
||||
val target: KonanTarget?
|
||||
// This is a default implementation. Can't make it an assignment.
|
||||
get() = null
|
||||
interface KonanLibrary {
|
||||
|
||||
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
|
||||
val libraryFile: File
|
||||
|
||||
// properties:
|
||||
val manifestProperties: Properties
|
||||
val abiVersion: String
|
||||
val linkerOpts: List<String>
|
||||
|
||||
// paths:
|
||||
val bitcodePaths: List<String>
|
||||
val includedPaths: List<String>
|
||||
|
||||
val targetList: List<String>
|
||||
|
||||
val dataFlowGraph: ByteArray?
|
||||
val moduleHeaderData: ByteArray
|
||||
fun packageMetadata(fqName: String): ByteArray
|
||||
|
||||
// FIXME: ddol: to be refactored into some global resolution context
|
||||
val isDefaultLibrary: Boolean get() = false
|
||||
val isNeededForLink: Boolean get() = true
|
||||
val resolvedDependencies: MutableList<KonanLibrary>
|
||||
fun markPackageAccessed(fqName: String)
|
||||
}
|
||||
|
||||
val KonanLibrary.uniqueName
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)!!
|
||||
|
||||
val KonanLibrary.unresolvedDependencies: List<String>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS)
|
||||
|
||||
val KonanLibrary.isInterop
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_INTEROP) == "true"
|
||||
|
||||
val KonanLibrary.packageFqName
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_PACKAGE)?.let { FqName(it) }
|
||||
|
||||
val KonanLibrary.exportForwardDeclarations
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS)
|
||||
.split(' ')
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
.map { FqName(it) }
|
||||
|
||||
val KonanLibrary.includedHeaders
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_INCLUDED_HEADERS).split(' ')
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
const val KLIB_FILE_EXTENSION = "klib"
|
||||
const val KLIB_FILE_EXTENSION_WITH_DOT = ".$KLIB_FILE_EXTENSION"
|
||||
|
||||
// This scheme describes the Kotlin/Native Library (klib) layout.
|
||||
interface KonanLibraryLayout {
|
||||
|
||||
val libraryName: String
|
||||
|
||||
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")
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
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)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.impl.DefaultMetadataReaderImpl
|
||||
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
|
||||
import org.jetbrains.kotlin.konan.library.impl.zippedKonanLibraryChecks
|
||||
import org.jetbrains.kotlin.konan.library.impl.zippedKonanLibraryRoot
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
fun File.unpackZippedKonanLibraryTo(newDir: File) {
|
||||
|
||||
// first run validity checks for the given KLIB file
|
||||
zippedKonanLibraryChecks(this)
|
||||
|
||||
if (newDir.exists) {
|
||||
if (newDir.isDirectory)
|
||||
newDir.deleteRecursively()
|
||||
else
|
||||
newDir.delete()
|
||||
}
|
||||
|
||||
zippedKonanLibraryRoot(this).recursiveCopyTo(newDir)
|
||||
check(newDir.exists) { "Could not unpack $this as $newDir." }
|
||||
}
|
||||
|
||||
fun createKonanLibraryReader(
|
||||
libraryFile: File,
|
||||
currentAbiVersion: Int,
|
||||
target: KonanTarget? = null,
|
||||
isDefaultLibrary: Boolean = false,
|
||||
metadataReader: MetadataReader = DefaultMetadataReaderImpl
|
||||
): KonanLibrary = KonanLibraryImpl(libraryFile, currentAbiVersion, target, isDefaultLibrary, metadataReader)
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
interface MetadataReader {
|
||||
fun loadSerializedModule(library: KonanLibrary): ByteArray
|
||||
fun loadSerializedPackageFragment(library: KonanLibrary, fqName: String): ByteArray
|
||||
fun loadSerializedModule(libraryLayout: KonanLibraryLayout): ByteArray
|
||||
fun loadSerializedPackageFragment(libraryLayout: KonanLibraryLayout, fqName: String): ByteArray
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,12 +1,13 @@
|
||||
package org.jetbrains.kotlin.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||
import org.jetbrains.kotlin.konan.library.MetadataReader
|
||||
|
||||
object DefaultMetadataReaderImpl : MetadataReader {
|
||||
internal object DefaultMetadataReaderImpl : MetadataReader {
|
||||
|
||||
override fun loadSerializedModule(library: KonanLibrary): ByteArray = library.moduleHeaderFile.readBytes()
|
||||
override fun loadSerializedModule(libraryLayout: KonanLibraryLayout): ByteArray =
|
||||
libraryLayout.moduleHeaderFile.readBytes()
|
||||
|
||||
override fun loadSerializedPackageFragment(library: KonanLibrary, fqName: String): ByteArray =
|
||||
library.packageFile(fqName).readBytes()
|
||||
override fun loadSerializedPackageFragment(libraryLayout: KonanLibraryLayout, fqName: String): ByteArray =
|
||||
libraryLayout.packageFile(fqName).readBytes()
|
||||
}
|
||||
|
||||
+67
-73
@@ -1,85 +1,79 @@
|
||||
package org.jetbrains.kotlin.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.KLIB_PROPERTY_ABI_VERSION
|
||||
import org.jetbrains.kotlin.konan.library.KLIB_PROPERTY_LINKED_OPTS
|
||||
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.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.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions
|
||||
import org.jetbrains.kotlin.konan.util.substitute
|
||||
import org.jetbrains.kotlin.serialization.konan.emptyPackages
|
||||
|
||||
const val KLIB_FILE_EXTENSION = "klib"
|
||||
const val KLIB_FILE_EXTENSION_WITH_DOT = ".$KLIB_FILE_EXTENSION"
|
||||
internal class KonanLibraryImpl(
|
||||
override val libraryFile: File,
|
||||
private val currentAbiVersion: Int,
|
||||
internal val target: KonanTarget?,
|
||||
override val isDefaultLibrary: Boolean,
|
||||
private val metadataReader: MetadataReader
|
||||
) : KonanLibrary {
|
||||
|
||||
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." }
|
||||
// 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 = createKonanLibraryLayout(libraryFile, target)
|
||||
private val realFiles = inPlace.realFiles
|
||||
|
||||
val extension = klibFile.extension
|
||||
check(extension.isEmpty() || extension == KLIB_FILE_EXTENSION) { "Unexpected file extension: $extension" }
|
||||
override val libraryName
|
||||
get() = inPlace.libraryName
|
||||
|
||||
override val manifestProperties: Properties by lazy {
|
||||
val properties = inPlace.manifestFile.loadProperties()
|
||||
if (target != null) substitute(properties, defaultTargetSubstitutions(target))
|
||||
properties
|
||||
}
|
||||
|
||||
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()
|
||||
override val abiVersion: String
|
||||
get() {
|
||||
val manifestAbiVersion = manifestProperties.getProperty(KLIB_PROPERTY_ABI_VERSION)
|
||||
check(currentAbiVersion.toString() == manifestAbiVersion) {
|
||||
"ABI version mismatch. Compiler expects: $currentAbiVersion, the library is $manifestAbiVersion"
|
||||
}
|
||||
return manifestAbiVersion
|
||||
}
|
||||
|
||||
override val linkerOpts: List<String>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_LINKED_OPTS, target!!.visibleName)
|
||||
|
||||
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 targetList by lazy { inPlace.targetsDir.listFiles.map { it.name } }
|
||||
|
||||
override val dataFlowGraph by lazy { inPlace.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null } }
|
||||
|
||||
override val moduleHeaderData: ByteArray by lazy { metadataReader.loadSerializedModule(inPlace) }
|
||||
|
||||
override fun packageMetadata(fqName: String) = metadataReader.loadSerializedPackageFragment(inPlace, fqName)
|
||||
|
||||
override var isNeededForLink: Boolean = false
|
||||
private set
|
||||
|
||||
override val resolvedDependencies = mutableListOf<KonanLibrary>()
|
||||
|
||||
override fun markPackageAccessed(fqName: String) {
|
||||
if (!isNeededForLink // fast path
|
||||
&& !emptyPackages.contains(fqName)) {
|
||||
isNeededForLink = true
|
||||
}
|
||||
libDir.recursiveCopyTo(newDir)
|
||||
check(newDir.exists) { "Could not unpack $klibFile as $newDir." }
|
||||
}
|
||||
|
||||
private val emptyPackages by lazy { emptyPackages(moduleHeaderData) }
|
||||
}
|
||||
|
||||
// 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.")
|
||||
}
|
||||
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package org.jetbrains.kotlin.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.file.asZipRoot
|
||||
import org.jetbrains.kotlin.konan.file.createTempDir
|
||||
import org.jetbrains.kotlin.konan.file.createTempFile
|
||||
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION_WITH_DOT
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent
|
||||
|
||||
private class ZippedKonanLibraryLayout(val klibFile: File, override val target: KonanTarget? = null): KonanLibraryLayout {
|
||||
|
||||
init { zippedKonanLibraryChecks(klibFile) }
|
||||
|
||||
override val libraryName = klibFile.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT)
|
||||
|
||||
override val libDir by lazy { zippedKonanLibraryRoot(klibFile) }
|
||||
}
|
||||
|
||||
internal fun zippedKonanLibraryChecks(klibFile: File) {
|
||||
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" }
|
||||
}
|
||||
|
||||
internal fun zippedKonanLibraryRoot(klibFile: File) = klibFile.asZipRoot
|
||||
|
||||
private class UnzippedKonanLibraryLayout(override val libDir: File, override val target: KonanTarget? = null): KonanLibraryLayout {
|
||||
override val libraryName = libDir.path
|
||||
}
|
||||
|
||||
// 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(zippedLibraryLayout: KonanLibraryLayout): KonanLibraryLayout by zippedLibraryLayout {
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createKonanLibraryLayout(klib: File, target: KonanTarget? = null) =
|
||||
if (klib.isFile) ZippedKonanLibraryLayout(klib, target) else UnzippedKonanLibraryLayout(klib, target)
|
||||
|
||||
internal val KonanLibraryLayout.realFiles
|
||||
get() = when (this) {
|
||||
is ZippedKonanLibraryLayout -> FileExtractor(this)
|
||||
// Unpacked library just provides its own files.
|
||||
is UnzippedKonanLibraryLayout -> this
|
||||
else -> error("Provide an extractor for your container.")
|
||||
}
|
||||
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
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)
|
||||
}
|
||||
+11
-13
@@ -7,8 +7,10 @@ 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.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.exportForwardDeclarations
|
||||
import org.jetbrains.kotlin.konan.library.isInterop
|
||||
import org.jetbrains.kotlin.konan.library.packageFqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||
@@ -19,7 +21,7 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
interface KonanModuleDescriptorFactory {
|
||||
|
||||
fun createModuleDescriptor(
|
||||
libraryReader: KonanLibraryReader,
|
||||
libraryReader: KonanLibrary,
|
||||
specifics: LanguageVersionSettings,
|
||||
storageManager: StorageManager = LockBasedStorageManager()
|
||||
): ModuleDescriptor
|
||||
@@ -28,7 +30,7 @@ interface KonanModuleDescriptorFactory {
|
||||
object DefaultKonanModuleDescriptorFactory: KonanModuleDescriptorFactory {
|
||||
|
||||
override fun createModuleDescriptor(
|
||||
libraryReader: KonanLibraryReader,
|
||||
libraryReader: KonanLibrary,
|
||||
specifics: LanguageVersionSettings,
|
||||
storageManager: StorageManager
|
||||
): ModuleDescriptorImpl {
|
||||
@@ -57,7 +59,7 @@ object DefaultKonanModuleDescriptorFactory: KonanModuleDescriptorFactory {
|
||||
}
|
||||
|
||||
private fun createPackageFragmentProvider(
|
||||
libraryReader: KonanLibraryReader,
|
||||
libraryReader: KonanLibrary,
|
||||
fragmentNames: List<String>,
|
||||
storageManager: StorageManager,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
@@ -106,21 +108,17 @@ object DefaultKonanModuleDescriptorFactory: KonanModuleDescriptorFactory {
|
||||
}
|
||||
|
||||
private fun getSyntheticPackageFragments(
|
||||
libraryReader: KonanLibraryReader,
|
||||
libraryReader: KonanLibrary,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
konanPackageFragments: List<KonanPackageFragment>
|
||||
): List<PackageFragmentDescriptor> {
|
||||
|
||||
if (libraryReader.manifestProperties.getProperty("interop") != "true") return emptyList()
|
||||
if (!libraryReader.isInterop) return emptyList()
|
||||
|
||||
val packageFqName = libraryReader.manifestProperties.getProperty("package")?.let { FqName(it) }
|
||||
val packageFqName = libraryReader.packageFqName
|
||||
?: 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 exportForwardDeclarations = libraryReader.exportForwardDeclarations
|
||||
|
||||
val interopPackageFragments = konanPackageFragments.filter { it.fqName == packageFqName }
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package org.jetbrains.kotlin.serialization.konan
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
class KonanPackageFragment(
|
||||
val fqNameString: String,
|
||||
val reader: KonanLibraryReader,
|
||||
val reader: KonanLibrary,
|
||||
storageManager: StorageManager,
|
||||
module: ModuleDescriptor
|
||||
) : DeserializedPackageFragment(FqName(fqNameString), storageManager, module) {
|
||||
|
||||
Reference in New Issue
Block a user