Provided library versioning in klib. (#2038)
* Provided library versioning in klib. * A test for library mismatch messages.
This commit is contained in:
committed by
Dmitriy Dolovov
parent
d406b1b16d
commit
27ce3b194d
@@ -24,10 +24,11 @@ import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
|||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
import org.jetbrains.kotlin.konan.KonanVersion
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
import org.jetbrains.kotlin.konan.util.profile
|
import org.jetbrains.kotlin.konan.util.*
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||||
@@ -142,7 +143,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
val outputKind = CompilerOutputKind.valueOf(
|
val outputKind = CompilerOutputKind.valueOf(
|
||||||
(arguments.produce ?: "program").toUpperCase())
|
(arguments.produce ?: "program").toUpperCase())
|
||||||
put(PRODUCE, outputKind)
|
put(PRODUCE, outputKind)
|
||||||
put(ABI_VERSION, 1)
|
arguments.libraryVersion ?. let { put(LIBRARY_VERSION, it) }
|
||||||
|
|
||||||
arguments.mainPackage ?.let{ put(ENTRY, it) }
|
arguments.mainPackage ?.let{ put(ENTRY, it) }
|
||||||
arguments.manifestFile ?.let{ put(MANIFEST_FILE, it) }
|
arguments.manifestFile ?.let{ put(MANIFEST_FILE, it) }
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
|||||||
@Argument(value = "-library", shortName = "-l", valueDescription = "<path>", description = "Link with the library")
|
@Argument(value = "-library", shortName = "-l", valueDescription = "<path>", description = "Link with the library")
|
||||||
var libraries: Array<String>? = null
|
var libraries: Array<String>? = null
|
||||||
|
|
||||||
|
@Argument(value = "-library-version", shortName = "-lv", valueDescription = "<version>", description = "Set library version")
|
||||||
|
var libraryVersion: String? = null
|
||||||
|
|
||||||
@Argument(value = "-list-targets", deprecatedName = "-list_targets", description = "List available hardware targets")
|
@Argument(value = "-list-targets", deprecatedName = "-list_targets", description = "List available hardware targets")
|
||||||
var listTargets: Boolean = false
|
var listTargets: Boolean = false
|
||||||
|
|
||||||
|
|||||||
+10
-3
@@ -8,6 +8,9 @@ import llvm.LLVMLinkModules2
|
|||||||
import llvm.LLVMWriteBitcodeToFile
|
import llvm.LLVMWriteBitcodeToFile
|
||||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||||
|
|
||||||
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
||||||
@@ -62,17 +65,21 @@ internal fun produceOutput(context: Context, phaser: PhaseManager) {
|
|||||||
val libraryName = context.config.moduleId
|
val libraryName = context.config.moduleId
|
||||||
val neededLibraries
|
val neededLibraries
|
||||||
= context.llvm.librariesForLibraryManifest
|
= context.llvm.librariesForLibraryManifest
|
||||||
val abiVersion = context.config.currentAbiVersion
|
val abiVersion = KonanAbiVersion.CURRENT
|
||||||
|
val compilerVersion = KonanVersion.CURRENT
|
||||||
|
val libraryVersion = config.get(KonanConfigKeys.LIBRARY_VERSION)
|
||||||
|
val versions = KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion)
|
||||||
val target = context.config.target
|
val target = context.config.target
|
||||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||||
val manifestProperties = context.config.manifestProperties
|
val manifestProperties = context.config.manifestProperties
|
||||||
|
|
||||||
|
|
||||||
val library = buildLibrary(
|
val library = buildLibrary(
|
||||||
context.config.nativeLibraries,
|
context.config.nativeLibraries,
|
||||||
context.config.includeBinaries,
|
context.config.includeBinaries,
|
||||||
neededLibraries,
|
neededLibraries,
|
||||||
context.serializedLinkData!!,
|
context.serializedLinkData!!,
|
||||||
abiVersion,
|
versions,
|
||||||
target,
|
target,
|
||||||
output,
|
output,
|
||||||
libraryName,
|
libraryName,
|
||||||
|
|||||||
+10
-6
@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.konan.library.defaultResolver
|
|||||||
import org.jetbrains.kotlin.konan.library.libraryResolver
|
import org.jetbrains.kotlin.konan.library.libraryResolver
|
||||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||||
import org.jetbrains.kotlin.konan.target.*
|
import org.jetbrains.kotlin.konan.target.*
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
import org.jetbrains.kotlin.konan.library.toUnresolvedLibraries
|
||||||
|
|
||||||
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||||
|
|
||||||
val currentAbiVersion: Int = configuration.get(KonanConfigKeys.ABI_VERSION)!!
|
|
||||||
|
|
||||||
internal val distribution = Distribution(
|
internal val distribution = Distribution(
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
@@ -71,15 +71,18 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
private val libraryNames: List<String>
|
private val libraryNames: List<String>
|
||||||
get() = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
get() = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
||||||
|
|
||||||
|
private val unresolvedLibraries = libraryNames.toUnresolvedLibraries
|
||||||
|
|
||||||
private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES)
|
private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES)
|
||||||
private val resolver = defaultResolver(repositories, target, distribution).libraryResolver(currentAbiVersion)
|
private fun resolverLogger(msg: String) = configuration.report(STRONG_WARNING, msg)
|
||||||
|
|
||||||
|
private val resolver = defaultResolver(repositories, target, distribution, ::resolverLogger).libraryResolver()
|
||||||
|
|
||||||
internal val resolvedLibraries by lazy {
|
internal val resolvedLibraries by lazy {
|
||||||
resolver.resolveWithDependencies(
|
resolver.resolveWithDependencies(
|
||||||
libraryNames,
|
unresolvedLibraries,
|
||||||
noStdLib = configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
|
noStdLib = configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
|
||||||
noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS) ) { msg ->
|
noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS) )
|
||||||
configuration.report(STRONG_WARNING, msg) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List<KonanLibrary> {
|
fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List<KonanLibrary> {
|
||||||
@@ -114,3 +117,4 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
|
|
||||||
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
||||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -12,8 +12,6 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
|||||||
class KonanConfigKeys {
|
class KonanConfigKeys {
|
||||||
companion object {
|
companion object {
|
||||||
// Keep the list lexically sorted.
|
// Keep the list lexically sorted.
|
||||||
val ABI_VERSION: CompilerConfigurationKey<Int>
|
|
||||||
= CompilerConfigurationKey.create("current abi version")
|
|
||||||
val CHECK_DEPENDENCIES: CompilerConfigurationKey<Boolean>
|
val CHECK_DEPENDENCIES: CompilerConfigurationKey<Boolean>
|
||||||
= CompilerConfigurationKey.create("check dependencies and download the missing ones")
|
= CompilerConfigurationKey.create("check dependencies and download the missing ones")
|
||||||
val DEBUG: CompilerConfigurationKey<Boolean>
|
val DEBUG: CompilerConfigurationKey<Boolean>
|
||||||
@@ -26,12 +24,16 @@ class KonanConfigKeys {
|
|||||||
= CompilerConfigurationKey.create("enable backend phases")
|
= CompilerConfigurationKey.create("enable backend phases")
|
||||||
val ENTRY: CompilerConfigurationKey<String?>
|
val ENTRY: CompilerConfigurationKey<String?>
|
||||||
= CompilerConfigurationKey.create("fully qualified main() name")
|
= CompilerConfigurationKey.create("fully qualified main() name")
|
||||||
|
val FRIEND_MODULES: CompilerConfigurationKey<List<String>>
|
||||||
|
= CompilerConfigurationKey.create<List<String>>("friend module paths")
|
||||||
val GENERATE_TEST_RUNNER: CompilerConfigurationKey<Boolean>
|
val GENERATE_TEST_RUNNER: CompilerConfigurationKey<Boolean>
|
||||||
= CompilerConfigurationKey.create("generate test runner")
|
= CompilerConfigurationKey.create("generate test runner")
|
||||||
val INCLUDED_BINARY_FILES: CompilerConfigurationKey<List<String>>
|
val INCLUDED_BINARY_FILES: CompilerConfigurationKey<List<String>>
|
||||||
= CompilerConfigurationKey.create("included binary file paths")
|
= CompilerConfigurationKey.create("included binary file paths")
|
||||||
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
||||||
= CompilerConfigurationKey.create("library file paths")
|
= CompilerConfigurationKey.create("library file paths")
|
||||||
|
val LIBRARY_VERSION: CompilerConfigurationKey<String?>
|
||||||
|
= CompilerConfigurationKey.create("library version")
|
||||||
val LINKER_ARGS: CompilerConfigurationKey<List<String>>
|
val LINKER_ARGS: CompilerConfigurationKey<List<String>>
|
||||||
= CompilerConfigurationKey.create("additional linker arguments")
|
= CompilerConfigurationKey.create("additional linker arguments")
|
||||||
val LIST_PHASES: CompilerConfigurationKey<Boolean>
|
val LIST_PHASES: CompilerConfigurationKey<Boolean>
|
||||||
@@ -94,8 +96,6 @@ class KonanConfigKeys {
|
|||||||
= CompilerConfigurationKey.create("verify ir")
|
= CompilerConfigurationKey.create("verify ir")
|
||||||
val VERBOSE_PHASES: CompilerConfigurationKey<List<String>>
|
val VERBOSE_PHASES: CompilerConfigurationKey<List<String>>
|
||||||
= CompilerConfigurationKey.create("verbose backend phases")
|
= CompilerConfigurationKey.create("verbose backend phases")
|
||||||
val FRIEND_MODULES: CompilerConfigurationKey<List<String>>
|
|
||||||
= CompilerConfigurationKey.create<List<String>>("friend module paths")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -7,11 +7,11 @@ package org.jetbrains.kotlin.backend.konan.library
|
|||||||
|
|
||||||
import llvm.LLVMModuleRef
|
import llvm.LLVMModuleRef
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
import java.util.*
|
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||||
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
const val KLIB_CURRENT_ABI_VERSION = 1
|
|
||||||
|
|
||||||
interface KonanLibraryWriter {
|
interface KonanLibraryWriter {
|
||||||
|
val versions: KonanLibraryVersioning
|
||||||
fun addLinkData(linkData: LinkData)
|
fun addLinkData(linkData: LinkData)
|
||||||
fun addNativeBitcode(library: String)
|
fun addNativeBitcode(library: String)
|
||||||
fun addIncludedBinary(library: String)
|
fun addIncludedBinary(library: String)
|
||||||
|
|||||||
+14
-8
@@ -11,10 +11,11 @@ import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
|||||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||||
import org.jetbrains.kotlin.konan.file.*
|
import org.jetbrains.kotlin.konan.file.*
|
||||||
import org.jetbrains.kotlin.konan.library.*
|
import org.jetbrains.kotlin.konan.library.*
|
||||||
|
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION
|
||||||
import org.jetbrains.kotlin.konan.properties.*
|
import org.jetbrains.kotlin.konan.properties.*
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
|
||||||
abstract class FileBasedLibraryWriter (val file: File, val currentAbiVersion: Int): KonanLibraryWriter
|
abstract class FileBasedLibraryWriter (val file: File): KonanLibraryWriter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requires non-null [target].
|
* Requires non-null [target].
|
||||||
@@ -22,13 +23,13 @@ abstract class FileBasedLibraryWriter (val file: File, val currentAbiVersion: In
|
|||||||
class LibraryWriterImpl(
|
class LibraryWriterImpl(
|
||||||
override val libDir: File,
|
override val libDir: File,
|
||||||
moduleName: String,
|
moduleName: String,
|
||||||
currentAbiVersion: Int,
|
override val versions: KonanLibraryVersioning,
|
||||||
override val target: KonanTarget,
|
override val target: KonanTarget,
|
||||||
val nopack: Boolean = false
|
val nopack: Boolean = false
|
||||||
): FileBasedLibraryWriter(libDir, currentAbiVersion), KonanLibraryLayout {
|
): FileBasedLibraryWriter(libDir), KonanLibraryLayout {
|
||||||
|
|
||||||
constructor(path: String, moduleName: String, currentAbiVersion: Int, target: KonanTarget, nopack: Boolean):
|
constructor(path: String, moduleName: String, versions: KonanLibraryVersioning, target: KonanTarget, nopack: Boolean):
|
||||||
this(File(path), moduleName, currentAbiVersion, target, nopack)
|
this(File(path), moduleName, versions, target, nopack)
|
||||||
|
|
||||||
override val libraryName = libDir.path
|
override val libraryName = libDir.path
|
||||||
val klibFile
|
val klibFile
|
||||||
@@ -53,7 +54,7 @@ class LibraryWriterImpl(
|
|||||||
resourcesDir.mkdirs()
|
resourcesDir.mkdirs()
|
||||||
// TODO: <name>:<hash> will go somewhere around here.
|
// TODO: <name>:<hash> will go somewhere around here.
|
||||||
manifestProperties.setProperty(KLIB_PROPERTY_UNIQUE_NAME, moduleName)
|
manifestProperties.setProperty(KLIB_PROPERTY_UNIQUE_NAME, moduleName)
|
||||||
manifestProperties.setProperty(KLIB_PROPERTY_ABI_VERSION, currentAbiVersion.toString())
|
manifestProperties.writeKonanLibraryVersioning(versions)
|
||||||
}
|
}
|
||||||
|
|
||||||
var llvmModule: LLVMModuleRef? = null
|
var llvmModule: LLVMModuleRef? = null
|
||||||
@@ -85,6 +86,11 @@ class LibraryWriterImpl(
|
|||||||
} else {
|
} else {
|
||||||
val newValue = libraries.joinToString(" ") { it.uniqueName }
|
val newValue = libraries.joinToString(" ") { it.uniqueName }
|
||||||
manifestProperties.setProperty(KLIB_PROPERTY_DEPENDS, newValue)
|
manifestProperties.setProperty(KLIB_PROPERTY_DEPENDS, newValue)
|
||||||
|
libraries.forEach { it ->
|
||||||
|
if (it.versions.libraryVersion != null) {
|
||||||
|
manifestProperties.setProperty("${KLIB_PROPERTY_DEPENDENCY_VERSION}_${it.uniqueName}", it.versions.libraryVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +116,7 @@ internal fun buildLibrary(
|
|||||||
included: List<String>,
|
included: List<String>,
|
||||||
linkDependencies: List<KonanLibrary>,
|
linkDependencies: List<KonanLibrary>,
|
||||||
linkData: LinkData,
|
linkData: LinkData,
|
||||||
abiVersion: Int,
|
versions: KonanLibraryVersioning,
|
||||||
target: KonanTarget,
|
target: KonanTarget,
|
||||||
output: String,
|
output: String,
|
||||||
moduleName: String,
|
moduleName: String,
|
||||||
@@ -119,7 +125,7 @@ internal fun buildLibrary(
|
|||||||
manifestProperties: Properties?,
|
manifestProperties: Properties?,
|
||||||
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
||||||
|
|
||||||
val library = LibraryWriterImpl(output, moduleName, abiVersion, target, nopack)
|
val library = LibraryWriterImpl(File(output), moduleName, versions, target, nopack)
|
||||||
|
|
||||||
library.addKotlinBitcode(llvmModule)
|
library.addKotlinBitcode(llvmModule)
|
||||||
library.addLinkData(linkData)
|
library.addLinkData(linkData)
|
||||||
|
|||||||
@@ -2892,6 +2892,37 @@ task produce_dynamic(type: DynamicKonanTest) {
|
|||||||
"topLevel = 777 3\n"
|
"topLevel = 777 3\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task library_mismatch(type: RunStandaloneKonanTest) {
|
||||||
|
def dir = buildDir.absolutePath
|
||||||
|
def lib = "$projectDir/link/versioning/empty.kt"
|
||||||
|
|
||||||
|
def currentTarget = project.target.name
|
||||||
|
def someOtherTarget = (project.testTarget == 'wasm32' ? project.hostName : 'wasm32')
|
||||||
|
|
||||||
|
if (!useCustomDist) {
|
||||||
|
dependsOn ':wasm32CrossDistRuntime' // we actually need any target other than the current one.
|
||||||
|
}
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
def konancScript = isWindows() ? "konanc.bat" : "konanc"
|
||||||
|
def konanc = "$dist/bin/$konancScript"
|
||||||
|
|
||||||
|
"$konanc $lib -p library -o $dir/1.2/empty -target $currentTarget -lv 1.2".execute().waitFor()
|
||||||
|
"$konanc $lib -p library -o $dir/3.4/empty -target $someOtherTarget".execute().waitFor()
|
||||||
|
"$konanc $lib -p library -o $dir/5.6/empty -target $currentTarget -lv 5.6".execute().waitFor()
|
||||||
|
"$konanc $lib -p library -o $dir/7.8/empty -target $currentTarget -lv 7.8".execute().waitFor()
|
||||||
|
|
||||||
|
}
|
||||||
|
source = "link/versioning/hello.kt"
|
||||||
|
flags = ['-l', 'empty@5.6', '-r', "$dir/1.2", '-r', "$dir/3.4", '-r', "$dir/5.6"]
|
||||||
|
compilerMessages = true
|
||||||
|
def messages =
|
||||||
|
"warning: skipping $dir/1.2/empty.klib. The library versions don't match. Expected '5.6', found '1.2'\n" +
|
||||||
|
"warning: skipping $dir/3.4/empty.klib. The target doesn't match. Expected '$currentTarget', found [$someOtherTarget]\n" +
|
||||||
|
"Hello, versioned world!\n"
|
||||||
|
goldValue = isWindows() ? messages.replaceAll('\\/', '\\\\') : messages
|
||||||
|
}
|
||||||
|
|
||||||
if (isMac() && project.testTarget != 'wasm32') {
|
if (isMac() && project.testTarget != 'wasm32') {
|
||||||
def target = ext.platformManager.targetByName(project.testTarget ?: 'host').name
|
def target = ext.platformManager.targetByName(project.testTarget ?: 'host').name
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/* This file has intentionally been left blank */
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
println("Hello, versioned world!")
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ abstract class KonanTest extends JavaExec {
|
|||||||
boolean enabled = true
|
boolean enabled = true
|
||||||
boolean expectedFail = false
|
boolean expectedFail = false
|
||||||
boolean run = true
|
boolean run = true
|
||||||
|
boolean compilerMessages = false
|
||||||
|
|
||||||
void setDisabled(boolean value) {
|
void setDisabled(boolean value) {
|
||||||
this.enabled = !value
|
this.enabled = !value
|
||||||
@@ -268,6 +269,8 @@ abstract class KonanTest extends JavaExec {
|
|||||||
}
|
}
|
||||||
println "execution: $exe"
|
println "execution: $exe"
|
||||||
|
|
||||||
|
def compilerMessagesText = compilerMessages ? project.file("${program}.compilation.log").getText('UTF-8') : ""
|
||||||
|
|
||||||
def out = new ByteArrayOutputStream()
|
def out = new ByteArrayOutputStream()
|
||||||
//TODO Add test timeout
|
//TODO Add test timeout
|
||||||
ExecResult execResult = project.execute {
|
ExecResult execResult = project.execute {
|
||||||
@@ -284,7 +287,7 @@ abstract class KonanTest extends JavaExec {
|
|||||||
|
|
||||||
ignoreExitValue = true
|
ignoreExitValue = true
|
||||||
}
|
}
|
||||||
def result = out.toString("UTF-8")
|
def result = compilerMessagesText + out.toString("UTF-8")
|
||||||
|
|
||||||
println(result)
|
println(result)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.jetbrains.kotlin.konan.library
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolver
|
||||||
|
import org.jetbrains.kotlin.konan.library.resolver.impl.KonanLibraryResolverImpl
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
|
||||||
|
fun SearchPathResolverWithTarget.libraryResolver(): KonanLibraryResolver =
|
||||||
|
KonanLibraryResolverImpl(this)
|
||||||
+3
-7
@@ -2,23 +2,20 @@ package org.jetbrains.kotlin.konan.library.resolver
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
import org.jetbrains.kotlin.konan.library.SearchPathResolverWithTarget
|
import org.jetbrains.kotlin.konan.library.SearchPathResolverWithTarget
|
||||||
|
import org.jetbrains.kotlin.konan.library.UnresolvedLibrary
|
||||||
typealias DuplicatedLibraryLogger = (String) -> Unit
|
|
||||||
|
|
||||||
interface KonanLibraryResolver {
|
interface KonanLibraryResolver {
|
||||||
|
|
||||||
val searchPathResolver: SearchPathResolverWithTarget
|
val searchPathResolver: SearchPathResolverWithTarget
|
||||||
val abiVersion: Int
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the list of Kotlin/Native library names, ABI version and other parameters
|
* Given the list of Kotlin/Native library names, ABI version and other parameters
|
||||||
* resolves libraries and evaluates dependencies between them.
|
* resolves libraries and evaluates dependencies between them.
|
||||||
*/
|
*/
|
||||||
fun resolveWithDependencies(
|
fun resolveWithDependencies(
|
||||||
libraryNames: List<String>,
|
unresolvedLibraries: List<UnresolvedLibrary>,
|
||||||
noStdLib: Boolean = false,
|
noStdLib: Boolean = false,
|
||||||
noDefaultLibs: Boolean = false,
|
noDefaultLibs: Boolean = false
|
||||||
logger: DuplicatedLibraryLogger? = null
|
|
||||||
): KonanLibraryResolveResult
|
): KonanLibraryResolveResult
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +28,6 @@ interface KonanLibraryResolveResult {
|
|||||||
fun forEach(action: (KonanLibrary, PackageAccessedHandler) -> Unit)
|
fun forEach(action: (KonanLibrary, PackageAccessedHandler) -> Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typealias LibraryOrder = (Iterable<KonanResolvedLibrary>) -> List<KonanResolvedLibrary>
|
typealias LibraryOrder = (Iterable<KonanResolvedLibrary>) -> List<KonanResolvedLibrary>
|
||||||
|
|
||||||
val TopologicalLibraryOrder: LibraryOrder = { input ->
|
val TopologicalLibraryOrder: LibraryOrder = { input ->
|
||||||
|
|||||||
+1
-2
@@ -1,11 +1,10 @@
|
|||||||
package org.jetbrains.kotlin.konan.library.resolver
|
package org.jetbrains.kotlin.konan.library.resolver
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
|
|
||||||
interface PackageAccessedHandler {
|
interface PackageAccessedHandler {
|
||||||
|
|
||||||
fun markPackageAccessed(fqName: FqName)
|
fun markPackageAccessed(fqName: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+25
-31
@@ -1,24 +1,20 @@
|
|||||||
package org.jetbrains.kotlin.konan.library.resolver.impl
|
package org.jetbrains.kotlin.konan.library.resolver.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
import org.jetbrains.kotlin.konan.library.*
|
||||||
import org.jetbrains.kotlin.konan.library.SearchPathResolverWithTarget
|
|
||||||
import org.jetbrains.kotlin.konan.library.createKonanLibrary
|
|
||||||
import org.jetbrains.kotlin.konan.library.resolver.*
|
import org.jetbrains.kotlin.konan.library.resolver.*
|
||||||
import org.jetbrains.kotlin.konan.library.unresolvedDependencies
|
import org.jetbrains.kotlin.konan.util.WithLogger
|
||||||
|
|
||||||
internal class KonanLibraryResolverImpl(
|
internal class KonanLibraryResolverImpl(
|
||||||
override val searchPathResolver: SearchPathResolverWithTarget,
|
override val searchPathResolver: SearchPathResolverWithTarget
|
||||||
override val abiVersion: Int
|
): KonanLibraryResolver, WithLogger by searchPathResolver {
|
||||||
): KonanLibraryResolver {
|
|
||||||
|
|
||||||
override fun resolveWithDependencies(
|
override fun resolveWithDependencies(
|
||||||
libraryNames: List<String>,
|
unresolvedLibraries: List<UnresolvedLibrary>,
|
||||||
noStdLib: Boolean,
|
noStdLib: Boolean,
|
||||||
noDefaultLibs: Boolean,
|
noDefaultLibs: Boolean
|
||||||
logger: DuplicatedLibraryLogger?
|
) = findLibraries(unresolvedLibraries, noStdLib, noDefaultLibs)
|
||||||
) = findLibraries(libraryNames, noStdLib, noDefaultLibs)
|
.leaveDistinct()
|
||||||
.leaveDistinct(logger)
|
|
||||||
.resolveDependencies()
|
.resolveDependencies()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,19 +24,16 @@ internal class KonanLibraryResolverImpl(
|
|||||||
* from the original library set (root set).
|
* from the original library set (root set).
|
||||||
*/
|
*/
|
||||||
private fun findLibraries(
|
private fun findLibraries(
|
||||||
libraryNames: List<String>,
|
unresolvedLibraries: List<UnresolvedLibrary>,
|
||||||
noStdLib: Boolean,
|
noStdLib: Boolean,
|
||||||
noDefaultLibs: Boolean
|
noDefaultLibs: Boolean
|
||||||
): List<KonanLibrary> {
|
): List<KonanLibrary> {
|
||||||
|
|
||||||
val userProvidedLibraries = libraryNames.asSequence()
|
val userProvidedLibraries = unresolvedLibraries.asSequence()
|
||||||
.map { searchPathResolver.resolve(it) }
|
.map { searchPathResolver.resolve(it) }
|
||||||
.map { createKonanLibrary(it, abiVersion, searchPathResolver.target) }
|
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val defaultLibraries = searchPathResolver.defaultLinks(noStdLib, noDefaultLibs).map {
|
val defaultLibraries = searchPathResolver.defaultLinks(noStdLib, noDefaultLibs)
|
||||||
createKonanLibrary(it, abiVersion, searchPathResolver.target, isDefault = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the user provided ones appear first, so that
|
// Make sure the user provided ones appear first, so that
|
||||||
// they have precedence over defaults when duplicates are eliminated.
|
// they have precedence over defaults when duplicates are eliminated.
|
||||||
@@ -50,14 +43,13 @@ internal class KonanLibraryResolverImpl(
|
|||||||
/**
|
/**
|
||||||
* Leaves only distinct libraries (by absolute path), warns on duplicated paths.
|
* Leaves only distinct libraries (by absolute path), warns on duplicated paths.
|
||||||
*/
|
*/
|
||||||
private fun List<KonanLibrary>.leaveDistinct(logger: DuplicatedLibraryLogger?) =
|
private fun List<KonanLibrary>.leaveDistinct() =
|
||||||
this.groupBy { it.libraryFile.absolutePath }.let { groupedByAbsolutePath ->
|
this.groupBy { it.libraryFile.absolutePath }.let { groupedByAbsolutePath ->
|
||||||
warnOnLibraryDuplicates(groupedByAbsolutePath.filter { it.value.size > 1 }.keys, logger)
|
warnOnLibraryDuplicates(groupedByAbsolutePath.filter { it.value.size > 1 }.keys)
|
||||||
groupedByAbsolutePath.map { it.value.first() }
|
groupedByAbsolutePath.map { it.value.first() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun warnOnLibraryDuplicates(duplicatedPaths: Iterable<String>, logger: DuplicatedLibraryLogger? ) {
|
private fun warnOnLibraryDuplicates(duplicatedPaths: Iterable<String>) {
|
||||||
if (logger == null) return
|
|
||||||
duplicatedPaths.forEach { logger("library included more than once: $it") }
|
duplicatedPaths.forEach { logger("library included more than once: $it") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,18 +76,20 @@ internal class KonanLibraryResolverImpl(
|
|||||||
do {
|
do {
|
||||||
newDependencies = newDependencies.map { library: KonanResolvedLibraryImpl ->
|
newDependencies = newDependencies.map { library: KonanResolvedLibraryImpl ->
|
||||||
library.library.unresolvedDependencies.asSequence()
|
library.library.unresolvedDependencies.asSequence()
|
||||||
.map { searchPathResolver.resolve(it).absoluteFile }
|
|
||||||
.mapNotNull {
|
.map { KonanResolvedLibraryImpl(searchPathResolver.resolve(it)) }
|
||||||
if (it in cache) {
|
.map { resolved ->
|
||||||
library.addDependency(cache[it]!!)
|
val absoluteFile = resolved.library.libraryFile.absoluteFile
|
||||||
|
if (absoluteFile in cache) {
|
||||||
|
library.addDependency(cache[absoluteFile]!!)
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
val newLibrary = KonanResolvedLibraryImpl(createKonanLibrary(it, abiVersion, searchPathResolver.target))
|
cache.put(absoluteFile, resolved)
|
||||||
cache[it] = newLibrary
|
library.addDependency(resolved)
|
||||||
library.addDependency(newLibrary)
|
resolved
|
||||||
newLibrary
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}.filterNotNull()
|
||||||
.toList()
|
.toList()
|
||||||
}.flatten()
|
}.flatten()
|
||||||
} while (newDependencies.isNotEmpty())
|
} while (newDependencies.isNotEmpty())
|
||||||
|
|||||||
+2
-3
@@ -2,7 +2,6 @@ package org.jetbrains.kotlin.konan.library.resolver.impl
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||||
import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary
|
import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
|
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
|
||||||
|
|
||||||
internal class KonanResolvedLibraryImpl(
|
internal class KonanResolvedLibraryImpl(
|
||||||
@@ -23,9 +22,9 @@ internal class KonanResolvedLibraryImpl(
|
|||||||
override val isDefault: Boolean
|
override val isDefault: Boolean
|
||||||
get() = library.isDefault
|
get() = library.isDefault
|
||||||
|
|
||||||
override fun markPackageAccessed(fqName: FqName) {
|
override fun markPackageAccessed(fqName: String) {
|
||||||
if (!isNeededForLink // fast path
|
if (!isNeededForLink // fast path
|
||||||
&& !_emptyPackages.contains(fqName.asString())) {
|
&& !_emptyPackages.contains(fqName)) {
|
||||||
isNeededForLink = true
|
isNeededForLink = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ class KonanPackageFragment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val proto: KonanProtoBuf.LinkDataPackageFragment
|
val proto: KonanProtoBuf.LinkDataPackageFragment
|
||||||
get() = protoForNames.also { packageAccessedHandler?.markPackageAccessed(fqName) }
|
get() = protoForNames.also { packageAccessedHandler?.markPackageAccessed(fqName.toString()) }
|
||||||
|
|
||||||
private val nameResolver by lazy {
|
private val nameResolver by lazy {
|
||||||
NameResolverImpl(protoForNames.stringTable, protoForNames.nameTable)
|
NameResolverImpl(protoForNames.stringTable, protoForNames.nameTable)
|
||||||
|
|||||||
+2
-2
@@ -41,9 +41,9 @@ internal object KonanDeserializedPackageFragmentsFactoryImpl: KonanDeserializedP
|
|||||||
|
|
||||||
if (!library.isInterop) return emptyList()
|
if (!library.isInterop) return emptyList()
|
||||||
|
|
||||||
val mainPackageFqName = library.packageFqName
|
val mainPackageFqName = library.packageFqName ?.let { FqName(it) }
|
||||||
?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified")
|
?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified")
|
||||||
val exportForwardDeclarations = library.exportForwardDeclarations
|
val exportForwardDeclarations = library.exportForwardDeclarations.map { FqName(it) }
|
||||||
|
|
||||||
val aliasedPackageFragments = deserializedPackageFragments.filter { it.fqName == mainPackageFqName }
|
val aliasedPackageFragments = deserializedPackageFragments.filter { it.fqName == mainPackageFqName }
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.cli.klib
|
package org.jetbrains.kotlin.cli.klib
|
||||||
|
|
||||||
// TODO: Extract `library` package as a shared jar?
|
// TODO: Extract `library` package as a shared jar?
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KLIB_CURRENT_ABI_VERSION
|
|
||||||
import org.jetbrains.kotlin.config.ApiVersion
|
import org.jetbrains.kotlin.config.ApiVersion
|
||||||
import org.jetbrains.kotlin.config.LanguageVersion
|
import org.jetbrains.kotlin.config.LanguageVersion
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
@@ -15,11 +14,12 @@ import org.jetbrains.kotlin.descriptors.konan.isKonanStdlib
|
|||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION_WITH_DOT
|
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION_WITH_DOT
|
||||||
import org.jetbrains.kotlin.konan.library.createKonanLibrary
|
import org.jetbrains.kotlin.konan.library.createKonanLibrary
|
||||||
import org.jetbrains.kotlin.konan.library.noTargetResolver
|
import org.jetbrains.kotlin.konan.library.resolverByName
|
||||||
import org.jetbrains.kotlin.konan.library.unpackZippedKonanLibraryTo
|
|
||||||
import org.jetbrains.kotlin.konan.target.Distribution
|
import org.jetbrains.kotlin.konan.target.Distribution
|
||||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
import org.jetbrains.kotlin.konan.library.unpackZippedKonanLibraryTo
|
||||||
import org.jetbrains.kotlin.konan.utils.KonanFactories.DefaultDeserializedDescriptorFactory
|
import org.jetbrains.kotlin.konan.utils.KonanFactories.DefaultDeserializedDescriptorFactory
|
||||||
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
|
||||||
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
|
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
|
||||||
@@ -96,31 +96,30 @@ class Library(val name: String, val requestedRepository: String?, val target: St
|
|||||||
val repository = requestedRepository?.File() ?: defaultRepository
|
val repository = requestedRepository?.File() ?: defaultRepository
|
||||||
fun info() {
|
fun info() {
|
||||||
val library = libraryInRepoOrCurrentDir(repository, name)
|
val library = libraryInRepoOrCurrentDir(repository, name)
|
||||||
val reader = createKonanLibrary(library, currentAbiVersion)
|
val headerAbiVersion = library.versions.abiVersion
|
||||||
val headerAbiVersion = reader.abiVersion
|
val moduleName = ModuleDeserializer(library.moduleHeaderData).moduleName
|
||||||
val moduleName = ModuleDeserializer(reader.moduleHeaderData).moduleName
|
|
||||||
|
|
||||||
println("")
|
println("")
|
||||||
println("Resolved to: ${reader.libraryName.File().absolutePath}")
|
println("Resolved to: ${library.libraryName.File().absolutePath}")
|
||||||
println("Module name: $moduleName")
|
println("Module name: $moduleName")
|
||||||
println("ABI version: $headerAbiVersion")
|
println("ABI version: $headerAbiVersion")
|
||||||
val targets = reader.targetList.joinToString(", ")
|
val targets = library.targetList.joinToString(", ")
|
||||||
print("Available targets: $targets\n")
|
print("Available targets: $targets\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun install() {
|
fun install() {
|
||||||
Library(File(name).name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT), requestedRepository, target).remove(true)
|
Library(File(name).name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT), requestedRepository, target).remove(true)
|
||||||
|
|
||||||
val klibFile = libraryInCurrentDir(name)
|
val library = libraryInCurrentDir(name)
|
||||||
val newLibDir = File(repository, klibFile.name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT))
|
val newLibDir = File(repository, library.libraryFile.name.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT))
|
||||||
|
|
||||||
klibFile.unpackZippedKonanLibraryTo(newLibDir)
|
library.libraryFile.unpackZippedKonanLibraryTo(newLibDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remove(blind: Boolean = false) {
|
fun remove(blind: Boolean = false) {
|
||||||
if (!repository.exists) error("Repository does not exist: $repository")
|
if (!repository.exists) error("Repository does not exist: $repository")
|
||||||
|
|
||||||
val libDir = try {
|
val library = try {
|
||||||
val library = libraryInRepo(repository, name)
|
val library = libraryInRepo(repository, name)
|
||||||
if (blind) warn("Removing The previously installed $name from $repository.")
|
if (blind) warn("Removing The previously installed $name from $repository.")
|
||||||
library
|
library
|
||||||
@@ -130,26 +129,26 @@ class Library(val name: String, val requestedRepository: String?, val target: St
|
|||||||
null
|
null
|
||||||
|
|
||||||
}
|
}
|
||||||
libDir?.deleteRecursively()
|
library?.libraryFile?.deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contents(output: Appendable = out) {
|
fun contents(output: Appendable = out) {
|
||||||
|
|
||||||
val storageManager = LockBasedStorageManager()
|
val storageManager = LockBasedStorageManager()
|
||||||
val library = createKonanLibrary(libraryInRepoOrCurrentDir(repository, name), currentAbiVersion)
|
val library = libraryInRepoOrCurrentDir(repository, name)
|
||||||
val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion)
|
val versionSpec = LanguageVersionSettingsImpl(currentLanguageVersion, currentApiVersion)
|
||||||
val module = DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(library, versionSpec, storageManager)
|
val module = DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(library, versionSpec, storageManager)
|
||||||
|
|
||||||
val defaultModules = mutableListOf<ModuleDescriptorImpl>()
|
val defaultModules = mutableListOf<ModuleDescriptorImpl>()
|
||||||
if (!module.isKonanStdlib()) {
|
if (!module.isKonanStdlib()) {
|
||||||
val resolver = noTargetResolver(
|
val resolver = resolverByName(
|
||||||
emptyList(),
|
emptyList(),
|
||||||
distributionKlib = Distribution().klib,
|
distributionKlib = Distribution().klib,
|
||||||
skipCurrentDir = true)
|
skipCurrentDir = true)
|
||||||
resolver.defaultLinks(false, true)
|
resolver.defaultLinks(false, true)
|
||||||
.mapTo(defaultModules) {
|
.mapTo(defaultModules) {
|
||||||
DefaultDeserializedDescriptorFactory.createDescriptor(
|
DefaultDeserializedDescriptorFactory.createDescriptor(
|
||||||
createKonanLibrary(it, currentAbiVersion), versionSpec, storageManager, module.builtIns)
|
it, versionSpec, storageManager, module.builtIns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,17 +160,16 @@ class Library(val name: String, val requestedRepository: String?, val target: St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const val currentAbiVersion = KLIB_CURRENT_ABI_VERSION
|
|
||||||
val currentLanguageVersion = LanguageVersion.LATEST_STABLE
|
val currentLanguageVersion = LanguageVersion.LATEST_STABLE
|
||||||
val currentApiVersion = ApiVersion.LATEST_STABLE
|
val currentApiVersion = ApiVersion.LATEST_STABLE
|
||||||
|
|
||||||
fun libraryInRepo(repository: File, name: String) =
|
fun libraryInRepo(repository: File, name: String) =
|
||||||
noTargetResolver(listOf(repository.absolutePath), skipCurrentDir = true).resolve(name)
|
resolverByName(listOf(repository.absolutePath), skipCurrentDir = true).resolve(name)
|
||||||
|
|
||||||
fun libraryInCurrentDir(name: String) = noTargetResolver(emptyList()).resolve(name)
|
fun libraryInCurrentDir(name: String) = resolverByName(emptyList()).resolve(name)
|
||||||
|
|
||||||
fun libraryInRepoOrCurrentDir(repository: File, name: String) =
|
fun libraryInRepoOrCurrentDir(repository: File, name: String) =
|
||||||
noTargetResolver(listOf(repository.absolutePath)).resolve(name)
|
resolverByName(listOf(repository.absolutePath)).resolve(name)
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val command = Command(args)
|
val command = Command(args)
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ task generateCompilerVersion(type: VersionGenerator){}
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
main.kotlin {
|
main.kotlin {
|
||||||
srcDir 'src/main/kotlin'
|
srcDir 'src/main/kotlin'
|
||||||
|
srcDir 'src/library/kotlin'
|
||||||
srcDir generateCompilerVersion.versionSourceDirectory
|
srcDir generateCompilerVersion.versionSourceDirectory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,17 @@ open class VersionGenerator: DefaultTask() {
|
|||||||
|
|
|
|
||||||
| override fun toString() = versionString
|
| override fun toString() = versionString
|
||||||
|}
|
|}
|
||||||
|
|fun String.parseKonanVersion(): KonanVersion {
|
||||||
|
| val (major, minor, maintenance, meta, build) =
|
||||||
|
| Regex(""${'"'}([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-(\p{Alpha}\p{Alnum}*))?(?:-([0-9]+))?""${'"'})
|
||||||
|
| .matchEntire(this)!!.destructured
|
||||||
|
| return KonanVersionImpl(
|
||||||
|
| MetaVersion.valueOf(meta.toUpperCase()),
|
||||||
|
| major.toInt(),
|
||||||
|
| minor.toInt(),
|
||||||
|
| maintenance.toIntOrNull() ?: 0,
|
||||||
|
| build.toIntOrNull() ?: -1)
|
||||||
|
|}
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
}
|
}
|
||||||
versionFile.printWriter().use {
|
versionFile.printWriter().use {
|
||||||
|
|||||||
+10
-5
@@ -3,9 +3,11 @@ package org.jetbrains.kotlin.konan.library
|
|||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
|
|
||||||
const val KLIB_PROPERTY_ABI_VERSION = "abi_version"
|
const val KLIB_PROPERTY_ABI_VERSION = "abi_version"
|
||||||
|
const val KLIB_PROPERTY_COMPILER_VERSION = "compiler_version"
|
||||||
|
const val KLIB_PROPERTY_DEPENDENCY_VERSION = "dependency_version"
|
||||||
|
const val KLIB_PROPERTY_LIBRARY_VERSION = "library_version"
|
||||||
const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name"
|
const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name"
|
||||||
const val KLIB_PROPERTY_LINKED_OPTS = "linkerOpts"
|
const val KLIB_PROPERTY_LINKED_OPTS = "linkerOpts"
|
||||||
const val KLIB_PROPERTY_DEPENDS = "depends"
|
const val KLIB_PROPERTY_DEPENDS = "depends"
|
||||||
@@ -27,7 +29,6 @@ interface KonanLibrary {
|
|||||||
|
|
||||||
// Properties:
|
// Properties:
|
||||||
val manifestProperties: Properties
|
val manifestProperties: Properties
|
||||||
val abiVersion: String
|
|
||||||
val linkerOpts: List<String>
|
val linkerOpts: List<String>
|
||||||
|
|
||||||
// Paths:
|
// Paths:
|
||||||
@@ -35,6 +36,7 @@ interface KonanLibrary {
|
|||||||
val includedPaths: List<String>
|
val includedPaths: List<String>
|
||||||
|
|
||||||
val targetList: List<String>
|
val targetList: List<String>
|
||||||
|
val versions: KonanLibraryVersioning
|
||||||
|
|
||||||
val dataFlowGraph: ByteArray?
|
val dataFlowGraph: ByteArray?
|
||||||
val moduleHeaderData: ByteArray
|
val moduleHeaderData: ByteArray
|
||||||
@@ -44,21 +46,24 @@ interface KonanLibrary {
|
|||||||
val KonanLibrary.uniqueName
|
val KonanLibrary.uniqueName
|
||||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)!!
|
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)!!
|
||||||
|
|
||||||
val KonanLibrary.unresolvedDependencies: List<String>
|
val KonanLibrary.unresolvedDependencies: List<UnresolvedLibrary>
|
||||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS)
|
get() = manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS)
|
||||||
|
.map {
|
||||||
|
UnresolvedLibrary(it, manifestProperties.getProperty("dependency_version_$it"))
|
||||||
|
}
|
||||||
|
|
||||||
val KonanLibrary.isInterop
|
val KonanLibrary.isInterop
|
||||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_INTEROP) == "true"
|
get() = manifestProperties.getProperty(KLIB_PROPERTY_INTEROP) == "true"
|
||||||
|
|
||||||
val KonanLibrary.packageFqName
|
val KonanLibrary.packageFqName
|
||||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_PACKAGE)?.let { FqName(it) }
|
get() = manifestProperties.getProperty(KLIB_PROPERTY_PACKAGE)
|
||||||
|
|
||||||
val KonanLibrary.exportForwardDeclarations
|
val KonanLibrary.exportForwardDeclarations
|
||||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS)
|
get() = manifestProperties.getProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS)
|
||||||
.split(' ').asSequence()
|
.split(' ').asSequence()
|
||||||
.map { it.trim() }
|
.map { it.trim() }
|
||||||
.filter { it.isNotEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
.map { FqName(it) }
|
.map { it }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val KonanLibrary.includedHeaders
|
val KonanLibrary.includedHeaders
|
||||||
+13
-8
@@ -3,14 +3,14 @@ package org.jetbrains.kotlin.konan.library
|
|||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.file.file
|
import org.jetbrains.kotlin.konan.file.file
|
||||||
import org.jetbrains.kotlin.konan.file.withMutableZipFileSystem
|
import org.jetbrains.kotlin.konan.file.withMutableZipFileSystem
|
||||||
import org.jetbrains.kotlin.konan.file.withZipFileSystem
|
|
||||||
import org.jetbrains.kotlin.konan.library.impl.DefaultMetadataReaderImpl
|
import org.jetbrains.kotlin.konan.library.impl.DefaultMetadataReaderImpl
|
||||||
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
|
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
|
||||||
import org.jetbrains.kotlin.konan.library.impl.zippedKonanLibraryChecks
|
import org.jetbrains.kotlin.konan.library.impl.zippedKonanLibraryChecks
|
||||||
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolver
|
|
||||||
import org.jetbrains.kotlin.konan.library.resolver.impl.KonanLibraryResolverImpl
|
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
|
||||||
|
val KLIB_FILE_EXTENSION = "klib"
|
||||||
|
val KLIB_FILE_EXTENSION_WITH_DOT = ".$KLIB_FILE_EXTENSION"
|
||||||
|
|
||||||
fun File.unpackZippedKonanLibraryTo(newDir: File) {
|
fun File.unpackZippedKonanLibraryTo(newDir: File) {
|
||||||
|
|
||||||
// First, run validity checks for the given KLIB file.
|
// First, run validity checks for the given KLIB file.
|
||||||
@@ -29,13 +29,18 @@ fun File.unpackZippedKonanLibraryTo(newDir: File) {
|
|||||||
check(newDir.exists) { "Could not unpack $this as $newDir." }
|
check(newDir.exists) { "Could not unpack $this as $newDir." }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val List<String>.toUnresolvedLibraries
|
||||||
|
get() = this.map {
|
||||||
|
|
||||||
|
val version = it.substringAfterLast('@', "")
|
||||||
|
.let { if (it.isEmpty()) null else it}
|
||||||
|
val name = it.substringBeforeLast('@')
|
||||||
|
UnresolvedLibrary(name, version)
|
||||||
|
}
|
||||||
|
|
||||||
fun createKonanLibrary(
|
fun createKonanLibrary(
|
||||||
libraryFile: File,
|
libraryFile: File,
|
||||||
currentAbiVersion: Int,
|
|
||||||
target: KonanTarget? = null,
|
target: KonanTarget? = null,
|
||||||
isDefault: Boolean = false,
|
isDefault: Boolean = false,
|
||||||
metadataReader: MetadataReader = DefaultMetadataReaderImpl
|
metadataReader: MetadataReader = DefaultMetadataReaderImpl
|
||||||
): KonanLibrary = KonanLibraryImpl(libraryFile, currentAbiVersion, target, isDefault, metadataReader)
|
): KonanLibrary = KonanLibraryImpl(libraryFile, target, isDefault, metadataReader)
|
||||||
|
|
||||||
fun SearchPathResolverWithTarget.libraryResolver(abiVersion: Int): KonanLibraryResolver =
|
|
||||||
KonanLibraryResolverImpl(this, abiVersion)
|
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package org.jetbrains.kotlin.konan.library
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.parseKonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
|
import org.jetbrains.kotlin.konan.parseKonanAbiVersion
|
||||||
|
|
||||||
|
|
||||||
|
data class KonanLibraryVersioning(
|
||||||
|
val libraryVersion: String?,
|
||||||
|
val compilerVersion: KonanVersion,
|
||||||
|
val abiVersion: KonanAbiVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Properties.writeKonanLibraryVersioning(versions: KonanLibraryVersioning) {
|
||||||
|
this.setProperty(KLIB_PROPERTY_ABI_VERSION, versions.abiVersion.toString())
|
||||||
|
versions.libraryVersion ?. let { this.setProperty(KLIB_PROPERTY_LIBRARY_VERSION, it) }
|
||||||
|
this.setProperty(KLIB_PROPERTY_COMPILER_VERSION, "${versions.compilerVersion}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Properties.readKonanLibraryVersioning(): KonanLibraryVersioning {
|
||||||
|
val abiVersion = this.getProperty(KLIB_PROPERTY_ABI_VERSION)!!.parseKonanAbiVersion()
|
||||||
|
val libraryVersion = this.getProperty(KLIB_PROPERTY_LIBRARY_VERSION)
|
||||||
|
val compilerVersion = this.getProperty(KLIB_PROPERTY_COMPILER_VERSION)!!.parseKonanVersion()
|
||||||
|
|
||||||
|
return KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion)
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
package org.jetbrains.kotlin.konan.library
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
|
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
|
||||||
|
import org.jetbrains.kotlin.konan.target.Distribution
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.konan.util.*
|
||||||
|
|
||||||
|
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the constants below:
|
||||||
|
const val KONAN_STDLIB_NAME = "stdlib"
|
||||||
|
|
||||||
|
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this interface!
|
||||||
|
interface SearchPathResolver : WithLogger {
|
||||||
|
val searchRoots: List<File>
|
||||||
|
fun resolutionSequence(givenPath: String): Sequence<File>
|
||||||
|
fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean = false): KonanLibraryImpl
|
||||||
|
fun resolve(givenPath: String): KonanLibraryImpl
|
||||||
|
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<KonanLibraryImpl>
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this interface!
|
||||||
|
interface SearchPathResolverWithTarget: SearchPathResolver {
|
||||||
|
val target: KonanTarget
|
||||||
|
val knownAbiVersions: List<KonanAbiVersion>?
|
||||||
|
val knownCompilerVersions: List<KonanVersion>?
|
||||||
|
}
|
||||||
|
|
||||||
|
fun defaultResolver(
|
||||||
|
repositories: List<String>,
|
||||||
|
target: KonanTarget
|
||||||
|
): SearchPathResolverWithTarget = defaultResolver(repositories, target, Distribution())
|
||||||
|
|
||||||
|
fun defaultResolver(
|
||||||
|
repositories: List<String>,
|
||||||
|
target: KonanTarget,
|
||||||
|
distribution: Distribution,
|
||||||
|
logger: Logger = ::dummyLogger,
|
||||||
|
skipCurrentDir: Boolean = false
|
||||||
|
): SearchPathResolverWithTarget = KonanLibraryProperResolver(
|
||||||
|
repositories,
|
||||||
|
target,
|
||||||
|
listOf(KonanAbiVersion.CURRENT),
|
||||||
|
listOf(KonanVersion.CURRENT),
|
||||||
|
distribution.klib,
|
||||||
|
distribution.localKonanDir.absolutePath,
|
||||||
|
skipCurrentDir,
|
||||||
|
logger)
|
||||||
|
|
||||||
|
fun resolverByName(
|
||||||
|
repositories: List<String>,
|
||||||
|
distributionKlib: String? = null,
|
||||||
|
localKonanDir: String? = null,
|
||||||
|
skipCurrentDir: Boolean = false
|
||||||
|
): SearchPathResolver = KonanLibrarySearchPathResolver(repositories, distributionKlib, localKonanDir, skipCurrentDir)
|
||||||
|
|
||||||
|
internal open class KonanLibrarySearchPathResolver(
|
||||||
|
repositories: List<String>,
|
||||||
|
val distributionKlib: String?,
|
||||||
|
val localKonanDir: String?,
|
||||||
|
val skipCurrentDir: Boolean,
|
||||||
|
override val logger:Logger = ::dummyLogger
|
||||||
|
) : SearchPathResolver {
|
||||||
|
|
||||||
|
val localHead: File?
|
||||||
|
get() = localKonanDir?.File()?.klib
|
||||||
|
|
||||||
|
val distHead: File?
|
||||||
|
get() = distributionKlib?.File()?.child("common")
|
||||||
|
|
||||||
|
open val distPlatformHead: File? = null
|
||||||
|
|
||||||
|
val currentDirHead: File?
|
||||||
|
get() = if (!skipCurrentDir) File.userDir else null
|
||||||
|
|
||||||
|
private val repoRoots: List<File> by lazy { repositories.map { File(it) } }
|
||||||
|
|
||||||
|
// This is the place where we specify the order of library search.
|
||||||
|
override val searchRoots: List<File> by lazy {
|
||||||
|
(listOf(currentDirHead) + repoRoots + listOf(localHead, distHead, distPlatformHead)).filterNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun found(candidate: File): File? {
|
||||||
|
fun check(file: File): Boolean =
|
||||||
|
file.exists && (file.isFile || File(file, "manifest").exists)
|
||||||
|
|
||||||
|
val noSuffix = File(candidate.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT))
|
||||||
|
val withSuffix = File(candidate.path.suffixIfNot(KLIB_FILE_EXTENSION_WITH_DOT))
|
||||||
|
return when {
|
||||||
|
check(withSuffix) -> withSuffix
|
||||||
|
check(noSuffix) -> noSuffix
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolutionSequence(givenPath: String): Sequence<File> {
|
||||||
|
val given = File(givenPath)
|
||||||
|
val sequence = if (given.isAbsolute) {
|
||||||
|
sequenceOf(found(given))
|
||||||
|
} else {
|
||||||
|
searchRoots.asSequence().map {
|
||||||
|
found(File(it, givenPath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sequence.filterNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): KonanLibraryImpl {
|
||||||
|
val givenPath = unresolved.path
|
||||||
|
return resolutionSequence(givenPath).firstOrNull() ?. let {
|
||||||
|
createKonanLibrary(it, null, isDefaultLink) as KonanLibraryImpl
|
||||||
|
} ?: error("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolve(givenPath: String) = resolve(UnresolvedLibrary(givenPath, null), false)
|
||||||
|
|
||||||
|
|
||||||
|
private val File.klib
|
||||||
|
get() = File(this, "klib")
|
||||||
|
|
||||||
|
// The libraries from the default root are linked automatically.
|
||||||
|
val defaultRoots: List<File>
|
||||||
|
get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists }
|
||||||
|
|
||||||
|
override fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<KonanLibraryImpl> {
|
||||||
|
|
||||||
|
val result = mutableListOf<KonanLibraryImpl>()
|
||||||
|
|
||||||
|
if (!noStdLib) {
|
||||||
|
result.add(resolve(UnresolvedLibrary(KONAN_STDLIB_NAME, null), true))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noDefaultLibs) {
|
||||||
|
val defaultLibs = defaultRoots.flatMap { it.listFiles }
|
||||||
|
.filterNot { it.name.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT) == KONAN_STDLIB_NAME }
|
||||||
|
.map { UnresolvedLibrary(it.absolutePath, null) }
|
||||||
|
.map {resolve(it, isDefaultLink = true) }
|
||||||
|
result.addAll(defaultLibs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class KonanLibraryProperResolver(
|
||||||
|
repositories: List<String>,
|
||||||
|
override val target: KonanTarget,
|
||||||
|
override val knownAbiVersions: List<KonanAbiVersion>?,
|
||||||
|
override val knownCompilerVersions: List<KonanVersion>?,
|
||||||
|
distributionKlib: String?,
|
||||||
|
localKonanDir: String?,
|
||||||
|
skipCurrentDir: Boolean,
|
||||||
|
override val logger: Logger = ::dummyLogger
|
||||||
|
): KonanLibrarySearchPathResolver(repositories, distributionKlib, localKonanDir, skipCurrentDir, logger), SearchPathResolverWithTarget {
|
||||||
|
|
||||||
|
override val distPlatformHead: File?
|
||||||
|
get() = distributionKlib?.File()?.child("platform")?.child(target.visibleName)
|
||||||
|
|
||||||
|
override fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): KonanLibraryImpl {
|
||||||
|
val givenPath = unresolved.path
|
||||||
|
val fileSequence = resolutionSequence(givenPath)
|
||||||
|
val matching = fileSequence.map { createKonanLibrary(it, target, isDefaultLink) as KonanLibraryImpl }
|
||||||
|
.map { it.takeIf { libraryMatch(it, unresolved) } }
|
||||||
|
.filterNotNull()
|
||||||
|
|
||||||
|
return matching.firstOrNull() ?: error("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun SearchPathResolverWithTarget.libraryMatch(candidate: KonanLibraryImpl, unresolved: UnresolvedLibrary): Boolean {
|
||||||
|
val resolverTarget = this.target
|
||||||
|
val candidatePath = candidate.libraryFile.absolutePath
|
||||||
|
|
||||||
|
if (resolverTarget != null && !candidate.targetList.contains(resolverTarget.visibleName)) {
|
||||||
|
logger("skipping $candidatePath. The target doesn't match. Expected '$resolverTarget', found ${candidate.targetList}")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (knownCompilerVersions != null &&
|
||||||
|
!knownCompilerVersions!!.contains(candidate.versions.compilerVersion)) {
|
||||||
|
logger("skipping $candidatePath. The compiler versions don't match. Expected '${knownCompilerVersions}', found '${candidate.versions.compilerVersion}'")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (knownAbiVersions != null &&
|
||||||
|
!knownAbiVersions!!.contains(candidate.versions.abiVersion)) {
|
||||||
|
logger("skipping $candidatePath. The abi versions don't match. Expected '${knownAbiVersions}', found '${candidate.versions.abiVersion}'")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidate.versions.libraryVersion != unresolved.libraryVersion &&
|
||||||
|
candidate.versions.libraryVersion != null &&
|
||||||
|
unresolved.libraryVersion != null) {
|
||||||
|
logger("skipping $candidatePath. The library versions don't match. Expected '${unresolved.libraryVersion}', found '${candidate.versions.libraryVersion}'")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.jetbrains.kotlin.konan.library
|
||||||
|
|
||||||
|
data class UnresolvedLibrary(
|
||||||
|
val path: String,
|
||||||
|
val libraryVersion: String?) {
|
||||||
|
|
||||||
|
fun substitutePath(newPath: String): UnresolvedLibrary {
|
||||||
|
return UnresolvedLibrary(newPath, libraryVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-10
@@ -9,9 +9,9 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
|
|||||||
import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions
|
import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions
|
||||||
import org.jetbrains.kotlin.konan.util.substitute
|
import org.jetbrains.kotlin.konan.util.substitute
|
||||||
|
|
||||||
internal class KonanLibraryImpl(
|
|
||||||
|
class KonanLibraryImpl(
|
||||||
override val libraryFile: File,
|
override val libraryFile: File,
|
||||||
private val currentAbiVersion: Int,
|
|
||||||
internal val target: KonanTarget?,
|
internal val target: KonanTarget?,
|
||||||
override val isDefault: Boolean,
|
override val isDefault: Boolean,
|
||||||
private val metadataReader: MetadataReader
|
private val metadataReader: MetadataReader
|
||||||
@@ -32,14 +32,8 @@ internal class KonanLibraryImpl(
|
|||||||
properties
|
properties
|
||||||
}
|
}
|
||||||
|
|
||||||
override val abiVersion: String
|
override val versions: KonanLibraryVersioning
|
||||||
get() {
|
get() = manifestProperties.readKonanLibraryVersioning()
|
||||||
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>
|
override val linkerOpts: List<String>
|
||||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_LINKED_OPTS, target!!.visibleName)
|
get() = manifestProperties.propertyList(KLIB_PROPERTY_LINKED_OPTS, target!!.visibleName)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.jetbrains.kotlin.konan
|
||||||
|
|
||||||
|
fun String.parseKonanAbiVersion(): KonanAbiVersion {
|
||||||
|
return KonanAbiVersion(this.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
data class KonanAbiVersion(val version: Int) {
|
||||||
|
companion object {
|
||||||
|
val CURRENT = KonanAbiVersion(1)
|
||||||
|
}
|
||||||
|
override fun toString() = "$version"
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.konan.file
|
|||||||
|
|
||||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
@@ -38,7 +39,7 @@ data class File constructor(internal val javaPath: Path) {
|
|||||||
val absoluteFile: File
|
val absoluteFile: File
|
||||||
get() = File(absolutePath)
|
get() = File(absolutePath)
|
||||||
val name: String
|
val name: String
|
||||||
get() = javaPath.fileName.toString()
|
get() = javaPath.fileName.toString().removeSuffixIfPresent("/") // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8153248
|
||||||
val extension: String
|
val extension: String
|
||||||
get() = name.substringAfterLast('.', "")
|
get() = name.substringAfterLast('.', "")
|
||||||
val parent: String
|
val parent: String
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
package org.jetbrains.kotlin.konan.library
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
|
||||||
import org.jetbrains.kotlin.konan.target.Distribution
|
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
|
||||||
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent
|
|
||||||
import org.jetbrains.kotlin.konan.util.suffixIfNot
|
|
||||||
|
|
||||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the constants below:
|
|
||||||
const val KLIB_FILE_EXTENSION = "klib"
|
|
||||||
const val KLIB_FILE_EXTENSION_WITH_DOT = ".$KLIB_FILE_EXTENSION"
|
|
||||||
|
|
||||||
const val KONAN_STDLIB_NAME = "stdlib"
|
|
||||||
|
|
||||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this interface!
|
|
||||||
interface SearchPathResolver {
|
|
||||||
val searchRoots: List<File>
|
|
||||||
fun resolve(givenPath: String): File
|
|
||||||
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<File>
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this interface!
|
|
||||||
interface SearchPathResolverWithTarget: SearchPathResolver {
|
|
||||||
val target: KonanTarget
|
|
||||||
}
|
|
||||||
|
|
||||||
fun defaultResolver(
|
|
||||||
repositories: List<String>,
|
|
||||||
target: KonanTarget
|
|
||||||
): SearchPathResolverWithTarget = defaultResolver(repositories, target, Distribution())
|
|
||||||
|
|
||||||
fun defaultResolver(
|
|
||||||
repositories: List<String>,
|
|
||||||
target: KonanTarget,
|
|
||||||
distribution: Distribution,
|
|
||||||
skipCurrentDir: Boolean = false
|
|
||||||
): SearchPathResolverWithTarget = KonanLibrarySearchPathResolverWithTarget(
|
|
||||||
repositories,
|
|
||||||
target,
|
|
||||||
distribution.klib,
|
|
||||||
distribution.localKonanDir.absolutePath,
|
|
||||||
skipCurrentDir)
|
|
||||||
|
|
||||||
fun noTargetResolver(
|
|
||||||
repositories: List<String>,
|
|
||||||
distributionKlib: String? = null,
|
|
||||||
localKonanDir: String? = null,
|
|
||||||
skipCurrentDir: Boolean = false
|
|
||||||
): SearchPathResolver = KonanLibrarySearchPathResolver(repositories, distributionKlib, localKonanDir, skipCurrentDir)
|
|
||||||
|
|
||||||
|
|
||||||
internal open class KonanLibrarySearchPathResolver(
|
|
||||||
repositories: List<String>,
|
|
||||||
val distributionKlib: String?,
|
|
||||||
val localKonanDir: String?,
|
|
||||||
val skipCurrentDir: Boolean
|
|
||||||
) : SearchPathResolver {
|
|
||||||
|
|
||||||
val localHead: File?
|
|
||||||
get() = localKonanDir?.File()?.klib
|
|
||||||
|
|
||||||
val distHead: File?
|
|
||||||
get() = distributionKlib?.File()?.child("common")
|
|
||||||
|
|
||||||
open val distPlatformHead: File? = null
|
|
||||||
|
|
||||||
val currentDirHead: File?
|
|
||||||
get() = if (!skipCurrentDir) File.userDir else null
|
|
||||||
|
|
||||||
private val repoRoots: List<File> by lazy { repositories.map { File(it) } }
|
|
||||||
|
|
||||||
// This is the place where we specify the order of library search.
|
|
||||||
override val searchRoots: List<File> by lazy {
|
|
||||||
(listOf(currentDirHead) + repoRoots + listOf(localHead, distHead, distPlatformHead)).filterNotNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun found(candidate: File): File? {
|
|
||||||
fun check(file: File): Boolean =
|
|
||||||
file.exists && (file.isFile || File(file, "manifest").exists)
|
|
||||||
|
|
||||||
val noSuffix = File(candidate.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT))
|
|
||||||
val withSuffix = File(candidate.path.suffixIfNot(KLIB_FILE_EXTENSION_WITH_DOT))
|
|
||||||
return when {
|
|
||||||
check(withSuffix) -> withSuffix
|
|
||||||
check(noSuffix) -> noSuffix
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resolve(givenPath: String): File {
|
|
||||||
val given = File(givenPath)
|
|
||||||
if (given.isAbsolute) {
|
|
||||||
found(given)?.apply { return this }
|
|
||||||
} else {
|
|
||||||
searchRoots.forEach {
|
|
||||||
found(File(it, givenPath))?.apply { return this }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
error("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val File.klib
|
|
||||||
get() = File(this, "klib")
|
|
||||||
|
|
||||||
// The libraries from the default root are linked automatically.
|
|
||||||
val defaultRoots: List<File>
|
|
||||||
get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists }
|
|
||||||
|
|
||||||
override fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<File> {
|
|
||||||
|
|
||||||
val result = mutableListOf<File>()
|
|
||||||
|
|
||||||
if (!noStdLib) {
|
|
||||||
result.add(resolve(KONAN_STDLIB_NAME))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!noDefaultLibs) {
|
|
||||||
val defaultLibs = defaultRoots.flatMap { it.listFiles }
|
|
||||||
.filterNot { it.name.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT) == KONAN_STDLIB_NAME }
|
|
||||||
.map { File(it.absolutePath) }
|
|
||||||
result.addAll(defaultLibs)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class KonanLibrarySearchPathResolverWithTarget(
|
|
||||||
repositories: List<String>,
|
|
||||||
override val target: KonanTarget,
|
|
||||||
distributionKlib: String?,
|
|
||||||
localKonanDir: String?,
|
|
||||||
skipCurrentDir: Boolean
|
|
||||||
): KonanLibrarySearchPathResolver(repositories, distributionKlib, localKonanDir, skipCurrentDir), SearchPathResolverWithTarget {
|
|
||||||
|
|
||||||
override val distPlatformHead: File?
|
|
||||||
get() = distributionKlib?.File()?.child("platform")?.child(target.visibleName)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.jetbrains.kotlin.konan.util
|
||||||
|
|
||||||
|
typealias Logger = (String) -> Unit
|
||||||
|
|
||||||
|
interface WithLogger {
|
||||||
|
val logger: Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dummyLogger(message: String) {}
|
||||||
|
|
||||||
+1
-1
@@ -154,6 +154,6 @@ open class KonanLibrariesSpec(val task: KonanArtifactWithLibrariesTask, val proj
|
|||||||
files.flatMapTo(this) { it.files }
|
files.flatMapTo(this) { it.files }
|
||||||
addAll(artifactFiles)
|
addAll(artifactFiles)
|
||||||
addAll(task.platformConfiguration.files)
|
addAll(task.platformConfiguration.files)
|
||||||
namedKlibs.mapTo(this) { project.file(resolver.resolve(it).absolutePath) }
|
namedKlibs.mapTo(this) { project.file(resolver.resolve(it).libraryFile.absolutePath) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.kotlin.cli.utilities
|
package org.jetbrains.kotlin.cli.utilities
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KLIB_CURRENT_ABI_VERSION
|
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
|
||||||
import org.jetbrains.kotlin.konan.library.includedHeaders
|
|
||||||
import org.jetbrains.kotlin.konan.library.libraryResolver
|
|
||||||
import org.jetbrains.kotlin.konan.library.packageFqName
|
|
||||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||||
|
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||||
|
import org.jetbrains.kotlin.konan.library.*
|
||||||
import org.jetbrains.kotlin.native.interop.gen.jvm.interop
|
import org.jetbrains.kotlin.native.interop.gen.jvm.interop
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
@@ -57,14 +54,14 @@ fun invokeInterop(flavor: String, args: Array<String>): Array<String> {
|
|||||||
val manifest = File(buildDir, "manifest.properties")
|
val manifest = File(buildDir, "manifest.properties")
|
||||||
|
|
||||||
val target = PlatformManager().targetManager(targetRequest).target
|
val target = PlatformManager().targetManager(targetRequest).target
|
||||||
val resolver = defaultResolver(repos, target).libraryResolver(KLIB_CURRENT_ABI_VERSION)
|
val resolver = defaultResolver(repos, target).libraryResolver()
|
||||||
val allLibraries = resolver.resolveWithDependencies(
|
val allLibraries = resolver.resolveWithDependencies(
|
||||||
libraries, noStdLib = true, noDefaultLibs = noDefaultLibs
|
libraries.toUnresolvedLibraries, noStdLib = true, noDefaultLibs = noDefaultLibs
|
||||||
).getFullList()
|
).getFullList()
|
||||||
|
|
||||||
val importArgs = allLibraries.flatMap { library ->
|
val importArgs = allLibraries.flatMap { library ->
|
||||||
// TODO: handle missing properties?
|
// TODO: handle missing properties?
|
||||||
library.packageFqName?.asString()?.let { packageFqName ->
|
library.packageFqName?.let { packageFqName ->
|
||||||
val headerIds = library.includedHeaders
|
val headerIds = library.includedHeaders
|
||||||
val arg = "$packageFqName:${headerIds.joinToString(";")}"
|
val arg = "$packageFqName:${headerIds.joinToString(";")}"
|
||||||
listOf("-import", arg)
|
listOf("-import", arg)
|
||||||
|
|||||||
Reference in New Issue
Block a user