From 8213df8bf26fd013eec637723808be222a686a4f Mon Sep 17 00:00:00 2001 From: Ilya Matveev Date: Thu, 20 Sep 2018 20:08:11 +0300 Subject: [PATCH] [klib-resolver] Resolve libraries passed as files by unique name (#2104) --- .../kotlin/backend/konan/KonanConfig.kt | 8 ++- .../konan/library/SearchPathResolver.kt | 54 ++++++++++++++----- .../org/jetbrains/kotlin/konan/file/File.kt | 1 + .../plugin/experimental/tasks/CInteropTask.kt | 5 +- .../experimental/tasks/KotlinNativeCompile.kt | 5 +- .../kotlin/cli/utilities/InteropCompiler.kt | 8 ++- 6 files changed, 59 insertions(+), 22 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 10b3a0e3e97..67c8712668f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -76,7 +76,13 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES) private fun resolverLogger(msg: String) = configuration.report(STRONG_WARNING, msg) - private val resolver = defaultResolver(repositories, target, distribution, ::resolverLogger).libraryResolver() + private val resolver = defaultResolver( + repositories, + libraryNames.filter { it.contains(File.separator) }, + target, + distribution, + ::resolverLogger + ).libraryResolver() internal val resolvedLibraries by lazy { resolver.resolveWithDependencies( diff --git a/shared/src/library/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt b/shared/src/library/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt index 81fdfd78f88..ea79081d04a 100644 --- a/shared/src/library/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt +++ b/shared/src/library/kotlin/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt @@ -29,17 +29,20 @@ interface SearchPathResolverWithTarget: SearchPathResolver { fun defaultResolver( repositories: List, - target: KonanTarget -): SearchPathResolverWithTarget = defaultResolver(repositories, target, Distribution()) + target: KonanTarget, + distribution: Distribution = Distribution() +): SearchPathResolverWithTarget = defaultResolver(repositories, emptyList(), target, distribution) fun defaultResolver( repositories: List, + directLibs: List, target: KonanTarget, distribution: Distribution, logger: Logger = ::dummyLogger, skipCurrentDir: Boolean = false ): SearchPathResolverWithTarget = KonanLibraryProperResolver( repositories, + directLibs, target, listOf(KonanAbiVersion.CURRENT), listOf(KonanVersion.CURRENT), @@ -50,13 +53,15 @@ fun defaultResolver( fun resolverByName( repositories: List, + directLibs: List = emptyList(), distributionKlib: String? = null, localKonanDir: String? = null, skipCurrentDir: Boolean = false -): SearchPathResolver = KonanLibrarySearchPathResolver(repositories, distributionKlib, localKonanDir, skipCurrentDir) +): SearchPathResolver = KonanLibrarySearchPathResolver(repositories, directLibs, distributionKlib, localKonanDir, skipCurrentDir) internal open class KonanLibrarySearchPathResolver( repositories: List, + directLibs: List, val distributionKlib: String?, val localKonanDir: String?, val skipCurrentDir: Boolean, @@ -76,6 +81,10 @@ internal open class KonanLibrarySearchPathResolver( private val repoRoots: List by lazy { repositories.map { File(it) } } + private val directLibraries: List by lazy { + directLibs.mapNotNull { found(File(it)) }.map { createKonanLibrary(it, null) } + } + // This is the place where we specify the order of library search. override val searchRoots: List by lazy { (listOf(currentDirHead) + repoRoots + listOf(localHead, distHead, distPlatformHead)).filterNotNull() @@ -99,9 +108,24 @@ internal open class KonanLibrarySearchPathResolver( val sequence = if (given.isAbsolute) { sequenceOf(found(given)) } else { - searchRoots.asSequence().map { + // Search among user-provided libraries by unique name. + // It's a workaround for maven publication. When a library is published without Gradle metadata, + // it has a complex file name (e.g. foo-macos_x64-1.0.klib). But a dependency on this lib in manifests + // of other libs uses its unique name written in the manifest (i.e just 'foo'). So we cannot resolve this + // library by its filename. But we have this library's file (we've downloaded it using maven dependency + // resolution) so we can pass it to the compiler directly. This code takes this into account and looks for + // a library dependencies also in libs passed to the compiler as files (passed to the resolver as the + // 'directLibraries' property). + val directLibs = directLibraries.asSequence().filter { + it.uniqueName == givenPath + }.map { + it.libraryFile + } + // Search among libraries in repositoreis by library filename. + val repoLibs = searchRoots.asSequence().map { found(File(it, givenPath)) } + directLibs + repoLibs } return sequence.filterNotNull() } @@ -144,16 +168,18 @@ internal open class KonanLibrarySearchPathResolver( } internal class KonanLibraryProperResolver( - repositories: List, - override val target: KonanTarget, - override val knownAbiVersions: List?, - override val knownCompilerVersions: List?, - distributionKlib: String?, - localKonanDir: String?, - skipCurrentDir: Boolean, - override val logger: Logger = ::dummyLogger -): KonanLibrarySearchPathResolver(repositories, distributionKlib, localKonanDir, skipCurrentDir, logger), SearchPathResolverWithTarget { - + repositories: List, + directLibs: List, + override val target: KonanTarget, + override val knownAbiVersions: List?, + override val knownCompilerVersions: List?, + distributionKlib: String?, + localKonanDir: String?, + skipCurrentDir: Boolean, + override val logger: Logger = ::dummyLogger +) : KonanLibrarySearchPathResolver(repositories, directLibs, distributionKlib, localKonanDir, skipCurrentDir, logger), + SearchPathResolverWithTarget +{ override val distPlatformHead: File? get() = distributionKlib?.File()?.child("platform")?.child(target.visibleName) diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt index 384d8264f53..66431182694 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/File.kt @@ -158,6 +158,7 @@ data class File constructor(internal val javaPath: Path) { val javaHome get() = File(System.getProperty("java.home")) val pathSeparator = java.io.File.pathSeparator + val separator = java.io.File.separator } fun readStrings() = mutableListOf().also { list -> forEachLine{list.add(it)}} diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt index 870e43e2edc..e7e0383d6d1 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/CInteropTask.kt @@ -106,9 +106,8 @@ open class CInteropTask @Inject constructor(val settings: CInteropSettingsImpl): addArgs("-copt", allHeadersDirs.map { "-I${it.absolutePath}" }) addArgs("-headerFilterAdditionalSearchPrefix", headerFilterDirs.map { it.absolutePath }) - libraries.files.forEach { library -> - library.parent?.let { addArg("-r", it) } - addArg("-l", library.nameWithoutExtension) + libraries.files.forEach { + addArg("-l", it.absolutePath) } addAll(extraOpts) diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt index 8b61c12046d..5ffd633e757 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/tasks/KotlinNativeCompile.kt @@ -157,9 +157,8 @@ open class KotlinNativeCompile @Inject constructor(internal val binary: Abstract addAll(additionalCompilerOptions) - libraries.files.forEach {library -> - library.parent?.let { addArg("-r", it) } - addArg("-l", library.nameWithoutExtension) + libraries.files.forEach { + addArg("-l", it.absolutePath) } addListArg("-linker-options", linkerOpts) diff --git a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt index 5ca1a6a76be..34513ba724f 100644 --- a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt +++ b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.konan.KonanAbiVersion import org.jetbrains.kotlin.konan.library.* +import org.jetbrains.kotlin.konan.target.Distribution import org.jetbrains.kotlin.native.interop.gen.jvm.interop import org.jetbrains.kotlin.utils.addIfNotNull @@ -54,7 +55,12 @@ fun invokeInterop(flavor: String, args: Array): Array { val manifest = File(buildDir, "manifest.properties") val target = PlatformManager().targetManager(targetRequest).target - val resolver = defaultResolver(repos, target).libraryResolver() + val resolver = defaultResolver( + repos, + libraries.filter { it.contains(File.separator) }, + target, + Distribution() + ).libraryResolver() val allLibraries = resolver.resolveWithDependencies( libraries.toUnresolvedLibraries, noStdLib = true, noDefaultLibs = noDefaultLibs ).getFullList()