[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
This commit is contained in:
Sergey Bogolepov
2022-07-20 11:32:00 +03:00
committed by Space
parent 30f1af7ce0
commit cd54afea8f
6 changed files with 27 additions and 5 deletions
@@ -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<AnalysisFlag<*>, Any> =
super.configureAnalysisFlags(collector, languageVersion).also {
val optInList = it[AnalysisFlags.optIn] as List<*>
@@ -386,6 +386,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
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)
}
}
}
@@ -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,
@@ -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)
@@ -172,7 +172,7 @@ class KonanConfigKeys {
val LAZY_IR_FOR_CACHES: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey.create("use lazy IR for cached libraries")
val PARTIAL_LINKAGE: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey.create("allows some symbols in klibs be missed")
val TEST_DUMP_OUTPUT_PATH: CompilerConfigurationKey<String?> = CompilerConfigurationKey.create("path to a file to dump the list of all available tests")
val OMIT_FRAMEWORK_BINARY: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey.create("do not generate binary in framework")
}
}
@@ -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)