Browse Source
Set Kotlin/Native cache kind based on Kotlin version Resolves #2046 Resolves #2386pull/3502/head v1.5.0-beta02
Alexey Tsvetkov
1 year ago
committed by
GitHub
23 changed files with 439 additions and 58 deletions
@ -0,0 +1,114 @@
|
||||
/* |
||||
* 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.ComposeMultiplatformBuildService |
||||
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.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" |
||||
|
||||
internal fun Project.configureNativeCompilerCaching() { |
||||
if (findProperty(COMPOSE_NATIVE_MANAGE_CACHE_KIND) == "false") return |
||||
|
||||
plugins.withId(KOTLIN_MPP_PLUGIN_ID) { |
||||
val kotlinVersion = kotlinVersionNumbers(this) |
||||
mppExt.targets.configureEachWithType<KotlinNativeTarget> { |
||||
checkCacheKindUserValueIsNotNone() |
||||
configureTargetCompilerCache(kotlinVersion) |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun KotlinNativeTarget.checkCacheKindUserValueIsNotNone() { |
||||
// 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) { |
||||
if (value.equals(NONE_VALUE, ignoreCase = true)) { |
||||
ComposeMultiplatformBuildService |
||||
.getInstance(project) |
||||
.warnOnceAfterBuild(cacheKindPropertyWarningMessage(cacheKindProperty, provider)) |
||||
} |
||||
return |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun cacheKindPropertyWarningMessage( |
||||
cacheKindProperty: String, |
||||
provider: KGPPropertyProvider |
||||
) = """ |
||||
|Warning: '$cacheKindProperty' is explicitly set to `none`. |
||||
|This option significantly slows the Kotlin/Native compiler. |
||||
|Compose Multiplatform Gradle plugin can set this property automatically, |
||||
|when it is necessary. |
||||
| * Recommended action: remove explicit '$cacheKindProperty=$NONE_VALUE' from ${provider.location}. |
||||
| * Alternative action: if you are sure you need '$cacheKindProperty=$NONE_VALUE', disable |
||||
|this warning by adding '$COMPOSE_NATIVE_MANAGE_CACHE_KIND=false' to your 'gradle.properties'. |
||||
""".trimMargin() |
||||
|
||||
private fun KotlinNativeTarget.configureTargetCompilerCache(kotlinVersion: KotlinVersion) { |
||||
// See comments in https://youtrack.jetbrains.com/issue/KT-57329 |
||||
when { |
||||
// Kotlin < 1.9.0 => disable cache |
||||
kotlinVersion < KotlinVersion(1, 9, 0) -> { |
||||
disableKotlinNativeCache() |
||||
} |
||||
// 1.9.0 <= Kotlin < 1.9.20 => add -Xlazy-ir-for-caches=disable |
||||
kotlinVersion < KotlinVersion(1, 9, 20) -> { |
||||
disableLazyIrForCaches() |
||||
} |
||||
// Kotlin >= 1.9.20 => do nothing |
||||
else -> {} |
||||
} |
||||
} |
||||
|
||||
private val KotlinNativeTarget.targetCacheKindPropertyName: String |
||||
get() = "$PROJECT_CACHE_KIND_PROPERTY_NAME.${konanTarget.presetName}" |
||||
|
||||
private fun KotlinNativeTarget.disableKotlinNativeCache() { |
||||
if (project.hasProperty(targetCacheKindPropertyName)) { |
||||
project.setProperty(targetCacheKindPropertyName, NONE_VALUE) |
||||
} else { |
||||
project.extensions.extraProperties.set(targetCacheKindPropertyName, NONE_VALUE) |
||||
} |
||||
} |
||||
|
||||
private fun KotlinNativeTarget.disableLazyIrForCaches() { |
||||
compilations.configureEach { compilation -> |
||||
compilation.kotlinOptions.freeCompilerArgs += listOf("-Xlazy-ir-for-caches=disable") |
||||
} |
||||
} |
||||
|
||||
private fun kotlinVersionNumbers(project: Project): KotlinVersion { |
||||
val version = project.getKotlinPluginVersion() |
||||
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'"), |
||||
) |
||||
} |
@ -0,0 +1,18 @@
|
||||
/* |
||||
* 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.internal.utils |
||||
|
||||
import org.gradle.api.Project |
||||
import org.gradle.build.event.BuildEventsListenerRegistry |
||||
import javax.inject.Inject |
||||
|
||||
@Suppress("UnstableApiUsage") |
||||
internal abstract class BuildEventsListenerRegistryProvider @Inject constructor(val registry: BuildEventsListenerRegistry) { |
||||
companion object { |
||||
fun getInstance(project: Project): BuildEventsListenerRegistry = |
||||
project.objects.newInstance(BuildEventsListenerRegistryProvider::class.java).registry |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
/* |
||||
* 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.internal.utils |
||||
|
||||
import org.gradle.api.Project |
||||
import java.util.* |
||||
|
||||
/** |
||||
* Reads Kotlin Gradle plugin properties. |
||||
* |
||||
* Kotlin Gradle plugin supports reading property from two sources: |
||||
* 1. Gradle properties. Normally located in gradle.properties file, |
||||
* but can also be provided via command-line, <GRADLE_HOME>/gradle.properties |
||||
* or can be set via Gradle API. |
||||
* 2. local.properties file. local.properties file is not supported by Gradle out-of-the-box. |
||||
* Nevertheless, it became a widespread convention. |
||||
*/ |
||||
internal abstract class KGPPropertyProvider { |
||||
abstract fun valueOrNull(propertyName: String): String? |
||||
abstract val location: String |
||||
|
||||
class GradleProperties(private val project: Project) : KGPPropertyProvider() { |
||||
override fun valueOrNull(propertyName: String): String? = project.findProperty(propertyName)?.toString() |
||||
override val location: String = "gradle.properties" |
||||
} |
||||
|
||||
class LocalProperties(project: Project) : KGPPropertyProvider() { |
||||
private val localProperties: Properties by lazyLoadProperties(project.localPropertiesFile) |
||||
override fun valueOrNull(propertyName: String): String? = localProperties.getProperty(propertyName) |
||||
override val location: String = "local.properties" |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
plugins { |
||||
id "org.jetbrains.kotlin.multiplatform" |
||||
id "org.jetbrains.compose" |
||||
} |
||||
|
||||
kotlin { |
||||
iosX64 { |
||||
binaries.framework { |
||||
isStatic = true |
||||
baseName = "shared" |
||||
} |
||||
} |
||||
iosArm64 { |
||||
binaries.framework { |
||||
isStatic = true |
||||
baseName = "shared" |
||||
} |
||||
} |
||||
|
||||
sourceSets { |
||||
commonMain { |
||||
dependencies { |
||||
implementation(compose.runtime) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1 @@
|
||||
org.jetbrains.compose.experimental.uikit.enabled=true |
@ -0,0 +1,12 @@
|
||||
pluginManagement { |
||||
plugins { |
||||
id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' |
||||
id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' |
||||
} |
||||
repositories { |
||||
mavenLocal() |
||||
gradlePluginPortal() |
||||
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" } |
||||
} |
||||
} |
||||
rootProject.name = "nativeCacheKind" |
@ -0,0 +1,10 @@
|
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.getValue |
||||
import androidx.compose.runtime.mutableStateOf |
||||
import androidx.compose.runtime.remember |
||||
import androidx.compose.runtime.setValue |
||||
|
||||
@Composable |
||||
fun App() { |
||||
var text by remember { mutableStateOf("Hello, World!") } |
||||
} |
@ -0,0 +1,20 @@
|
||||
plugins { |
||||
id "org.jetbrains.kotlin.multiplatform" |
||||
id "org.jetbrains.compose" |
||||
} |
||||
|
||||
kotlin { |
||||
iosX64() |
||||
iosArm64() |
||||
iosSimulatorArm64() |
||||
macosX64() |
||||
macosArm64() |
||||
|
||||
sourceSets { |
||||
commonMain { |
||||
dependencies { |
||||
implementation(compose.runtime) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1 @@
|
||||
org.jetbrains.compose.experimental.uikit.enabled=true |
@ -0,0 +1,12 @@
|
||||
pluginManagement { |
||||
plugins { |
||||
id 'org.jetbrains.kotlin.multiplatform' version 'KOTLIN_VERSION_PLACEHOLDER' |
||||
id 'org.jetbrains.compose' version 'COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER' |
||||
} |
||||
repositories { |
||||
mavenLocal() |
||||
gradlePluginPortal() |
||||
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" } |
||||
} |
||||
} |
||||
rootProject.name = "nativeCacheKind" |
@ -0,0 +1,10 @@
|
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.getValue |
||||
import androidx.compose.runtime.mutableStateOf |
||||
import androidx.compose.runtime.remember |
||||
import androidx.compose.runtime.setValue |
||||
|
||||
@Composable |
||||
fun App() { |
||||
var text by remember { mutableStateOf("Hello, World!") } |
||||
} |
Loading…
Reference in new issue