From 8eb3068689ca4f9dce9fd65233b709ea83219e91 Mon Sep 17 00:00:00 2001 From: Tadeas Kriz Date: Sun, 29 Oct 2023 10:06:13 -0400 Subject: [PATCH] Use a specific version of runtime, instead of using Gradle's variant resolution. Previously we added the KotlinVersion attribute to all configurations in the module where SKIE was applied to. That unfortunately breaks transitive dependencies, when other modules would depend on it, as those wouldn't have the attribute. This change no longer relies on the attribute and instead targets an artifact for the specific version directly. --- .../skie/gradle/KotlinCompilerVersion.kt | 33 ++++++++++++++ .../touchlab/skie/plugin/SkieLoaderPlugin.kt | 2 + .../plugin/gradle-plugin.gradle.kts | 10 +++-- .../coroutines/AddDependencyOnSkieRuntime.kt | 43 +++++++++++++++---- 4 files changed, 77 insertions(+), 11 deletions(-) diff --git a/SKIE/skie-gradle/plugin-loader/src/main/kotlin-compiler-attribute/co/touchlab/skie/gradle/KotlinCompilerVersion.kt b/SKIE/skie-gradle/plugin-loader/src/main/kotlin-compiler-attribute/co/touchlab/skie/gradle/KotlinCompilerVersion.kt index 2d4afd925..f3ee6a2bb 100644 --- a/SKIE/skie-gradle/plugin-loader/src/main/kotlin-compiler-attribute/co/touchlab/skie/gradle/KotlinCompilerVersion.kt +++ b/SKIE/skie-gradle/plugin-loader/src/main/kotlin-compiler-attribute/co/touchlab/skie/gradle/KotlinCompilerVersion.kt @@ -1,11 +1,44 @@ package co.touchlab.skie.gradle import org.gradle.api.Named +import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.attributes.Attribute +import org.gradle.api.attributes.AttributeDisambiguationRule +import org.gradle.api.attributes.MultipleCandidatesDetails +import org.gradle.api.logging.Logging interface KotlinCompilerVersion : Named { companion object { val attribute = Attribute.of("co.touchlab.skie.kotlin.compiler.version", KotlinCompilerVersion::class.java) + + fun registerIn(dependencies: DependencyHandler, currentKotlinVersion: String) { + dependencies.attributesSchema.attribute(attribute) { + disambiguationRules.add(DisambiguationRule::class.java) { + params(currentKotlinVersion) + } + } + } + } + + class DisambiguationRule( + private val currentKotlinVersion: String, + ): AttributeDisambiguationRule { + override fun execute(details: MultipleCandidatesDetails) { + val correctCandidate = details.candidateValues.lastOrNull { + it.name == currentKotlinVersion + } + + if (correctCandidate != null) { + details.closestMatch(correctCandidate) + } else { + // This should've already been caught by SKIE Plugin Loader, but we'll let the user know just in case. + log.error("Could not find a Kotlin compiler version matching the current Kotlin version ($currentKotlinVersion)!") + } + } + + companion object { + val log = Logging.getLogger("KotlinCompilerVersion.DisambiguationRule") + } } } diff --git a/SKIE/skie-gradle/plugin-loader/src/main/kotlin/co/touchlab/skie/plugin/SkieLoaderPlugin.kt b/SKIE/skie-gradle/plugin-loader/src/main/kotlin/co/touchlab/skie/plugin/SkieLoaderPlugin.kt index 6d3c3f60a..4b09e455c 100644 --- a/SKIE/skie-gradle/plugin-loader/src/main/kotlin/co/touchlab/skie/plugin/SkieLoaderPlugin.kt +++ b/SKIE/skie-gradle/plugin-loader/src/main/kotlin/co/touchlab/skie/plugin/SkieLoaderPlugin.kt @@ -93,6 +93,8 @@ abstract class SkieLoaderPlugin : Plugin { val gradleVersion = GradleVersion.current().version logger.info("Resolving SKIE gradle plugin for Kotlin plugin version $kotlinVersion and Gradle version $gradleVersion") + KotlinCompilerVersion.registerIn(project.dependencies, kotlinVersion) + KotlinCompilerVersion.registerIn(buildscript.dependencies, kotlinVersion) val skieGradleConfiguration = buildscript.configurations.detachedConfiguration( buildscript.dependencies.create(BuildConfig.SKIE_GRADLE_PLUGIN), ).apply { diff --git a/SKIE/skie-gradle/plugin/gradle-plugin.gradle.kts b/SKIE/skie-gradle/plugin/gradle-plugin.gradle.kts index 9f617a3cd..a3cc79ce2 100644 --- a/SKIE/skie-gradle/plugin/gradle-plugin.gradle.kts +++ b/SKIE/skie-gradle/plugin/gradle-plugin.gradle.kts @@ -49,7 +49,9 @@ buildConfig { buildConfigField("String", "KOTLIN_PLUGIN_VERSION", "") buildConfigField("String", "KOTLIN_TOOLING_VERSION", "") buildConfigField("String", "GRADLE_API_VERSION", "") - buildConfigField("String", "RUNTIME_DEPENDENCY", "") + buildConfigField("String", "RUNTIME_DEPENDENCY_GROUP", "") + buildConfigField("String", "RUNTIME_DEPENDENCY_NAME", "") + buildConfigField("String", "RUNTIME_DEPENDENCY_VERSION", "") buildConfigField("String", "KOTLIN_PLUGIN_ID", "") buildConfigField("String", "MIXPANEL_PROJECT_TOKEN", "") } @@ -78,8 +80,10 @@ multiDimensionTarget.configureSourceSet { sourceSet -> buildConfigField("String", "KOTLIN_TOOLING_VERSION", sourceSet.kotlinToolingVersion.value.enquoted()) buildConfigField("String", "GRADLE_API_VERSION", sourceSet.gradleApiVersion.value.enquoted()) - val runtime = project.provider { projects.runtime.runtimeKotlin.dependencyProject.dependencyName } - buildConfigField("String", "RUNTIME_DEPENDENCY", runtime.map { it.enquoted() }) + val runtime = project.provider { projects.runtime.runtimeKotlin.dependencyProject } + buildConfigField("String", "RUNTIME_DEPENDENCY_GROUP", runtime.map { it.group.toString().enquoted() }) + buildConfigField("String", "RUNTIME_DEPENDENCY_NAME", runtime.map { it.name.enquoted() }) + buildConfigField("String", "RUNTIME_DEPENDENCY_VERSION", runtime.map { it.version.toString().enquoted() }) val pluginId: String by properties buildConfigField("String", "KOTLIN_PLUGIN_ID", "\"$pluginId\"") diff --git a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt index 93d0bdfbd..720fcae3d 100644 --- a/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt +++ b/SKIE/skie-gradle/plugin/src/kgp_common/gradle_common/kotlin/co/touchlab/skie/plugin/coroutines/AddDependencyOnSkieRuntime.kt @@ -6,25 +6,52 @@ import co.touchlab.skie.plugin.util.named import co.touchlab.skie.plugin.util.withType import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractNativeLibrary import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.konan.target.KonanTarget internal fun KotlinNativeTarget.addDependencyOnSkieRuntime() { if (!project.isCoroutinesInteropEnabled) { return } - project.configurations.configureEach { - attributes { - attribute(KotlinCompilerVersion.attribute, project.objects.named(BuildConfig.KOTLIN_TOOLING_VERSION)) - } - } - compilations.named("main") { defaultSourceSet.dependencies { - api(BuildConfig.RUNTIME_DEPENDENCY) + api(BuildConfig.RUNTIME_DEPENDENCY(konanTarget, BuildConfig.KOTLIN_TOOLING_VERSION)) } } binaries.withType().configureEach { - export(BuildConfig.RUNTIME_DEPENDENCY) + export(BuildConfig.RUNTIME_DEPENDENCY(konanTarget, BuildConfig.KOTLIN_TOOLING_VERSION)) } } + +private fun BuildConfig.RUNTIME_DEPENDENCY(konanTarget: KonanTarget, kotlinVersion: String): String { + return "$RUNTIME_DEPENDENCY_GROUP:$RUNTIME_DEPENDENCY_NAME-${konanTarget.presetName}__kgp_${kotlinVersion}:$RUNTIME_DEPENDENCY_VERSION" +} + +private val KonanTarget.presetName: String + get() = when (this) { + KonanTarget.IOS_ARM32 -> "iosArm32" + KonanTarget.IOS_ARM64 -> "iosArm64" + KonanTarget.IOS_X64 -> "iosX64" + KonanTarget.IOS_SIMULATOR_ARM64 -> "iosSimulatorArm64" + + KonanTarget.MACOS_ARM64 -> "macosArm64" + KonanTarget.MACOS_X64 -> "macosX64" + + KonanTarget.TVOS_ARM64 -> "tvosArm64" + KonanTarget.TVOS_SIMULATOR_ARM64 -> "tvosSimulatorArm64" + KonanTarget.TVOS_X64 -> "tvosX64" + + KonanTarget.WATCHOS_ARM32 -> "watchosArm32" + KonanTarget.WATCHOS_ARM64 -> "watchosArm64" + KonanTarget.WATCHOS_DEVICE_ARM64 -> "watchosArm64" + KonanTarget.WATCHOS_X86 -> "watchosX86" + KonanTarget.WATCHOS_X64 -> "watchosX64" + KonanTarget.WATCHOS_SIMULATOR_ARM64 -> "watchosSimulatorArm64" + + KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64, KonanTarget.ANDROID_X64, KonanTarget.ANDROID_X86, KonanTarget.LINUX_ARM32_HFP, + KonanTarget.LINUX_ARM64, KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32, KonanTarget.LINUX_X64, KonanTarget.MINGW_X64, + KonanTarget.MINGW_X86, KonanTarget.WASM32, is KonanTarget.ZEPHYR -> error( + "SKIE doesn't support these platforms, so it should never ask for the preset name of this target." + ) + }