From e714f1e0679ebfd75f7334b93d28643229c86f41 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Thu, 21 Nov 2019 13:39:38 +0700 Subject: [PATCH] [Interop] Move dependency resolution into `processCLib` Because metadata mode doesn't call compiler we need to resolve dependencies (including stdlib) by hand. This logic was partially implemented in `InteropCompiler.kt`. So we move it into `processCLib`. --- .../interop/gen/jvm/InteropLibraryCreation.kt | 5 +- .../kotlin/native/interop/gen/jvm/main.kt | 63 ++++++++++++++----- .../kotlin/cli/utilities/InteropCompiler.kt | 58 +++++------------ 3 files changed, 64 insertions(+), 62 deletions(-) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt index 944c6beb996..47bcf3970d2 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.konan.library.impl.KonanLibraryWriterImpl import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.library.KotlinLibraryVersioning import org.jetbrains.kotlin.library.KotlinAbiVersion +import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.util.removeSuffixIfPresent import java.util.* @@ -24,7 +25,8 @@ data class LibraryCreationArguments( val moduleName: String, val nativeBitcodePath: String, val target: KonanTarget, - val manifest: Properties + val manifest: Properties, + val dependencies: List ) fun createInteropLibrary(arguments: LibraryCreationArguments) { @@ -47,6 +49,7 @@ fun createInteropLibrary(arguments: LibraryCreationArguments) { addMetadata(SerializedMetadata(metadata.header, metadata.fragments, metadata.fragmentNames)) addNativeBitcode(arguments.nativeBitcodePath) addManifestAddend(arguments.manifest) + addLinkDependencies(arguments.dependencies) commit() } } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt index fa54ba52aa9..21d1a64e496 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt @@ -24,8 +24,12 @@ import org.jetbrains.kotlin.native.interop.gen.wasm.processIdlLib import org.jetbrains.kotlin.native.interop.indexer.* import org.jetbrains.kotlin.native.interop.tool.* import kotlinx.cli.ArgParser -import org.jetbrains.kotlin.konan.library.KLIB_INTEROP_IR_PROVIDER_IDENTIFIER +import org.jetbrains.kotlin.konan.library.* +import org.jetbrains.kotlin.konan.target.Distribution import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.library.resolver.impl.libraryResolver +import org.jetbrains.kotlin.library.toUnresolvedLibraries import java.io.File import java.lang.IllegalArgumentException import java.nio.file.* @@ -98,15 +102,14 @@ private fun selectNativeLanguage(config: DefFile.DefFileConfig): Language { error("Unexpected language '$language'. Possible values are: ${languages.keys.joinToString { "'$it'" }}") } -private fun parseImports(imports: Array): ImportsImpl { - val headerIdToPackage = imports.map { arg -> - val (pkg, joinedIds) = arg.split(':') - val ids = joinedIds.split(';') - ids.map { HeaderId(it) to pkg } - }.reversed().flatten().toMap() - - return ImportsImpl(headerIdToPackage) -} +private fun parseImports(dependencies: List): ImportsImpl = + dependencies.filterIsInstance().mapNotNull { library -> + // TODO: handle missing properties? + library.packageFqName?.let { packageFqName -> + val headerIds = library.includedHeaders + headerIds.map { HeaderId(it) to packageFqName } + } + }.reversed().flatten().toMap().let(::ImportsImpl) fun getCompilerFlagsForVfsOverlay(headerFilterPrefix: Array, def: DefFile): List { val relativeToRoot = mutableMapOf() // TODO: handle clashes @@ -161,7 +164,6 @@ private fun findFilesByGlobs(roots: List, globs: List): Map, additionalArgs: Map = mapOf()): Array? { val cinteropArguments = CInteropArguments() cinteropArguments.argParser.parse(args) @@ -209,11 +211,19 @@ private fun processCLib(args: Array, additionalArgs: Map = val outKtPkg = fqParts.joinToString(".") - val libName = (additionalArgs["cstubsname"] as? String)?: fqParts.joinToString("") + "stubs" + val mode = parseGenerationMode(cinteropArguments.mode) + ?: error ("Unexpected interop generation mode: ${cinteropArguments.mode}") + + val allLibraryDependencies = when (flavor) { + KotlinPlatform.NATIVE -> resolveDependencies(cinteropArguments, tool.target) + else -> listOf() + } + + val libName = additionalArgs["cstubsName"] as? String ?: fqParts.joinToString("") + "stubs" val tempFiles = TempFiles(libName, cinteropArguments.tempDir) - val imports = parseImports((additionalArgs["import"] as? List)?.toTypedArray() ?: arrayOf()) + val imports = parseImports(allLibraryDependencies) val library = buildNativeLibrary(tool, def, cinteropArguments, imports) @@ -251,9 +261,6 @@ private fun processCLib(args: Array, additionalArgs: Map = {} } - val mode = parseGenerationMode(cinteropArguments.mode) - ?: error ("Unexpected interop generation mode: ${cinteropArguments.mode}") - val stubIrContext = StubIrContext(logger, configuration, nativeIndex, imports, flavor, libName) val stubIrOutput = run { val outKtFileCreator = { @@ -320,7 +327,8 @@ private fun processCLib(args: Array, additionalArgs: Map = target = tool.target, moduleName = moduleName, outputPath = cinteropArguments.output, - manifest = def.manifestAddendProperties + manifest = def.manifestAddendProperties, + dependencies = allLibraryDependencies ) createInteropLibrary(args) return null @@ -328,6 +336,27 @@ private fun processCLib(args: Array, additionalArgs: Map = } } +private fun resolveDependencies( + cinteropArguments: CInteropArguments, target: KonanTarget +): List { + val libraries = cinteropArguments.library + val repos = cinteropArguments.repo + val noDefaultLibs = cinteropArguments.nodefaultlibs || cinteropArguments.nodefaultlibsDeprecated + val noEndorsedLibs = cinteropArguments.noendorsedlibs + val resolver = defaultResolver( + repos, + libraries.filter { it.contains(org.jetbrains.kotlin.konan.file.File.separator) }, + target, + Distribution() + ).libraryResolver() + return resolver.resolveWithDependencies( + libraries.toUnresolvedLibraries, + noStdLib = false, + noDefaultLibs = noDefaultLibs, + noEndorsedLibs = noEndorsedLibs + ).getFullList() +} + internal fun prepareTool(target: String?, flavor: KotlinPlatform): ToolConfig { val tool = ToolConfig(target, flavor) tool.downloadDependencies() 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 81ac6c446b8..94112b867ac 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 @@ -5,14 +5,7 @@ package org.jetbrains.kotlin.cli.utilities import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.library.KonanLibrary -import org.jetbrains.kotlin.konan.library.defaultResolver -import org.jetbrains.kotlin.konan.library.includedHeaders -import org.jetbrains.kotlin.konan.library.packageFqName -import org.jetbrains.kotlin.konan.target.Distribution import org.jetbrains.kotlin.konan.target.PlatformManager -import org.jetbrains.kotlin.library.resolver.impl.libraryResolver -import org.jetbrains.kotlin.library.toUnresolvedLibraries import org.jetbrains.kotlin.native.interop.gen.jvm.interop import org.jetbrains.kotlin.native.interop.tool.* @@ -41,8 +34,6 @@ fun invokeInterop(flavor: String, args: Array): Array? { "-natives", nativesDir.path, "-flavor", flavor ) - val additionalProperties = mutableMapOf( - "manifest" to manifest.path) val cstubsName ="cstubs" val libraries = arguments.library val repos = arguments.repo @@ -50,54 +41,33 @@ fun invokeInterop(flavor: String, args: Array): Array? { else (arguments as JSInteropArguments).target val target = PlatformManager().targetManager(targetRequest).target - if (flavor == "native") { - val resolver = defaultResolver( - repos, - libraries.filter { it.contains(File.separator) }, - target, - Distribution() - ).libraryResolver() - val allLibraries = resolver.resolveWithDependencies( - libraries.toUnresolvedLibraries, noStdLib = true, noDefaultLibs = noDefaultLibs, - noEndorsedLibs = noEndorsedLibs - ).getFullList() as List + val cinteropArgsToCompiler = interop(flavor, args + additionalArgs, + listOfNotNull( + "manifest" to manifest.path, + ("cstubsName" to cstubsName).takeIf { flavor == "native" } + ).toMap() + ) ?: return null // There is no need in compiler invocation if we're generating only metadata. - val imports = allLibraries.map { library -> - // TODO: handle missing properties? - library.packageFqName?.let { packageFqName -> - val headerIds = library.includedHeaders - "$packageFqName:${headerIds.joinToString(";")}" - } - }.filterNotNull() - additionalProperties.putAll(mapOf("cstubsname" to cstubsName, "import" to imports)) - } - - - val cinteropArgsToCompiler = interop(flavor, args + additionalArgs, additionalProperties) - ?: return null // There is no need in compiler invocation if we're generating only metadata. - - val nativeStubs = - if (flavor == "wasm") + val nativeStubs = + if (flavor == "wasm") arrayOf("-include-binary", File(nativesDir, "js_stubs.js").path) - else + else arrayOf("-native-library", File(nativesDir, "$cstubsName.bc").path) - val konancArgs = arrayOf( - generatedDir.path, - "-produce", "library", + return arrayOf( + generatedDir.path, + "-produce", "library", "-o", outputFileName, "-target", target.visibleName, "-manifest", manifest.path, "-Xtemporary-files-dir=$temporaryFilesDir") + nativeStubs + - cinteropArgsToCompiler + - libraries.flatMap { listOf("-library", it) } + + cinteropArgsToCompiler + + libraries.flatMap { listOf("-library", it) } + repos.flatMap { listOf("-repo", it) } + (if (noDefaultLibs) arrayOf("-$NODEFAULTLIBS") else emptyArray()) + (if (noEndorsedLibs) arrayOf("-$NOENDORSEDLIBS") else emptyArray()) + (if (purgeUserLibs) arrayOf("-$PURGE_USER_LIBS") else emptyArray()) - - return konancArgs }