[WIP] Handle konan options a bit more uniformely
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 d8b30b5..e97b9e0 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
@@ -17,20 +17,75 @@
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.config.phaseConfig
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.target.*
+import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.util.visibleName
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.util.removeSuffixIfPresent
import org.jetbrains.kotlin.utils.KotlinNativePaths
import java.nio.file.Files
import java.nio.file.Paths
+import kotlin.properties.PropertyDelegateProvider
+import kotlin.properties.ReadOnlyProperty
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
+
+ // FIXME () -> AAAAAAAAAAAA
+ private val systemCacheFlavor = mutableListOf<() -> String?>()
+ private val userCacheFlavor = mutableListOf<() -> String?>()
+ private var ignoreCacheReason0: String? = null // FIXME use or delete
+
+ private data class Config<C, D>(val configured: C, val default: D)
+
+ private fun <C, R> option(
+ configKey: CompilerConfigurationKey<C>,
+ default: () -> R,
+ altersSystemCache: Boolean = false,
+ altersUserCache: Boolean = false,
+ invalidatesCaches: Boolean = false,
+ transform: Config<C, R>.() -> R,
+ ): PropertyDelegateProvider<KonanConfig, ReadOnlyProperty<KonanConfig, R>> =
+ PropertyDelegateProvider { _, property ->
+ val configured = configuration.get(configKey)
+ val lazyDefault = lazy { default() }
+ val lazyValue = lazy { configured?.let { Config<C, R>(it, lazyDefault.value).transform() } ?: lazyDefault.value }
+
+ val flavor = {
+ "-${property.name}${lazyValue.value}" // TODO mangle properly?
+ .takeIf { lazyValue.value != lazyDefault.value }
+ }
+ if (altersSystemCache) {
+ systemCacheFlavor += flavor
+ }
+ if (altersUserCache) {
+ userCacheFlavor += flavor
+ }
+
+ ReadOnlyProperty { _, _ -> lazyValue.value }
+ }
+
+ @JvmName("optionSameType")
+ private fun <T> option(
+ configKey: CompilerConfigurationKey<T>,
+ default: () -> T,
+ altersSystemCache: Boolean = false,
+ altersUserCache: Boolean = false,
+ invalidatesCaches: Boolean = false,
+ ) = option<T, T>(
+ configKey,
+ default,
+ altersSystemCache = altersSystemCache,
+ altersUserCache = altersUserCache,
+ invalidatesCaches = invalidatesCaches
+ ) { configured }
+
+
internal val distribution = run {
val overridenProperties = mutableMapOf<String, String>().apply {
configuration.get(KonanConfigKeys.OVERRIDE_KONAN_PROPERTIES)?.let(this::putAll)
@@ -57,73 +112,101 @@
val useLlvmOpaquePointers = true
// TODO: debug info generation mode and debug/release variant selection probably requires some refactoring.
- val debug: Boolean get() = configuration.getBoolean(KonanConfigKeys.DEBUG)
- val lightDebug: Boolean = configuration.get(KonanConfigKeys.LIGHT_DEBUG)
- ?: target.family.isAppleFamily // Default is true for Apple targets.
- val generateDebugTrampoline = debug && configuration.get(KonanConfigKeys.GENERATE_DEBUG_TRAMPOLINE) ?: false
- val optimizationsEnabled = configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
+ val debug: Boolean by option(KonanConfigKeys.DEBUG, default = { false }, altersSystemCache = true, altersUserCache = true)
+ // FIXME CompilerConfigurationKey<Boolean?>
+ val lightDebug: Boolean by option(KonanConfigKeys.LIGHT_DEBUG, default = { target.family.isAppleFamily }) { configured ?: default }
+ val generateDebugTrampoline by option(KonanConfigKeys.GENERATE_DEBUG_TRAMPOLINE, default = { false }) {
+ debug && (configured == true)
+ }
+ val optimizationsEnabled by option(KonanConfigKeys.OPTIMIZATION, default = { false }, invalidatesCaches = true)
- val smallBinary: Boolean get() = configuration.get(BinaryOptions.smallBinary)
- ?: (target.needSmallBinary() || debug)
+ val smallBinary: Boolean by option(BinaryOptions.smallBinary, default = { target.needSmallBinary() || debug })
- val assertsEnabled = configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
+ // FIXME how about caches?
+ val assertsEnabled by option(KonanConfigKeys.ENABLE_ASSERTIONS, default = { false })
- val sanitizer = configuration.get(BinaryOptions.sanitizer)?.takeIf {
- when {
- it != SanitizerKind.THREAD -> "${it.name} sanitizer is not supported yet"
- produce == CompilerOutputKind.STATIC -> "${it.name} sanitizer is unsupported for static library"
- produce == CompilerOutputKind.FRAMEWORK && produceStaticFramework -> "${it.name} sanitizer is unsupported for static framework"
- it !in target.supportedSanitizers() -> "${it.name} sanitizer is unsupported on ${target.name}"
+ val sanitizer by option<SanitizerKind, SanitizerKind?>(
+ BinaryOptions.sanitizer,
+ default = { null },
+ altersSystemCache = true,
+ altersUserCache = true,
+ ) {
+ val notSupportedReason = when {
+ configured != SanitizerKind.THREAD -> "yet"
+ produce == CompilerOutputKind.STATIC -> "for static library"
+ produce == CompilerOutputKind.FRAMEWORK && produceStaticFramework -> "for static framework"
+ configured !in target.supportedSanitizers() -> "on ${target.name}"
else -> null
- }?.let { message ->
- configuration.report(CompilerMessageSeverity.STRONG_WARNING, message)
- return@takeIf false
}
- return@takeIf true
+ if (notSupportedReason != null) {
+ configuration.report(
+ CompilerMessageSeverity.STRONG_WARNING,
+ "${configured.name} sanitizer is not supported $notSupportedReason"
+ )
+ return@option default
+ }
+ return@option configured
}
- private val defaultGC get() = GC.PARALLEL_MARK_CONCURRENT_SWEEP
- val gc: GC get() = configuration.get(BinaryOptions.gc) ?: run {
- if (swiftExport) GC.CONCURRENT_MARK_AND_SWEEP else defaultGC
+ val swiftExport: Boolean by option(BinaryOptions.swiftExport, default = { false }) {
+ if (configured && !target.supportsObjcInterop()) {
+ configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Swift Export cannot be enabled on $target that does not have objc interop")
+ false
+ } else configured
}
- val runtimeAssertsMode: RuntimeAssertsMode get() = configuration.get(BinaryOptions.runtimeAssertionsMode) ?: RuntimeAssertsMode.IGNORE
- val checkStateAtExternalCalls: Boolean get() = configuration.get(BinaryOptions.checkStateAtExternalCalls) ?: false
- private val defaultDisableMmap get() = target.family == Family.MINGW || !pagedAllocator
- val disableMmap: Boolean by lazy {
- when (configuration.get(BinaryOptions.disableMmap)) {
- null -> defaultDisableMmap
+
+ val gc: GC by option(
+ BinaryOptions.gc,
+ default = { if (swiftExport) GC.CONCURRENT_MARK_AND_SWEEP else GC.PARALLEL_MARK_CONCURRENT_SWEEP }, // FIXME something wired was here
+ altersSystemCache = true,
+ )
+
+ val runtimeAssertsMode: RuntimeAssertsMode by option(
+ BinaryOptions.runtimeAssertionsMode,
+ default = { RuntimeAssertsMode.IGNORE },
+ altersSystemCache = true
+ )
+
+ val checkStateAtExternalCalls: Boolean by option(
+ BinaryOptions.checkStateAtExternalCalls,
+ default = { false },
+ altersSystemCache = true,
+ altersUserCache = true,
+ )
+ val disableMmap: Boolean by option(
+ BinaryOptions.disableMmap,
+ default = { target.family == Family.MINGW || !pagedAllocator },
+ altersSystemCache = true
+ ) {
+ when (configured) {
true -> true
false -> {
if (target.family == Family.MINGW) {
configuration.report(CompilerMessageSeverity.STRONG_WARNING, "MinGW target does not support mmap/munmap")
- true
+ true // FIXME should this be reflected in default?
} else {
- false
+ false // FIXME should this be reflected in default?
}
}
}
}
- val mmapTag: UByte by lazy {
- configuration.get(BinaryOptions.mmapTag)?.let {
- if (it > 255U) {
- configuration.report(CompilerMessageSeverity.ERROR, "mmap tag must be between 1 and 255")
- }
- it.toUByte()
- } ?: 246U // doesn't seem to be used in the wild.
- }
- val packFields: Boolean by lazy {
- configuration.get(BinaryOptions.packFields) ?: true
+
+ // 246 doesn't seem to be used in the wild.
+ val mmapTag: UByte by option(BinaryOptions.mmapTag, default = { 246U }) {
+ if (configured > 255U) {
+ configuration.report(CompilerMessageSeverity.ERROR, "mmap tag must be between 1 and 255")
+ }
+ configured.toUByte()
}
- val runtimeLogsEnabled: Boolean by lazy {
- configuration.get(KonanConfigKeys.RUNTIME_LOGS) != null
- }
+ val packFields: Boolean by option(BinaryOptions.packFields, default = { true })
- val runtimeLogs: Map<LoggingTag, LoggingLevel> by lazy {
- val default = LoggingTag.entries.associateWith { LoggingLevel.None }
+ val runtimeLogsEnabled: Boolean by option(KonanConfigKeys.RUNTIME_LOGS, default = { false }, invalidatesCaches = true) { true }
- val cfgString = configuration.get(KonanConfigKeys.RUNTIME_LOGS) ?: return@lazy default
-
+ val runtimeLogs: Map<LoggingTag, LoggingLevel> by option(
+ KonanConfigKeys.RUNTIME_LOGS,
+ default = { LoggingTag.entries.associateWith { LoggingLevel.None } }
+ ) {
fun <T> error(message: String): T? {
configuration.report(CompilerMessageSeverity.STRONG_WARNING, "$message. No logging will be performed.")
return null
@@ -143,164 +226,136 @@
return tag?.let { t -> level?.let { l -> Pair(t, l) } }
}
- val configured = cfgString.split(",").map { parseSingleTagLevel(it) ?: return@lazy default }
- default + configured
+ default + configured.split(",").map { parseSingleTagLevel(it) ?: return@option default }
}
- val suspendFunctionsFromAnyThreadFromObjC: Boolean by lazy {
- configuration.get(BinaryOptions.objcExportSuspendFunctionLaunchThreadRestriction) !=
- ObjCExportSuspendFunctionLaunchThreadRestriction.MAIN
+ val suspendFunctionsFromAnyThreadFromObjC: Boolean by option(BinaryOptions.objcExportSuspendFunctionLaunchThreadRestriction, default = { false }) {
+ configured == ObjCExportSuspendFunctionLaunchThreadRestriction.NONE
}
- val sourceInfoType: SourceInfoType
- get() = configuration.get(BinaryOptions.sourceInfoType)
- ?: SourceInfoType.CORESYMBOLICATION.takeIf { debug && target.supportsCoreSymbolication() }
- ?: SourceInfoType.NOOP
+ val sourceInfoType: SourceInfoType by option(
+ BinaryOptions.sourceInfoType,
+ default = { if (debug && target.supportsCoreSymbolication()) SourceInfoType.CORESYMBOLICATION else SourceInfoType.NOOP }
+ )
- val coreSymbolicationUseOnlyKotlinImage: Boolean
- get() = when (configuration.get(BinaryOptions.coreSymbolicationImageListType)) {
- CoreSymbolicationImageListType.ALL_LOADED -> false
- null,
- CoreSymbolicationImageListType.ONLY_KOTLIN -> true
- }
+ val coreSymbolicationUseOnlyKotlinImage: Boolean by option(BinaryOptions.coreSymbolicationImageListType, default = { true }) {
+ configured == CoreSymbolicationImageListType.ONLY_KOTLIN
+ }
- val defaultGCSchedulerType
- get() =
- when (gc) {
- GC.NOOP -> GCSchedulerType.MANUAL
- else -> GCSchedulerType.ADAPTIVE
- }
-
- val gcSchedulerType: GCSchedulerType by lazy {
- val arg = configuration.get(BinaryOptions.gcSchedulerType) ?: defaultGCSchedulerType
- arg.deprecatedWithReplacement?.let { replacement ->
- configuration.report(CompilerMessageSeverity.WARNING, "Binary option gcSchedulerType=$arg is deprecated. Use gcSchedulerType=$replacement instead")
+ val gcSchedulerType: GCSchedulerType by option(
+ BinaryOptions.gcSchedulerType,
+ default = { if (gc == GC.NOOP) GCSchedulerType.MANUAL else GCSchedulerType.ADAPTIVE },
+ altersSystemCache = true
+ ) {
+ configured.deprecatedWithReplacement?.let { replacement ->
+ assert(configured != default)
+ configuration.report(
+ CompilerMessageSeverity.WARNING,
+ "Binary option gcSchedulerType=$configured is deprecated. Use gcSchedulerType=$replacement instead"
+ )
replacement
- } ?: arg
+ } ?: configured
}
- private val defaultGcMarkSingleThreaded get() = target.family == Family.MINGW && gc == GC.PARALLEL_MARK_CONCURRENT_SWEEP
+ val gcMarkSingleThreaded: Boolean by option(
+ BinaryOptions.gcMarkSingleThreaded,
+ default = { target.family == Family.MINGW && gc == GC.PARALLEL_MARK_CONCURRENT_SWEEP },
+ altersSystemCache = true,
+ )
- val gcMarkSingleThreaded: Boolean by lazy {
- configuration.get(BinaryOptions.gcMarkSingleThreaded) ?: defaultGcMarkSingleThreaded
- }
+ val fixedBlockPageSize: UInt by option(
+ BinaryOptions.fixedBlockPageSize,
+ default = { 128u },
+ altersSystemCache = true
+ )
- private val defaultFixedBlockPageSize: UInt get() = 128u
+ val concurrentWeakSweep: Boolean by option(BinaryOptions.concurrentWeakSweep, default = { true }, altersSystemCache = true)
- val fixedBlockPageSize: UInt
- get() = configuration.get(BinaryOptions.fixedBlockPageSize) ?: defaultFixedBlockPageSize
+ val concurrentMarkMaxIterations: UInt by option(BinaryOptions.concurrentMarkMaxIterations, default = { 100U })
- val concurrentWeakSweep: Boolean
- get() = configuration.get(BinaryOptions.concurrentWeakSweep) ?: true
-
- val concurrentMarkMaxIterations: UInt
- get() = configuration.get(BinaryOptions.concurrentMarkMaxIterations) ?: 100U
-
- val gcMutatorsCooperate: Boolean by lazy {
- val mutatorsCooperate = configuration.get(BinaryOptions.gcMutatorsCooperate)
+ val gcMutatorsCooperate: Boolean by option(BinaryOptions.gcMutatorsCooperate, default = { true }) {
+ // FIXME reflect these checks in default?
if (gcMarkSingleThreaded) {
- if (mutatorsCooperate == true) {
+ if (configured == true) {
configuration.report(CompilerMessageSeverity.STRONG_WARNING,
"Mutators cooperation is not supported during single threaded mark")
}
false
} else if (gc == GC.CONCURRENT_MARK_AND_SWEEP) {
- if (mutatorsCooperate == true) {
+ if (configured == true) {
configuration.report(CompilerMessageSeverity.STRONG_WARNING,
"Mutators cooperation is not yet supported in CMS GC")
}
false
} else {
- mutatorsCooperate ?: true
+ configured
}
}
- val auxGCThreads: UInt by lazy {
- val auxGCThreads = configuration.get(BinaryOptions.auxGCThreads)
- if (gcMarkSingleThreaded) {
- if (auxGCThreads != null && auxGCThreads != 0U) {
- configuration.report(CompilerMessageSeverity.STRONG_WARNING,
- "Auxiliary GC workers are not supported during single threaded mark")
- }
- 0U
- } else {
- auxGCThreads ?: 0U
+ val auxGCThreads: UInt by option(BinaryOptions.auxGCThreads, default = { 0U }) {
+ if (gcMarkSingleThreaded && configured != 0U) {
+ configuration.report(
+ CompilerMessageSeverity.STRONG_WARNING,
+ "Auxiliary GC workers are not supported during single threaded mark"
+ )
}
+ configured
}
- val needCompilerVerification: Boolean
- get() = configuration.get(KonanConfigKeys.VERIFY_COMPILER)
- ?: (optimizationsEnabled || !KotlinCompilerVersion.VERSION.isRelease())
+ val needCompilerVerification: Boolean by
+ option(KonanConfigKeys.VERIFY_COMPILER, default = { optimizationsEnabled || !KotlinCompilerVersion.VERSION.isRelease() })
- val appStateTracking: AppStateTracking by lazy {
- configuration.get(BinaryOptions.appStateTracking) ?: AppStateTracking.DISABLED
- }
+ val appStateTracking: AppStateTracking by option(BinaryOptions.appStateTracking, default = { AppStateTracking.DISABLED })
- val objcDisposeOnMain: Boolean by lazy {
- configuration.get(BinaryOptions.objcDisposeOnMain) ?: true
- }
+ val objcDisposeOnMain: Boolean by option(BinaryOptions.objcDisposeOnMain, default = { true })
- val objcDisposeWithRunLoop: Boolean by lazy {
- configuration.get(BinaryOptions.objcDisposeWithRunLoop) ?: true
- }
+ val objcDisposeWithRunLoop: Boolean by option(BinaryOptions.objcDisposeWithRunLoop, default = { true })
- val objcEntryPoints: ObjCEntryPoints by lazy {
- configuration
- .get(BinaryOptions.objcExportEntryPointsPath)
- ?.let { File(it).readObjCEntryPoints() }
- ?: ObjCEntryPoints.ALL
+ val objcEntryPoints: ObjCEntryPoints by option(BinaryOptions.objcExportEntryPointsPath, default = { ObjCEntryPoints.ALL }) {
+ File(configured).readObjCEntryPoints()
}
/**
* Path to store ObjC selector to Kotlin signature mapping
*/
- val dumpObjcSelectorToSignatureMapping: String? by lazy {
- configuration.get(BinaryOptions.dumpObjcSelectorToSignatureMapping)
- }
+ val dumpObjcSelectorToSignatureMapping: String? by
+ option(BinaryOptions.dumpObjcSelectorToSignatureMapping, default = { null }) { configured }
- val enableSafepointSignposts: Boolean = configuration.get(BinaryOptions.enableSafepointSignposts)?.also {
- if (it && !target.supportsSignposts) {
- configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Signposts are not available on $target. The setting will have no effect.")
+ // Disabled by default because of KT-68928
+ val enableSafepointSignposts: Boolean by option(BinaryOptions.enableSafepointSignposts, default = { false }) {
+ if (configured && !target.supportsSignposts) {
+ configuration.report(
+ CompilerMessageSeverity.STRONG_WARNING,
+ "Signposts are not available on $target. The setting will have no effect."
+ )
}
- } ?: false // Disabled by default because of KT-68928
-
- val globalDataLazyInit: Boolean by lazy {
- configuration.get(BinaryOptions.globalDataLazyInit) ?: true
+ configured
}
- val genericSafeCasts: Boolean by lazy {
- configuration.get(BinaryOptions.genericSafeCasts)
- ?: false // For now disabled by default due to performance penalty.
- }
+ val globalDataLazyInit: Boolean by option(BinaryOptions.globalDataLazyInit, default = { true })
- internal val defaultPagedAllocator: Boolean get() = true
+ // For now disabled by default due to performance penalty.
+ val genericSafeCasts: Boolean by option(BinaryOptions.genericSafeCasts, default = { false })
- val pagedAllocator: Boolean by lazy {
- configuration.get(BinaryOptions.pagedAllocator) ?: true
- }
+ val pagedAllocator: Boolean by option(BinaryOptions.pagedAllocator, default = { true }, altersSystemCache = true)
+ // TODO not an option?
internal val bridgesPolicy: BridgesPolicy by lazy {
if (genericSafeCasts) BridgesPolicy.BOX_UNBOX_CASTS else BridgesPolicy.BOX_UNBOX_ONLY
}
- val llvmModulePasses: String? by lazy {
- configuration.get(KonanConfigKeys.LLVM_MODULE_PASSES)
- }
+ val llvmModulePasses: String? by option(KonanConfigKeys.LLVM_MODULE_PASSES, default = { null })
- val llvmLTOPasses: String? by lazy {
- configuration.get(KonanConfigKeys.LLVM_LTO_PASSES)
- }
+ val llvmLTOPasses: String? by option(KonanConfigKeys.LLVM_LTO_PASSES, default = { null })
- val preCodegenInlineThreshold: UInt by lazy {
- configuration.get(BinaryOptions.preCodegenInlineThreshold) ?: 0U
- }
+ val preCodegenInlineThreshold: UInt by option(BinaryOptions.preCodegenInlineThreshold, default = { 0U })
+ // TODO
val enableDebugTransparentStepping: Boolean
get() = target.family.isAppleFamily && (configuration.get(BinaryOptions.enableDebugTransparentStepping) ?: true)
- val latin1Strings: Boolean
- get() = configuration.get(BinaryOptions.latin1Strings) ?: false
+ val latin1Strings: Boolean by option(BinaryOptions.latin1Strings, default = { false })
init {
// NB: producing LIBRARY is enabled on any combination of hosts/targets
@@ -309,6 +364,7 @@
}
}
+ // TODO
val platform by lazy {
platformManager.platform(target).apply {
if (configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES)) {
@@ -319,7 +375,7 @@
internal val clang by lazy { platform.clang }
- internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!!
+ internal val produce: CompilerOutputKind get() = configuration.get(KonanConfigKeys.PRODUCE)!!
internal val metadataKlib get() = configuration.getBoolean(CommonConfigurationKeys.METADATA_KLIB)
@@ -363,33 +419,15 @@
return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder).map { it as KonanLibrary }
}
- private val defaultAllocationMode
- get() =
- if (sanitizer == null)
- AllocationMode.CUSTOM
- else
- AllocationMode.STD
-
- val allocationMode by lazy {
- when (configuration.get(KonanConfigKeys.ALLOCATION_MODE)) {
- null -> defaultAllocationMode
- AllocationMode.STD -> AllocationMode.STD
- AllocationMode.CUSTOM -> {
- if (sanitizer != null) {
- configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Sanitizers are useful only with the std allocator")
- }
- AllocationMode.CUSTOM
- }
+ val allocationMode by option(
+ KonanConfigKeys.ALLOCATION_MODE,
+ default = { if (sanitizer == null) AllocationMode.CUSTOM else AllocationMode.STD },
+ altersSystemCache = true
+ ) {
+ if (sanitizer != null && configured == AllocationMode.CUSTOM) {
+ configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Sanitizers are useful only with the std allocator")
}
- }
-
- val swiftExport by lazy {
- configuration.get(BinaryOptions.swiftExport)?.let {
- if (it && !target.supportsObjcInterop()) {
- configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Swift Export cannot be enabled on $target that does not have objc interop")
- false
- } else it
- } ?: false
+ configured
}
internal val runtimeNativeLibraries: List<String> = mutableListOf<String>().apply {
@@ -485,13 +523,17 @@
internal val isInteropStubs: Boolean get() = manifestProperties?.getProperty("interop") == "true"
- private val defaultPropertyLazyInitialization = true
- internal val propertyLazyInitialization: Boolean
- get() = configuration.get(KonanConfigKeys.PROPERTY_LAZY_INITIALIZATION)?.also {
- if (!it) {
- configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Eager property initialization is deprecated")
- }
- } ?: defaultPropertyLazyInitialization
+ internal val propertyLazyInitialization: Boolean by option(
+ KonanConfigKeys.PROPERTY_LAZY_INITIALIZATION,
+ default = { true },
+ altersSystemCache = true,
+ altersUserCache = true,
+ ) {
+ if (!configured) {
+ configuration.report(CompilerMessageSeverity.STRONG_WARNING, "Eager property initialization is deprecated")
+ }
+ configured
+ }
internal val lazyIrForCaches: Boolean get() = configuration.get(KonanConfigKeys.LAZY_IR_FOR_CACHES)!!
@@ -511,7 +553,11 @@
internal val testDumpFile: File? = configuration[KonanConfigKeys.TEST_DUMP_OUTPUT_PATH]?.let(::File)
- internal val useDebugInfoInNativeLibs = configuration.get(BinaryOptions.stripDebugInfoFromNativeLibs) == false
+ internal val useDebugInfoInNativeLibs: Boolean by option(
+ BinaryOptions.stripDebugInfoFromNativeLibs,
+ default = { false },
+ altersSystemCache = true,
+ ) { !configured }
internal val partialLinkageConfig = configuration.partialLinkageConfig
@@ -521,46 +567,24 @@
private fun StringBuilder.appendCommonCacheFlavor() {
append(target.toString())
- if (debug) append("-g")
- append("STATIC")
+ if (debug) append("-g") // todo from option?
+ append("STATIC") // TODO what is this?
- if (propertyLazyInitialization != defaultPropertyLazyInitialization)
- append("-lazy_init${if (propertyLazyInitialization) "ENABLE" else "DISABLE"}")
- if (sanitizer != null)
- append("-sanitizer${sanitizer.name}")
- if (checkStateAtExternalCalls) {
- append("-check_state_at_external_calls")
- }
+ systemCacheFlavor.mapNotNull { it() }.forEach { append(it) }
+ userCacheFlavor.mapNotNull { it() }.forEach { append(it) }
}
private val systemCacheFlavorString = buildString {
appendCommonCacheFlavor()
append("-system")
-
- if (useDebugInfoInNativeLibs)
- append("-runtime_debug")
- if (allocationMode != defaultAllocationMode)
- append("-allocator${allocationMode.name}")
- if (gc != defaultGC)
- append("-gc${gc.shortcut ?: gc.name.lowercase()}")
- if (gcSchedulerType != defaultGCSchedulerType)
- append("-gc_scheduler${gcSchedulerType.name}")
- if (runtimeAssertsMode != RuntimeAssertsMode.IGNORE)
- append("-runtime_asserts${runtimeAssertsMode.name}")
- if (disableMmap != defaultDisableMmap)
- append("-disable_mmap${if (disableMmap) "TRUE" else "FALSE"}")
- if (gcMarkSingleThreaded != defaultGcMarkSingleThreaded)
- append("-gc_mark_single_threaded${if (gcMarkSingleThreaded) "TRUE" else "FALSE"}")
- if (fixedBlockPageSize != defaultFixedBlockPageSize)
- append("-fixed_block_page_size$fixedBlockPageSize")
- if (pagedAllocator != defaultPagedAllocator)
- append("-paged_allocator${if (pagedAllocator) "TRUE" else "FALSE"}")
+ systemCacheFlavor.mapNotNull { it() }.forEach { append(it) }
}
private val userCacheFlavorString = buildString {
appendCommonCacheFlavor()
append("-user")
- if (partialLinkageConfig.isEnabled) append("-pl")
+ if (partialLinkageConfig.isEnabled) append("-pl") // TODO replace with option?
+ userCacheFlavor.mapNotNull { it() }.forEach { append(it) }
}
private val systemCacheRootDirectory = File(distribution.konanHome).child("klib").child("cache")