From cd54afea8fc1d072d6264886540ffeae63f24f01 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Wed, 20 Jul 2022 11:32:00 +0300 Subject: [PATCH] [K/N] Add option to omit generation of binary when producing framework `-Xomit-framework-binary` is useful when the user does not care about generated machine code, but only about its public interface. Current use-case is for development purposes only: to iterate faster on ObjCExport. But potentially it can be turned into user-facing feature --- .../common/arguments/K2NativeCompilerArguments.kt | 3 +++ .../src/org/jetbrains/kotlin/cli/bc/K2Native.kt | 1 + .../jetbrains/kotlin/backend/konan/CompilerOutput.kt | 10 ++++++++-- .../jetbrains/kotlin/backend/konan/KonanConfig.kt | 12 ++++++++++++ .../kotlin/backend/konan/KonanConfigurationKeys.kt | 2 +- .../jetbrains/kotlin/backend/konan/ToplevelPhases.kt | 4 ++-- 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt index a3075f61859..d196dbf7853 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2NativeCompilerArguments.kt @@ -387,6 +387,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xpartial-linkage", description = "Allow unlinked symbols") var partialLinkage: Boolean = false + @Argument(value = "-Xomit-framework-binary", description = "Omit binary when compiling framework") + var omitFrameworkBinary: Boolean = false + override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap, Any> = super.configureAnalysisFlags(collector, languageVersion).also { val optInList = it[AnalysisFlags.optIn] as List<*> diff --git a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index 84de4596a0a..002e3565816 100644 --- a/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/kotlin-native/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -386,6 +386,7 @@ class K2Native : CLICompiler() { putIfNotNull(BUNDLE_ID, parseBundleId(arguments, outputKind, configuration)) arguments.testDumpOutputPath?.let { put(TEST_DUMP_OUTPUT_PATH, it) } put(PARTIAL_LINKAGE, arguments.partialLinkage) + put(OMIT_FRAMEWORK_BINARY, arguments.omitFrameworkBinary) } } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 97158c3b68e..aa55e666d5e 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -30,9 +30,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty */ val KonanConfig.isFinalBinary: Boolean get() = when (this.produce) { CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC, - CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true + CompilerOutputKind.STATIC -> true CompilerOutputKind.DYNAMIC_CACHE, CompilerOutputKind.STATIC_CACHE, CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false + CompilerOutputKind.FRAMEWORK -> !omitFrameworkBinary } val CompilerOutputKind.involvesBitcodeGeneration: Boolean @@ -45,8 +46,9 @@ val KonanConfig.involvesLinkStage: Boolean get() = when (this.produce) { CompilerOutputKind.PROGRAM, CompilerOutputKind.DYNAMIC, CompilerOutputKind.DYNAMIC_CACHE, CompilerOutputKind.STATIC_CACHE, - CompilerOutputKind.STATIC, CompilerOutputKind.FRAMEWORK -> true + CompilerOutputKind.STATIC-> true CompilerOutputKind.LIBRARY, CompilerOutputKind.BITCODE -> false + CompilerOutputKind.FRAMEWORK -> !omitFrameworkBinary } val CompilerOutputKind.isCache: Boolean @@ -183,6 +185,10 @@ internal fun produceOutput(context: Context) { val produce = config.get(KonanConfigKeys.PRODUCE) if (produce == CompilerOutputKind.FRAMEWORK) { context.objCExport.produceFrameworkInterface() + if (context.config.omitFrameworkBinary) { + // Compiler does not compile anything in this mode, so return early. + return + } } when (produce) { CompilerOutputKind.STATIC, diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 173898cb2c4..af4613a08ba 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -397,6 +397,18 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration && librariesToCache.isEmpty() && configuration[KonanConfigKeys.EXPORTED_LIBRARIES].isNullOrEmpty() + /** + * Do not compile binary when compiling framework. + * This is useful when user care only about framework's interface. + */ + internal val omitFrameworkBinary: Boolean by lazy { + configuration.getBoolean(KonanConfigKeys.OMIT_FRAMEWORK_BINARY).also { + if (it && produce != CompilerOutputKind.FRAMEWORK) { + configuration.report(CompilerMessageSeverity.STRONG_WARNING, + "Trying to disable framework binary compilation when producing ${produce.name.lowercase()} is meaningless.") + } + } + } } fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index 29730d7fedc..12d805814c6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -172,7 +172,7 @@ class KonanConfigKeys { val LAZY_IR_FOR_CACHES: CompilerConfigurationKey = CompilerConfigurationKey.create("use lazy IR for cached libraries") val PARTIAL_LINKAGE: CompilerConfigurationKey = CompilerConfigurationKey.create("allows some symbols in klibs be missed") val TEST_DUMP_OUTPUT_PATH: CompilerConfigurationKey = CompilerConfigurationKey.create("path to a file to dump the list of all available tests") - + val OMIT_FRAMEWORK_BINARY: CompilerConfigurationKey = CompilerConfigurationKey.create("do not generate binary in framework") } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index eba71042f14..9a3b38f3d05 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -622,7 +622,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) { disableUnless(entryPointPhase, config.produce == CompilerOutputKind.PROGRAM) disableUnless(buildAdditionalCacheInfoPhase, config.produce.isCache && config.lazyIrForCaches) disableUnless(exportInternalAbiPhase, config.produce.isCache) - disableIf(backendCodegen, config.produce == CompilerOutputKind.LIBRARY) + disableIf(backendCodegen, config.produce == CompilerOutputKind.LIBRARY || config.omitFrameworkBinary) disableUnless(checkExternalCallsPhase, getBoolean(KonanConfigKeys.CHECK_EXTERNAL_CALLS)) disableUnless(rewriteExternalCallsCheckerGlobals, getBoolean(KonanConfigKeys.CHECK_EXTERNAL_CALLS)) disableUnless(stringConcatenationTypeNarrowingPhase, config.optimizationsEnabled) @@ -655,7 +655,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) { disableUnless(removeRedundantSafepointsPhase, config.memoryModel == MemoryModel.EXPERIMENTAL) - if (config.metadataKlib) { + if (config.metadataKlib || config.omitFrameworkBinary) { disable(psiToIrPhase) disable(copyDefaultValuesToActualPhase) disable(specialBackendChecksPhase)