diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index abca7b02a30..988539cec82 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -70,11 +70,6 @@ class K2Native : CLICompiler() { configuration.put(CommonConfigurationKeys.METADATA_VERSION, KonanMetadataVersion.INSTANCE) } - if (konanConfig.linkOnly) { - configuration.report(WARNING, "You have not specified any source files. " + - "Only libraries will be used to produce the output binary.") - } - try { runTopLevelPhases(konanConfig, environment) } catch (e: KonanCompilationException) { @@ -95,7 +90,7 @@ class K2Native : CLICompiler() { } val K2NativeCompilerArguments.isUsefulWithoutFreeArgs: Boolean - get() = this.listTargets || this.listPhases || this.checkDependencies || this.libraries?.isNotEmpty() ?: false + get() = listTargets || listPhases || checkDependencies || !sourceLibraries.isNullOrEmpty() fun Array?.toNonNullList(): List { return this?.asList() ?: listOf() @@ -195,7 +190,7 @@ class K2Native : CLICompiler() { else -> put(GENERATE_TEST_RUNNER, TestRunnerKind.NONE) } // We need to download dependencies only if we use them ( = there are files to compile). - put(CHECK_DEPENDENCIES, if (configuration.kotlinSourceRoots.isNotEmpty()) { + put(CHECK_DEPENDENCIES, if (configuration.kotlinSourceRoots.isNotEmpty() || !arguments.sourceLibraries.isNullOrEmpty()) { true } else { arguments.checkDependencies @@ -204,6 +199,7 @@ class K2Native : CLICompiler() { put(FRIEND_MODULES, arguments.friendModules!!.split(File.pathSeparator).filterNot(String::isEmpty)) put(EXPORTED_LIBRARIES, selectExportedLibraries(configuration, arguments, outputKind)) + put(SOURCE_LIBRARIES, selectSourceLibraries(configuration, arguments, outputKind)) put(FRAMEWORK_IMPORT_HEADERS, arguments.frameworkImportHeaders.toNonNullList()) arguments.emitLazyObjCHeader?.let { put(EMIT_LAZY_OBJC_HEADER_FILE, it) } @@ -305,5 +301,22 @@ private fun selectExportedLibraries( } } +private fun selectSourceLibraries( + configuration: CompilerConfiguration, + arguments: K2NativeCompilerArguments, + outputKind: CompilerOutputKind +): List { + val sourceLibraries = arguments.sourceLibraries?.toList().orEmpty() + val produceBinaryOrBitcode = outputKind.let { it.isNativeBinary || it == CompilerOutputKind.BITCODE } + + return if (sourceLibraries.isNotEmpty() && !produceBinaryOrBitcode) { + configuration.report(ERROR, "The $SOURCE_LIBRARY_ARG flag is only supported when producing native binaries or bitcode files, " + + "but the compiler is producing ${outputKind.name.toLowerCase()}") + emptyList() + } else { + sourceLibraries + } +} + fun main(args: Array) = K2Native.main(args) diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt index 20bf4a8fb7d..77930c5780f 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -157,6 +157,15 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xruntime", deprecatedName = "--runtime", valueDescription = "", description = "Override standard 'runtime.bc' location") var runtimeFile: String? = null + // TODO: Rename? + // TODO: Improve description + @Argument( + value = SOURCE_LIBRARY_ARG, + valueDescription = "", + description = "Produce an output binary from a klibrary instead of source files" + ) + var sourceLibraries: Array? = null + @Argument(value = STATIC_FRAMEWORK_FLAG, description = "Create a framework with a static library instead of a dynamic one") var staticFramework: Boolean = false @@ -208,3 +217,4 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { const val EMBED_BITCODE_FLAG = "-Xembed-bitcode" const val EMBED_BITCODE_MARKER_FLAG = "-Xembed-bitcode-marker" const val STATIC_FRAMEWORK_FLAG = "-Xstatic-framework" +const val SOURCE_LIBRARY_ARG = "-Xsource-library" 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 42af8378942..2f4fbf11707 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 @@ -39,10 +39,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration internal val target = targetManager.target internal val phaseConfig = configuration.get(CLIConfigurationKeys.PHASE_CONFIG)!! - val linkOnly: Boolean = - configuration.kotlinSourceRoots.isEmpty() && libraryNames.isNotEmpty() && produce.isNativeBinary - - val infoArgsOnly = configuration.kotlinSourceRoots.isEmpty() && !linkOnly + val infoArgsOnly = configuration.kotlinSourceRoots.isEmpty() && configuration[KonanConfigKeys.SOURCE_LIBRARIES].isNullOrEmpty() // TODO: debug info generation mode and debug/release variant selection probably requires some refactoring. val debug: Boolean get() = configuration.getBoolean(KonanConfigKeys.DEBUG) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index afd35a32ab8..d4a9949f27b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -94,10 +94,12 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("library search path repositories") val RUNTIME_FILE: CompilerConfigurationKey = CompilerConfigurationKey.create("override default runtime file path") + val SOURCE_LIBRARIES: CompilerConfigurationKey> + = CompilerConfigurationKey("a klibraries used to produce the final binaries instead of source code") // TODO: Better description. val SOURCE_MAP: CompilerConfigurationKey> = CompilerConfigurationKey.create("generate source map") val STATIC_FRAMEWORK: CompilerConfigurationKey - = CompilerConfigurationKey.create("Produce a static library for a framework") + = CompilerConfigurationKey.create("produce a static library for a framework") val TARGET: CompilerConfigurationKey = CompilerConfigurationKey.create("target we compile for") val TEMPORARY_FILES_DIR: CompilerConfigurationKey