You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
5.5 KiB
127 lines
5.5 KiB
/* |
|
* Copyright 2020-2023 JetBrains s.r.o. and respective authors and developers. |
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. |
|
*/ |
|
|
|
package org.jetbrains.compose.experimental.internal |
|
|
|
import org.gradle.api.Project |
|
import org.jetbrains.compose.internal.KOTLIN_MPP_PLUGIN_ID |
|
import org.jetbrains.compose.internal.mppExt |
|
import org.jetbrains.compose.internal.utils.KGPPropertyProvider |
|
import org.jetbrains.compose.internal.utils.configureEachWithType |
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion |
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget |
|
import org.jetbrains.kotlin.konan.target.KonanTarget |
|
import org.jetbrains.kotlin.konan.target.presetName |
|
|
|
private const val PROJECT_CACHE_KIND_PROPERTY_NAME = "kotlin.native.cacheKind" |
|
private const val COMPOSE_NATIVE_MANAGE_CACHE_KIND = "compose.kotlin.native.manageCacheKind" |
|
private const val NONE_VALUE = "none" |
|
|
|
// Compose runtime supports these k/native targets: |
|
// https://github.com/JetBrains/compose-multiplatform-core/blob/jb-main/compose/runtime/runtime/build.gradle#L75 |
|
private val SUPPORTED_NATIVE_TARGETS = setOf( |
|
// ios |
|
KonanTarget.IOS_X64, |
|
KonanTarget.IOS_ARM64, |
|
KonanTarget.IOS_SIMULATOR_ARM64, |
|
// macos |
|
KonanTarget.MACOS_X64, |
|
KonanTarget.MACOS_ARM64, |
|
// tvos |
|
KonanTarget.TVOS_X64, |
|
KonanTarget.TVOS_ARM64, |
|
KonanTarget.TVOS_SIMULATOR_ARM64, |
|
// watchOS |
|
KonanTarget.WATCHOS_ARM64, |
|
KonanTarget.WATCHOS_ARM32, |
|
KonanTarget.WATCHOS_X64, |
|
KonanTarget.WATCHOS_SIMULATOR_ARM64, |
|
// mingw |
|
KonanTarget.MINGW_X64, |
|
// linux |
|
KonanTarget.LINUX_X64, |
|
) |
|
|
|
internal val SUPPORTED_NATIVE_CACHE_KIND_PROPERTIES = |
|
SUPPORTED_NATIVE_TARGETS.map { it.targetCacheKindPropertyName } + |
|
PROJECT_CACHE_KIND_PROPERTY_NAME |
|
|
|
internal fun Project.configureNativeCompilerCaching() { |
|
if (findProperty(COMPOSE_NATIVE_MANAGE_CACHE_KIND) == "false") return |
|
|
|
plugins.withId(KOTLIN_MPP_PLUGIN_ID) { |
|
val kotlinPluginVersion = kotlinVersionNumbers(project.getKotlinPluginVersion()) |
|
mppExt.targets.configureEachWithType<KotlinNativeTarget> { |
|
if (konanTarget in SUPPORTED_NATIVE_TARGETS) { |
|
checkExplicitCacheKind() |
|
if (kotlinPluginVersion < KotlinVersion(1, 9, 20)) { |
|
// Pre-1.9.20 Kotlin compiler caches have known compatibility issues |
|
// See KT-57329, KT-61270 |
|
disableKotlinNativeCache() |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
private fun KotlinNativeTarget.checkExplicitCacheKind() { |
|
// To determine cache kind KGP checks kotlin.native.cacheKind.<PRESET_NAME> first, then kotlin.native.cacheKind |
|
// For each property it tries to read Project.property, then checks local.properties |
|
// See https://github.com/JetBrains/kotlin/blob/d4d30dcfcf1afb083f09279c6f1ba05031efeabb/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt#L416 |
|
val cacheKindProperties = listOf(targetCacheKindPropertyName, PROJECT_CACHE_KIND_PROPERTY_NAME) |
|
val propertyProviders = listOf( |
|
KGPPropertyProvider.GradleProperties(project), |
|
KGPPropertyProvider.LocalProperties(project) |
|
) |
|
|
|
for (cacheKindProperty in cacheKindProperties) { |
|
for (provider in propertyProviders) { |
|
val value = provider.valueOrNull(cacheKindProperty) |
|
if (value != null) { |
|
error(explicitCacheKindErrorMessage(cacheKindProperty, value, provider)) |
|
} |
|
} |
|
} |
|
} |
|
|
|
private fun explicitCacheKindErrorMessage( |
|
cacheKindProperty: String, |
|
value: String, |
|
provider: KGPPropertyProvider |
|
) = """ |
|
|Error: '$cacheKindProperty' is explicitly set to '$value'. |
|
|This option significantly slows the Kotlin/Native compiler. |
|
|Compose Multiplatform Gradle plugin manages this property automatically based on a Kotlin compiler version being used. |
|
| * Recommended action: remove explicit '$cacheKindProperty=$value' from ${provider.location}. |
|
| * Alternative action: disable cache kind management by adding '$COMPOSE_NATIVE_MANAGE_CACHE_KIND=false' to your 'gradle.properties'. |
|
""".trimMargin() |
|
|
|
|
|
private val KotlinNativeTarget.targetCacheKindPropertyName: String |
|
get() = konanTarget.targetCacheKindPropertyName |
|
|
|
private val KonanTarget.targetCacheKindPropertyName: String |
|
get() = "$PROJECT_CACHE_KIND_PROPERTY_NAME.${presetName}" |
|
|
|
private fun KotlinNativeTarget.disableKotlinNativeCache() { |
|
val existingValue = project.findProperty(targetCacheKindPropertyName)?.toString() |
|
if (NONE_VALUE.equals(existingValue, ignoreCase = true)) return |
|
|
|
if (targetCacheKindPropertyName in project.properties) { |
|
project.setProperty(targetCacheKindPropertyName, NONE_VALUE) |
|
} else { |
|
project.extensions.extraProperties.set(targetCacheKindPropertyName, NONE_VALUE) |
|
} |
|
} |
|
|
|
internal fun kotlinVersionNumbers(version: String): KotlinVersion { |
|
val m = Regex("(\\d+)\\.(\\d+)\\.(\\d+)").find(version) ?: error("Kotlin version has unexpected format: '$version'") |
|
val (_, majorPart, minorPart, patchPart) = m.groupValues |
|
return KotlinVersion( |
|
major = majorPart.toIntOrNull() ?: error("Could not parse major part '$majorPart' of Kotlin plugin version: '$version'"), |
|
minor = minorPart.toIntOrNull() ?: error("Could not parse minor part '$minorPart' of Kotlin plugin version: '$version'"), |
|
patch = patchPart.toIntOrNull() ?: error("Could not parse patch part '$patchPart' of Kotlin plugin version: '$version'"), |
|
) |
|
}
|
|
|