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.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
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.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||
@@ -142,7 +143,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
val outputKind = CompilerOutputKind.valueOf(
|
||||
(arguments.produce ?: "program").toUpperCase())
|
||||
put(PRODUCE, outputKind)
|
||||
put(ABI_VERSION, 1)
|
||||
arguments.libraryVersion ?. let { put(LIBRARY_VERSION, it) }
|
||||
|
||||
arguments.mainPackage ?.let{ put(ENTRY, 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")
|
||||
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")
|
||||
var listTargets: Boolean = false
|
||||
|
||||
|
||||
+10
-3
@@ -8,6 +8,9 @@ import llvm.LLVMLinkModules2
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
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
|
||||
|
||||
val CompilerOutputKind.isNativeBinary: Boolean get() = when (this) {
|
||||
@@ -62,17 +65,21 @@ internal fun produceOutput(context: Context, phaser: PhaseManager) {
|
||||
val libraryName = context.config.moduleId
|
||||
val neededLibraries
|
||||
= 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 nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val manifestProperties = context.config.manifestProperties
|
||||
|
||||
|
||||
val library = buildLibrary(
|
||||
context.config.nativeLibraries,
|
||||
context.config.includeBinaries,
|
||||
neededLibraries,
|
||||
context.serializedLinkData!!,
|
||||
abiVersion,
|
||||
context.serializedLinkData!!,
|
||||
versions,
|
||||
target,
|
||||
output,
|
||||
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.properties.loadProperties
|
||||
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) {
|
||||
|
||||
val currentAbiVersion: Int = configuration.get(KonanConfigKeys.ABI_VERSION)!!
|
||||
|
||||
internal val distribution = Distribution(
|
||||
false,
|
||||
null,
|
||||
@@ -71,15 +71,18 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
private val libraryNames: List<String>
|
||||
get() = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
||||
|
||||
private val unresolvedLibraries = libraryNames.toUnresolvedLibraries
|
||||
|
||||
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 {
|
||||
resolver.resolveWithDependencies(
|
||||
libraryNames,
|
||||
unresolvedLibraries,
|
||||
noStdLib = configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
|
||||
noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS) ) { msg ->
|
||||
configuration.report(STRONG_WARNING, msg) }
|
||||
noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS) )
|
||||
}
|
||||
|
||||
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)
|
||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||
|
||||
|
||||
+4
-4
@@ -12,8 +12,6 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
class KonanConfigKeys {
|
||||
companion object {
|
||||
// Keep the list lexically sorted.
|
||||
val ABI_VERSION: CompilerConfigurationKey<Int>
|
||||
= CompilerConfigurationKey.create("current abi version")
|
||||
val CHECK_DEPENDENCIES: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("check dependencies and download the missing ones")
|
||||
val DEBUG: CompilerConfigurationKey<Boolean>
|
||||
@@ -26,12 +24,16 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("enable backend phases")
|
||||
val ENTRY: CompilerConfigurationKey<String?>
|
||||
= 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>
|
||||
= CompilerConfigurationKey.create("generate test runner")
|
||||
val INCLUDED_BINARY_FILES: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("included binary file paths")
|
||||
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("library file paths")
|
||||
val LIBRARY_VERSION: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create("library version")
|
||||
val LINKER_ARGS: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("additional linker arguments")
|
||||
val LIST_PHASES: CompilerConfigurationKey<Boolean>
|
||||
@@ -94,8 +96,6 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("verify ir")
|
||||
val VERBOSE_PHASES: CompilerConfigurationKey<List<String>>
|
||||
= 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 org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import java.util.*
|
||||
|
||||
const val KLIB_CURRENT_ABI_VERSION = 1
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
interface KonanLibraryWriter {
|
||||
val versions: KonanLibraryVersioning
|
||||
fun addLinkData(linkData: LinkData)
|
||||
fun addNativeBitcode(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.konan.file.*
|
||||
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.target.KonanTarget
|
||||
|
||||
abstract class FileBasedLibraryWriter (val file: File, val currentAbiVersion: Int): KonanLibraryWriter
|
||||
abstract class FileBasedLibraryWriter (val file: File): KonanLibraryWriter
|
||||
|
||||
/**
|
||||
* Requires non-null [target].
|
||||
@@ -22,13 +23,13 @@ abstract class FileBasedLibraryWriter (val file: File, val currentAbiVersion: In
|
||||
class LibraryWriterImpl(
|
||||
override val libDir: File,
|
||||
moduleName: String,
|
||||
currentAbiVersion: Int,
|
||||
override val versions: KonanLibraryVersioning,
|
||||
override val target: KonanTarget,
|
||||
val nopack: Boolean = false
|
||||
): FileBasedLibraryWriter(libDir, currentAbiVersion), KonanLibraryLayout {
|
||||
): FileBasedLibraryWriter(libDir), KonanLibraryLayout {
|
||||
|
||||
constructor(path: String, moduleName: String, currentAbiVersion: Int, target: KonanTarget, nopack: Boolean):
|
||||
this(File(path), moduleName, currentAbiVersion, target, nopack)
|
||||
constructor(path: String, moduleName: String, versions: KonanLibraryVersioning, target: KonanTarget, nopack: Boolean):
|
||||
this(File(path), moduleName, versions, target, nopack)
|
||||
|
||||
override val libraryName = libDir.path
|
||||
val klibFile
|
||||
@@ -53,7 +54,7 @@ class LibraryWriterImpl(
|
||||
resourcesDir.mkdirs()
|
||||
// TODO: <name>:<hash> will go somewhere around here.
|
||||
manifestProperties.setProperty(KLIB_PROPERTY_UNIQUE_NAME, moduleName)
|
||||
manifestProperties.setProperty(KLIB_PROPERTY_ABI_VERSION, currentAbiVersion.toString())
|
||||
manifestProperties.writeKonanLibraryVersioning(versions)
|
||||
}
|
||||
|
||||
var llvmModule: LLVMModuleRef? = null
|
||||
@@ -85,6 +86,11 @@ class LibraryWriterImpl(
|
||||
} else {
|
||||
val newValue = libraries.joinToString(" ") { it.uniqueName }
|
||||
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>,
|
||||
linkDependencies: List<KonanLibrary>,
|
||||
linkData: LinkData,
|
||||
abiVersion: Int,
|
||||
versions: KonanLibraryVersioning,
|
||||
target: KonanTarget,
|
||||
output: String,
|
||||
moduleName: String,
|
||||
@@ -119,7 +125,7 @@ internal fun buildLibrary(
|
||||
manifestProperties: Properties?,
|
||||
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
||||
|
||||
val library = LibraryWriterImpl(output, moduleName, abiVersion, target, nopack)
|
||||
val library = LibraryWriterImpl(File(output), moduleName, versions, target, nopack)
|
||||
|
||||
library.addKotlinBitcode(llvmModule)
|
||||
library.addLinkData(linkData)
|
||||
|
||||
@@ -2892,6 +2892,37 @@ task produce_dynamic(type: DynamicKonanTest) {
|
||||
"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') {
|
||||
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!")
|
||||
}
|
||||
Reference in New Issue
Block a user