Temp
diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt
index 6364478..25e0cac 100644
--- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt
+++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlatformType.kt
@@ -56,9 +56,7 @@
     /**
      * Represents a compilation output compiled for the Wasm Kotlin platform.
      */
-    wasm,
-    
-    unknown;
+    wasm;
 
     /**
      * @suppress
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
index 75add62..b858447 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts
@@ -108,6 +108,7 @@
 
     // AGP classes for buildScriptInjection's
     testImplementation(libs.android.gradle.plugin.gradle.api) { isTransitive = false }
+    testImplementation(libs.android.gradle.plugin.gradle) { isTransitive = false }
 
     testImplementation(project(path = ":examples:annotation-processor-example"))
     testImplementation(kotlinStdlib("jdk8"))
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt
index 4c222f0..3770266 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGenerateSourceSets.kt
@@ -5,8 +5,11 @@
 
 package org.jetbrains.kotlin.gradle.testbase
 
+import org.intellij.lang.annotations.Language
 import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
 import java.io.Serializable
+import java.security.MessageDigest
+import java.util.Base64
 
 data class SourceSetIdentifier(
     val name: String,
@@ -45,4 +48,20 @@
             }
         }
     )
+}
+
+fun KotlinSourceSet.compileSource(
+    @Language("kotlin")
+    sourceContent: String
+) {
+    val identifier = name
+    val identifierPath = project.layout.buildDirectory.dir("consume_${identifier}")
+    kotlin.srcDir(
+        project.tasks.create("consumeSourceIn_${identifier}") { task ->
+            task.outputs.dir(identifierPath)
+            task.doLast {
+                identifierPath.get().asFile.resolve("consumeSourceIn_${identifier}.kt").writeText(sourceContent)
+            }
+        }
+    )
 }
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt
index 84cafbf..44bd192 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testGradleBuildInjection.kt
@@ -109,11 +109,14 @@
      * query anything from relevant tasks since they have executed. However, we have to disable CC, so that the returning closure can reach
      * out for configuration entities.
      */
-    fun buildAndReturn(evaluationTask: String = "tasks"): T {
+    fun buildAndReturn(
+        evaluationTask: String = "tasks",
+        deriveBuildOptions: TestProject.() -> BuildOptions = { buildOptions },
+    ): T {
         gradleProject.build(
             evaluationTask,
             "-P${injectionLoadProperty}=true",
-            buildOptions = gradleProject.buildOptions.copy(
+            buildOptions = gradleProject.deriveBuildOptions().copy(
                 configurationCache = BuildOptions.ConfigurationCacheValue.DISABLED,
             )
         )
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt
new file mode 100644
index 0000000..9aa442f
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.uklibs
+
+import org.gradle.api.Project
+import org.gradle.api.artifacts.component.ModuleComponentIdentifier
+import org.gradle.api.file.Directory
+import org.gradle.api.initialization.resolve.RepositoriesMode
+import org.gradle.api.internal.GradleInternal
+import org.gradle.api.plugins.ExtraPropertiesExtension
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.internal.project.*
+import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.artifacts.UklibResolutionStrategy
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.internal.properties.nativeProperties
+import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
+import org.jetbrains.kotlin.gradle.testbase.*
+import org.jetbrains.kotlin.internal.compilerRunner.native.nativeCompilerClasspath
+import org.junit.jupiter.api.DisplayName
+import java.io.File
+import java.io.FileOutputStream
+import java.io.Serializable
+import java.net.URLClassLoader
+import kotlin.test.assertEquals
+import java.io.PrintStream
+
+@MppGradlePluginTests
+@DisplayName("Smoke test uklib consumption")
+class UklibConsumptionIT : KGPBaseTest() {
+
+    @GradleTestVersions
+    @GradleTest
+    fun `uklib consumption smoke - in kotlin compilations of a symmetric consumer and producer projects - with all metadata compilations`(
+        version: GradleVersion
+    ) {
+        val symmetricTargets: KotlinMultiplatformExtension.() -> Unit = @JvmSerializableLambda {
+            linuxArm64()
+            iosArm64()
+            iosX64()
+            jvm()
+            js()
+            wasmJs()
+            wasmWasi()
+        }
+        val publisher = publishUklib(version) @JvmSerializableLambda {
+            symmetricTargets()
+            sourceSets.all {
+                it.compileSource(
+                    "object Producer_${it.name}"
+                )
+            }
+        }
+
+        val producerConsumerVisibility = mapOf(
+            "common" to listOf(
+                "Producer_commonMain",
+            ),
+            "native" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+            ),
+            "apple" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+                "Producer_appleMain",
+            ),
+            "ios" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+                "Producer_appleMain",
+                "Producer_iosMain"
+            ),
+            "linux" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+                "Producer_linuxMain",
+            ),
+            "jvm" to listOf(
+                "Producer_commonMain",
+                "Producer_jvmMain",
+            ),
+            "js" to listOf(
+                "Producer_commonMain",
+                "Producer_jsMain",
+            ),
+            "wasmJs" to listOf(
+                "Producer_commonMain",
+                "Producer_wasmJsMain",
+            ),
+            "wasmWasi" to listOf(
+                "Producer_commonMain",
+                "Producer_wasmWasiMain"
+            ),
+            "iosArm64" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+                "Producer_appleMain",
+                "Producer_iosArm64Main",
+            ),
+            "iosX64" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+                "Producer_appleMain",
+                "Producer_iosX64Main",
+            ),
+            "linuxArm64" to listOf(
+                "Producer_commonMain",
+                "Producer_nativeMain",
+                "Producer_linuxMain",
+                "Producer_linuxArm64Main",
+            ),
+        ).flatMap {
+            listOf(
+                it.key + "Main" to it.value,
+                it.key + "Test" to it.value,
+            )
+        }.toMap()
+
+        project(
+            "buildScriptInjectionGroovy",
+            version,
+            dependencyManagement = DependencyManagement.DefaultDependencyManagement(
+                gradleRepositoriesMode = RepositoriesMode.PREFER_PROJECT,
+            )
+        ) {
+            transferDependencyResolutionRepositoriesIntoProjectRepositories()
+            buildScriptInjection {
+                project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY, UklibResolutionStrategy.AllowResolvingUklibs.propertyName)
+
+                project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+
+                project.repositories.maven {
+                    it.setUrl(publisher.repository)
+
+                    // Prevent Gradle from reading Gradle metadata
+                    it.metadataSources {
+                        it.mavenPom()
+                        it.ignoreGradleMetadataRedirection()
+                    }
+                }
+
+                with(kotlinMultiplatform) {
+                    symmetricTargets()
+
+                    sourceSets.all {
+                        val producerTypes = producerConsumerVisibility[it.name] ?: error("Missing producer declaration for ${it.name}")
+                        val arguments = producerTypes.map { "${it}: ${it}" }.joinToString(", ")
+                        it.compileSource(
+                            """
+                                fun consumeIn_${it.name}(${arguments}) {}
+                            """.trimIndent()
+                        )
+                    }
+
+                    sourceSets.commonMain.dependencies {
+                        implementation("${publisher.group}:${publisher.name}:${publisher.version}")
+                    }
+                }
+            }
+
+            // FIXME: Maybe just nuke Gradle metadata?
+            val resolvedProducerIosArm64Variant = buildScriptReturn {
+                (project.gradle as GradleInternal).services.get(ProjectStateRegistry::class.java).allowUncontrolledAccessToAnyProject {
+                    val selectedVariant = kotlinMultiplatform.iosArm64().compilations.getByName("main")
+                        .configurations.compileDependencyConfiguration
+                        .incoming.artifacts.artifacts.single {
+                            val identifier = (it.id.componentIdentifier as? ModuleComponentIdentifier) ?: return@single false
+                            identifier.group == publisher.group
+                                    && identifier.module == publisher.name
+                                    && identifier.version == publisher.version
+                        }.variant
+                    selectedVariant.attributes.keySet().map {
+                        it.toString() to selectedVariant.attributes.getAttribute(it).toString()
+                    }.toMap()
+                }
+            }.buildAndReturn()
+
+            // Make sure that we are actually resolving uklib from metadataSources configuration
+            assertEquals(
+                resolvedProducerIosArm64Variant["uklibDestination"],
+                "ios_arm64",
+            )
+
+            // FIXME: Test metadata compilations
+            build("build")
+
+            data class KlibsToCheck(
+                val iosArm64Klib: File,
+                val commonMainKlib: File,
+            ) : Serializable
+
+            val klibs = buildScriptReturn {
+                KlibsToCheck(
+                    kotlinMultiplatform.iosArm64().compilations.getByName("main").compileTaskProvider.flatMap { it.outputFile }.get(),
+                    kotlinMultiplatform.metadata().compilations.getByName("commonMain").output.classesDirs.singleFile,
+                )
+            }.buildAndReturn()
+
+            assertEquals(
+                """
+                /consumeIn_appleMain|consumeIn_appleMain(Producer_commonMain;Producer_nativeMain;Producer_appleMain){}[0]
+                /consumeIn_commonMain|consumeIn_commonMain(Producer_commonMain){}[0]
+                /consumeIn_iosArm64Main|consumeIn_iosArm64Main(Producer_commonMain;Producer_nativeMain;Producer_appleMain;Producer_iosArm64Main){}[0]
+                /consumeIn_iosMain|consumeIn_iosMain(Producer_commonMain;Producer_nativeMain;Producer_appleMain;Producer_iosMain){}[0]
+                /consumeIn_nativeMain|consumeIn_nativeMain(Producer_commonMain;Producer_nativeMain){}[0]
+
+                """.trimIndent(),
+                dumpKlibMetadataSignatures(klibs.iosArm64Klib),
+            )
+
+            assertEquals(
+                """
+                /consumeIn_commonMain|consumeIn_commonMain(Producer_commonMain){}[0]
+                
+                """.trimIndent(),
+                dumpKlibMetadataSignatures(klibs.commonMainKlib),
+            )
+        }
+    }
+
+    private fun TestProject.dumpKlibMetadataSignatures(klib: File): String {
+        val dumpName = "dump_${klib.name}"
+        // FIXME: This path is not actually unique
+        val outputFile = projectPath.resolve(dumpName).toFile()
+        outputFile.createNewFile()
+
+        buildScriptInjection {
+            project.tasks.register(dumpName) {
+                val inputs = project.objects.nativeCompilerClasspath(
+                    project.nativeProperties.actualNativeHomeDirectory,
+                    project.nativeProperties.shouldUseEmbeddableCompilerJar,
+                )
+                it.inputs.files(inputs)
+                val nativePath = project.nativeProperties.actualNativeHomeDirectory
+                it.doLast {
+                    // FIXME: Why does App class loader loads compiler classes and why is this crutch needed ???
+                    System.setProperty("kotlin.native.home", nativePath.get().path)
+                    URLClassLoader(inputs.map { it.toURI().toURL() }.toTypedArray()).use { classLoader ->
+                        val entryPoint = Class.forName("org.jetbrains.kotlin.cli.klib.Main", true, classLoader)
+                            .declaredMethods
+                            .single { it.name == "exec" }
+
+                        val stdout = PrintStream(FileOutputStream(outputFile))
+                        val stderr = System.err
+
+                        val args: Array<String> = arrayOf(
+                            "dump-metadata-signatures", klib.path,
+                            "-test-mode", "true",
+                        )
+
+                        assert(entryPoint.invoke(null, stdout, stderr, args) as Int == 0)
+                    }
+                }
+            }
+        }
+
+        build(dumpName)
+
+        return outputFile.readText()
+    }
+
+    data class PublisherProject(
+        val repository: File,
+        val group: String,
+        val name: String,
+        val version: String,
+    ) : Serializable
+
+    private fun publishUklib(
+        gradleVersion: GradleVersion,
+        publisherConfiguration: KotlinMultiplatformExtension.() -> Unit,
+    ): PublisherProject {
+        val publisherGroup = "foo"
+        val publisherVersion = "1.0"
+        val publisherName = "producer"
+        var publicationRepoPath: File? = null
+        project(
+            "buildScriptInjectionGroovy",
+            gradleVersion,
+            projectPathAdditionalSuffix = publisherName,
+        ) {
+            val publicationRepo: Project.() -> Directory = @JvmSerializableLambda { project.layout.projectDirectory.dir("repo") }
+            buildScriptInjection {
+                project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, true.toString())
+
+                project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+                project.plugins.apply("maven-publish")
+
+                project.group = publisherGroup
+                project.version = publisherVersion
+
+                with(kotlinMultiplatform) {
+                    publisherConfiguration()
+                }
+
+                val publishingExtension = project.extensions.getByType(PublishingExtension::class.java)
+                publishingExtension.repositories.maven {
+                    it.url = project.uri(project.publicationRepo())
+                }
+            }
+
+            build("publishAllPublicationsToMavenRepository")
+
+            publicationRepoPath = buildScriptReturn {
+                project.publicationRepo().asFile
+            }.buildAndReturn()
+        }
+        return PublisherProject(
+            publicationRepoPath!!,
+            publisherGroup,
+            publisherName,
+            publisherVersion,
+        )
+    }
+}
+
+val Project.propertiesExtension: ExtraPropertiesExtension
+    get() = extensions.getByType(ExtraPropertiesExtension::class.java)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibPublicationIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibPublicationIT.kt
new file mode 100644
index 0000000..4177af3
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibPublicationIT.kt
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.uklibs
+
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.decodeFromStream
+import org.gradle.api.Project
+import org.gradle.api.file.Directory
+import org.gradle.api.publish.PublishingExtension
+import org.gradle.util.GradleVersion
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.mpp.resources.unzip
+import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.*
+import org.jetbrains.kotlin.gradle.testbase.*
+import org.junit.jupiter.api.DisplayName
+import java.io.File
+import java.io.FileInputStream
+import java.io.Serializable
+import java.nio.file.Path
+import kotlin.io.path.createDirectory
+import kotlin.io.path.listDirectoryEntries
+import kotlin.io.path.name
+import kotlin.test.assertEquals
+import com.android.build.gradle.BaseExtension
+import org.gradle.api.NamedDomainObjectContainer
+import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
+import org.jetbrains.kotlin.gradle.dsl.HasConfigurableKotlinCompilerOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
+import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
+import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.mpp.external.*
+
+@OptIn(ExternalKotlinTargetApi::class)
+@MppGradlePluginTests
+@DisplayName("Smoke test uklib artifact publication")
+class UklibPublicationIT : KGPBaseTest() {
+
+    @GradleTest
+    fun `uklib contents - produces expected umanifest, platform and metadata artifacts`(
+        gradleVersion: GradleVersion
+    ) {
+        val publisher = publishUklib(
+            gradleVersion = gradleVersion,
+        ) @JvmSerializableLambda {
+            linuxArm64()
+            linuxX64()
+            iosArm64()
+            iosX64()
+            jvm()
+            js()
+            wasmJs()
+            wasmWasi()
+        }
+
+        val expectedFragments = listOf(
+            Fragment(identifier="appleMain", targets=listOf("ios_arm64", "ios_x64")),
+            Fragment(identifier="commonMain", targets=listOf("ios_arm64", "ios_x64", "js_ir", "jvm", "linux_arm64", "linux_x64", "wasm_js", "wasm_wasi")),
+            Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+            Fragment(identifier="iosMain", targets=listOf("ios_arm64", "ios_x64")),
+            Fragment(identifier="iosX64Main", targets=listOf("ios_x64")),
+            Fragment(identifier="jsMain", targets=listOf("js_ir")),
+            Fragment(identifier="jvmMain", targets=listOf("jvm")),
+            Fragment(identifier="linuxArm64Main", targets=listOf("linux_arm64")),
+            Fragment(identifier="linuxMain", targets=listOf("linux_arm64", "linux_x64")),
+            Fragment(identifier="linuxX64Main", targets=listOf("linux_x64")),
+            Fragment(identifier="nativeMain", targets=listOf("ios_arm64", "ios_x64", "linux_arm64", "linux_x64")),
+            Fragment(identifier="wasmJsMain", targets=listOf("wasm_js")),
+            Fragment(identifier="wasmWasiMain", targets=listOf("wasm_wasi")),
+        )
+
+        assertEquals(
+            Umanifest(expectedFragments),
+            publisher.umanifest,
+        )
+        assertEquals(
+            expectedFragments.map { it.identifier }.toSet(),
+            publisher.uklibContents.listDirectoryEntries().map {
+                it.name
+            }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+        )
+    }
+
+    @GradleTest
+    fun `uklib contents - produces single platform fragment - when metadata compilations are redundant`(
+        gradleVersion: GradleVersion,
+    ) {
+        val publisher = publishUklib(
+            gradleVersion = gradleVersion
+        ) @JvmSerializableLambda {
+            iosArm64()
+        }
+
+        val expectedFragments = listOf(
+            Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+        )
+
+        assertEquals(
+            Umanifest(expectedFragments),
+            publisher.umanifest,
+        )
+        assertEquals(
+            expectedFragments.map { it.identifier }.toSet(),
+            publisher.uklibContents.listDirectoryEntries().map {
+                it.name
+            }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+        )
+    }
+
+    // FIXME: This should be an error or we need to introduce refines edges
+    @GradleTest
+    fun `uklib contents - bamboo metadata publication`(
+        gradleVersion: GradleVersion
+    ) {
+        val publisher = publishUklib(
+            gradleVersion = gradleVersion
+        ) @JvmSerializableLambda {
+            iosArm64()
+            iosX64()
+        }
+
+        val expectedFragments = listOf(
+            Fragment(identifier="appleMain", targets=listOf("ios_arm64", "ios_x64")),
+            Fragment(identifier="commonMain", targets=listOf("ios_arm64", "ios_x64")),
+            Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+            Fragment(identifier="iosMain", targets=listOf("ios_arm64", "ios_x64")),
+            Fragment(identifier="iosX64Main", targets=listOf("ios_x64")),
+            Fragment(identifier="nativeMain", targets=listOf("ios_arm64", "ios_x64")),
+        )
+
+        assertEquals(
+            Umanifest(expectedFragments),
+            publisher.umanifest,
+        )
+        assertEquals(
+            expectedFragments.map { it.identifier }.toSet(),
+            publisher.uklibContents.listDirectoryEntries().map {
+                it.name
+            }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+        )
+    }
+
+    @GradleAndroidTest
+    fun `uklib publication - with AGP`(
+        gradleVersion: GradleVersion,
+        agpVersion: String,
+    ) {
+        val publisher = publishUklib(
+            template = "buildScriptInjectionGroovyWithAGP",
+            gradleVersion = gradleVersion,
+            agpVersion = agpVersion,
+        ) @JvmSerializableLambda {
+            project.plugins.apply("com.android.library")
+            iosArm64()
+            androidTarget()
+
+            with(project.extensions.getByType(BaseExtension::class.java)) {
+                compileSdkVersion(23)
+                namespace = "kotlin.multiplatform.projects"
+            }
+        }
+
+        val expectedFragments = listOf(
+            Fragment(identifier="commonMain", targets=listOf("android", "ios_arm64")),
+            Fragment(identifier="iosArm64Main", targets=listOf("ios_arm64")),
+        )
+
+        assertEquals(
+            Umanifest(expectedFragments),
+            publisher.umanifest,
+        )
+        assertEquals(
+            expectedFragments.map { it.identifier }.toSet(),
+            publisher.uklibContents.listDirectoryEntries().map {
+                it.name
+            }.filterNot { it == Uklib.UMANIFEST_FILE_NAME }.toSet(),
+        )
+    }
+
+    // FIXME: Lift this to FT
+    @GradleTest
+    fun `uklib publication - with externalTarget`(
+        gradleVersion: GradleVersion
+    ) {
+        project(
+            "buildScriptInjectionGroovy",
+            gradleVersion,
+        ) {
+            val publicationRepo: Project.() -> Directory = @JvmSerializableLambda{ project.layout.projectDirectory.dir("repo") }
+            buildScriptInjection {
+                // FIXME: Enable cross compilation
+                project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, true.toString())
+
+                project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+                project.plugins.apply("maven-publish")
+
+                project.group = "foo"
+                project.version = "1.0"
+
+                with(kotlinMultiplatform) {
+                    class FakeCompilation(delegate: Delegate) : DecoratedExternalKotlinCompilation(delegate) {
+                        @Suppress("UNCHECKED_CAST", "DEPRECATION")
+                        override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions>
+                            get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions>
+                    }
+
+                    class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate),
+                        HasConfigurableKotlinCompilerOptions<KotlinJvmCompilerOptions> {
+
+                        @Suppress("UNCHECKED_CAST")
+                        override val compilations: NamedDomainObjectContainer<FakeCompilation>
+                            get() = super.compilations as NamedDomainObjectContainer<FakeCompilation>
+
+                        override val compilerOptions: KotlinJvmCompilerOptions
+                            get() = super.compilerOptions as KotlinJvmCompilerOptions
+                    }
+
+                    fun ExternalKotlinTargetDescriptorBuilder<FakeTarget>.defaults() {
+                        targetName = "fake"
+                        platformType = KotlinPlatformType.jvm
+                        targetFactory = ExternalKotlinTargetDescriptor.TargetFactory(::FakeTarget)
+                    }
+
+                    fun ExternalKotlinCompilationDescriptorBuilder<FakeCompilation>.defaults(
+                        kotlin: KotlinMultiplatformExtension,
+                        name: String = KotlinCompilation.MAIN_COMPILATION_NAME,
+                    ) {
+                        compilationName = name
+                        compilationFactory = ExternalKotlinCompilationDescriptor.CompilationFactory(::FakeCompilation)
+                        defaultSourceSet = kotlin.sourceSets.maybeCreate(name)
+                    }
+
+                    iosArm64()
+                    iosX64()
+                    val kotlin = this
+                    createExternalKotlinTarget {
+                        defaults()
+                    }.createCompilation { defaults(kotlin) }
+
+                    sourceSets.all {
+                        it.addIdentifierClass(SourceSetIdentifier(it.name))
+                    }
+                }
+
+                val publishingExtension = project.extensions.getByType(PublishingExtension::class.java)
+                publishingExtension.repositories.maven {
+                    it.url = project.uri(project.publicationRepo())
+                }
+            }
+
+            buildAndFail("publishAllPublicationsToMavenRepository") {
+                assertOutputContains("FIXME: This is explicitly unsupported")
+            }
+        }
+    }
+
+    @kotlinx.serialization.Serializable
+    data class Fragment(
+        val identifier: String,
+        val targets: List<String>,
+    )
+    @kotlinx.serialization.Serializable
+    data class Umanifest(
+        val fragments: List<Fragment>,
+    )
+
+    data class UklibProducer(
+        val uklibContents: Path,
+        val umanifest: Umanifest,
+    ) : Serializable
+
+    private fun publishUklib(
+        template: String = "buildScriptInjectionGroovy",
+        gradleVersion: GradleVersion,
+        agpVersion: String? = null,
+        publisherConfiguration: KotlinMultiplatformExtension.() -> Unit,
+    ): UklibProducer {
+        val publisherGroup = "foo"
+        val publisherVersion = "1.0"
+        val publisherName = "producer"
+        var repository: File? = null
+        project(
+            template,
+            gradleVersion,
+            projectPathAdditionalSuffix = publisherName,
+        ) {
+            val publicationRepo: Project.() -> Directory = @JvmSerializableLambda{ project.layout.projectDirectory.dir("repo") }
+            buildScriptInjection {
+                // FIXME: Enable cross compilation
+                project.propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, true.toString())
+
+                project.plugins.apply("org.jetbrains.kotlin.multiplatform")
+                project.plugins.apply("maven-publish")
+
+                project.group = publisherGroup
+                project.version = publisherVersion
+
+                with(kotlinMultiplatform) {
+                    // Add a source to all source sets
+                    publisherConfiguration()
+
+                    sourceSets.all {
+                        it.addIdentifierClass(SourceSetIdentifier(it.name))
+                    }
+                }
+
+                val publishingExtension = project.extensions.getByType(PublishingExtension::class.java)
+                publishingExtension.repositories.maven {
+                    it.url = project.uri(project.publicationRepo())
+                }
+            }
+
+            build(
+                "publishAllPublicationsToMavenRepository",
+                buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion),
+            )
+
+            repository = buildScriptReturn {
+                project.publicationRepo().asFile
+            }.buildAndReturn(
+                deriveBuildOptions = { defaultBuildOptions.copy(androidVersion = agpVersion) }
+            )
+        }
+
+        val uklibPath = repository!!
+            .resolve(publisherGroup).resolve(publisherName).resolve(publisherVersion)
+            .resolve("${publisherName}-${publisherVersion}.uklib").toPath()
+
+        assertFileExists(uklibPath)
+
+        val uklibContents = repository!!.resolve("uklibContents").toPath()
+        uklibContents.createDirectory()
+        unzip(
+            uklibPath,
+            uklibContents,
+            ""
+        )
+
+        return UklibProducer(
+            uklibContents = uklibContents,
+            umanifest = Json.decodeFromStream<Umanifest>(
+                FileInputStream(uklibContents.resolve("umanifest").toFile())
+            )
+        )
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt
index e682538..a65373a 100644
--- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/gradleRunningUtils.kt
@@ -9,7 +9,7 @@
 
 class ProcessRunResult(
     private val cmd: List<String>,
-    private val workingDir: File,
+    private val workingDir: File?,
     val exitCode: Int,
     val output: String,
     val stdErr: String,
@@ -20,20 +20,22 @@
     override fun toString(): String = """
 Executing process was ${if (isSuccessful) "successful" else "unsuccessful"}
     Command: ${cmd.joinToString()}
-    Working directory: ${workingDir.absolutePath}
+    Working directory: ${workingDir?.absolutePath}
     Exit code: $exitCode
 """
 }
 
 fun runProcess(
     cmd: List<String>,
-    workingDir: File,
+    workingDir: File?,
     environmentVariables: Map<String, String> = mapOf(),
     redirectErrorStream: Boolean = true,
 ): ProcessRunResult {
     val builder = ProcessBuilder(cmd)
     builder.environment().putAll(environmentVariables)
-    builder.directory(workingDir)
+    workingDir?.let {
+        builder.directory(it)
+    }
     // redirectErrorStream merges stdout and stderr, so it can be gotten from process.inputStream
     builder.redirectErrorStream(redirectErrorStream)
 
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/buildScriptInjectionGroovyWithAGP/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/buildScriptInjectionGroovyWithAGP/build.gradle
new file mode 100644
index 0000000..ab3f872
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/buildScriptInjectionGroovyWithAGP/build.gradle
@@ -0,0 +1,4 @@
+plugins {
+    id("org.jetbrains.kotlin.multiplatform") apply false
+    id("com.android.library") apply false
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/build.gradle.kts
new file mode 100644
index 0000000..7bb3986
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/build.gradle.kts
@@ -0,0 +1,4 @@
+plugins {
+    kotlin("multiplatform")
+    `maven-publish`
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/gradle.properties
new file mode 100644
index 0000000..9ca8278
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/gradle.properties
@@ -0,0 +1 @@
+kotlin.mpp.enableUklibs=true
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/appleMain/kotlin/Apple.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/appleMain/kotlin/Apple.kt
new file mode 100644
index 0000000..7ee6903
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/appleMain/kotlin/Apple.kt
@@ -0,0 +1,2 @@
+class Apple {
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/commonMain/kotlin/Common.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/commonMain/kotlin/Common.kt
new file mode 100644
index 0000000..c86db65
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/commonMain/kotlin/Common.kt
@@ -0,0 +1,2 @@
+class Common {
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/linuxMain/kotlin/Linux.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/linuxMain/kotlin/Linux.kt
new file mode 100644
index 0000000..0ab4450
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/uklibs/src/linuxMain/kotlin/Linux.kt
@@ -0,0 +1,2 @@
+class Linux {
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
index ff587bb..26b8d22 100644
--- a/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
+++ b/libraries/tools/kotlin-gradle-plugin/build.gradle.kts
@@ -214,6 +214,7 @@
     testImplementation(project(":kotlin-gradle-statistics"))
     testImplementation(project(":kotlin-tooling-metadata"))
     testImplementation(libs.lincheck)
+    testImplementation(commonDependency("org.jetbrains.kotlin:kotlin-reflect")) { isTransitive = false }
 }
 
 configurations.commonCompileClasspath.get().exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core")
@@ -293,58 +294,58 @@
              */
             pivotVersion = KotlinMetadataPivotVersion(1, 6, 0)
         }
-        asmDeprecation {
-            val exclusions = listOf(
-                "org.jetbrains.kotlin.gradle.**", // part of the plugin
-                "org.jetbrains.kotlin.project.model.**", // part of the plugin
-                "org.jetbrains.kotlin.statistics.**", // part of the plugin
-                "org.jetbrains.kotlin.tooling.**", // part of the plugin
-                "org.jetbrains.kotlin.org.**", // already shadowed dependencies
-                "org.jetbrains.kotlin.com.**", // already shadowed dependencies
-                "org.jetbrains.kotlin.it.unimi.**", // already shadowed dependencies
-                "org.jetbrains.kotlin.internal.**", // already internal package
-            )
-            val deprecationMessage = """
-                You're using a Kotlin compiler class bundled into KGP for its internal needs.
-                This is discouraged and will not be supported in future releases.
-                The class in this artifact is scheduled for removal in Kotlin 2.2. Please define dependency on it in an alternative way.
-                See https://kotl.in/gradle/internal-compiler-symbols for more details
-            """.trimIndent()
-            deprecateClassesByPattern("org.jetbrains.kotlin.**", deprecationMessage, exclusions)
-        }
+//        asmDeprecation {
+//            val exclusions = listOf(
+//                "org.jetbrains.kotlin.gradle.**", // part of the plugin
+//                "org.jetbrains.kotlin.project.model.**", // part of the plugin
+//                "org.jetbrains.kotlin.statistics.**", // part of the plugin
+//                "org.jetbrains.kotlin.tooling.**", // part of the plugin
+//                "org.jetbrains.kotlin.org.**", // already shadowed dependencies
+//                "org.jetbrains.kotlin.com.**", // already shadowed dependencies
+//                "org.jetbrains.kotlin.it.unimi.**", // already shadowed dependencies
+//                "org.jetbrains.kotlin.internal.**", // already internal package
+//            )
+//            val deprecationMessage = """
+//                You're using a Kotlin compiler class bundled into KGP for its internal needs.
+//                This is discouraged and will not be supported in future releases.
+//                The class in this artifact is scheduled for removal in Kotlin 2.2. Please define dependency on it in an alternative way.
+//                See https://kotl.in/gradle/internal-compiler-symbols for more details
+//            """.trimIndent()
+//            deprecateClassesByPattern("org.jetbrains.kotlin.**", deprecationMessage, exclusions)
+//        }
     }
-    GradlePluginVariant.values().forEach { variant ->
-        if (kotlinBuildProperties.isInJpsBuildIdeaSync) return@forEach
-        val sourceSet = sourceSets.getByName(variant.sourceSetName)
-        val taskSuffix = sourceSet.jarTaskName.capitalize()
-        val shadowJarTaskName = "$EMBEDDABLE_COMPILER_TASK_NAME$taskSuffix"
-        asmDeprecation {
-            val dumpTask = registerDumpDeprecationsTask(shadowJarTaskName, taskSuffix)
-            val dumpAllTask = getOrCreateTask<Task>("dumpDeprecations") {
-                dependsOn(dumpTask)
-            }
-            val expectedFileDoesNotExistMessage = """
-                The file with expected deprecations for the compiler modules bundled into KGP does not exist.
-                Run ./gradlew ${project.path}:${dumpTask.name} first to create it.
-                You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
-                Context: https://youtrack.jetbrains.com/issue/KT-70251
-            """.trimIndent()
-            val checkFailureMessage = """
-                Expected deprecations applied to the compiler modules bundled into KGP does not match with the actually applied ones.
-                Run ./gradlew ${project.path}:${dumpTask.name} to see the difference.
-                You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
-                Use INFO level log for the exact deprecated classes set.
-                Either commit the difference or adjust the package relocation rules in ${buildFile.absolutePath}
-                Please be sure to leave a comment explaining any changes related to this failure clear enough.
-                Context: https://youtrack.jetbrains.com/issue/KT-70251
-            """.trimIndent()
-            val checkTask =
-                registerCheckDeprecationsTask(shadowJarTaskName, taskSuffix, expectedFileDoesNotExistMessage, checkFailureMessage)
-            named("check") {
-                dependsOn(checkTask)
-            }
-        }
-    }
+//    GradlePluginVariant.values().forEach {
+//        if (kotlinBuildProperties.isInJpsBuildIdeaSync) return@forEach
+//        val sourceSet = sourceSets.getByName(variant.sourceSetName)
+//        val taskSuffix = sourceSet.jarTaskName.capitalize()
+//        val shadowJarTaskName = "$EMBEDDABLE_COMPILER_TASK_NAME$taskSuffix"
+//        asmDeprecation {
+//            val dumpTask = registerDumpDeprecationsTask(shadowJarTaskName, taskSuffix)
+//            val dumpAllTask = getOrCreateTask<Task>("dumpDeprecations") {
+//                dependsOn(dumpTask)
+//            }
+//            val expectedFileDoesNotExistMessage = """
+//                The file with expected deprecations for the compiler modules bundled into KGP does not exist.
+//                Run ./gradlew ${project.path}:${dumpTask.name} first to create it.
+//                You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
+//                Context: https://youtrack.jetbrains.com/issue/KT-70251
+//            """.trimIndent()
+//            val checkFailureMessage = """
+//                Expected deprecations applied to the compiler modules bundled into KGP does not match with the actually applied ones.
+//                Run ./gradlew ${project.path}:${dumpTask.name} to see the difference.
+//                You may also use ./gradlew ${project.path}:${dumpAllTask.name} to dump deprecations of all fat jars.
+//                Use INFO level log for the exact deprecated classes set.
+//                Either commit the difference or adjust the package relocation rules in ${buildFile.absolutePath}
+//                Please be sure to leave a comment explaining any changes related to this failure clear enough.
+//                Context: https://youtrack.jetbrains.com/issue/KT-70251
+//            """.trimIndent()
+//            val checkTask =
+//                registerCheckDeprecationsTask(shadowJarTaskName, taskSuffix, expectedFileDoesNotExistMessage, checkFailureMessage)
+//            named("check") {
+//                dependsOn(checkTask)
+//            }
+//        }
+//    }
 }
 
 tasks.named("validatePlugins") {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt
index 09d480f2..4b456b7 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinMetadataArtifact.kt
@@ -5,12 +5,19 @@
 
 package org.jetbrains.kotlin.gradle.artifacts
 
+import org.gradle.api.Project
 import org.gradle.api.artifacts.type.ArtifactTypeDefinition.JAR_TYPE
 import org.gradle.api.attributes.Category
 import org.gradle.api.attributes.Usage
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.UklibFragmentPlatformAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.uklibFragmentPlatformAttribute
+import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
 import org.jetbrains.kotlin.gradle.plugin.categoryByName
 import org.jetbrains.kotlin.gradle.plugin.mpp.*
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
 import org.jetbrains.kotlin.gradle.plugin.usageByName
+import org.jetbrains.kotlin.gradle.targets.metadata.awaitMetadataCompilationsCreated
 import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled
 import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
 import org.jetbrains.kotlin.gradle.targets.metadata.locateOrRegisterGenerateProjectStructureMetadataTask
@@ -40,13 +47,12 @@
 
     /* Include output of metadata compilations into metadata jar (including commonizer output if available */
     val hostSpecificSourceSets = getHostSpecificSourceSets(target.project)
-    target.compilations.all { compilation ->
-        /* Filter legacy compilation */
-        if (compilation is KotlinCommonCompilation && !compilation.isKlibCompilation) return@all
+    // FIXME: How are test compilations filtered out ????
+    target.publishedMetadataCompilations().filter {
         /* Filter 'host specific' source sets (aka source sets that require a certain host to compile metadata) */
-        if (compilation.defaultSourceSet in hostSpecificSourceSets) return@all
-
-        metadataJarTask.configure { it.from(compilation.output.classesDirs) { spec -> spec.into(compilation.defaultSourceSet.name) } }
+        it.defaultSourceSet !in hostSpecificSourceSets
+    }.forEach { compilation ->
+        metadataJarTask.configure { it.from(compilation.metadataPublishedArtifacts) { spec -> spec.into(compilation.metadataFragmentIdentifier) } }
         if (compilation is KotlinSharedNativeCompilation) {
             target.project.includeCommonizedCInteropMetadata(metadataJarTask, compilation)
         }
@@ -54,3 +60,18 @@
 
     target.createPublishArtifact(metadataJarTask, JAR_TYPE, apiElements)
 }
+
+internal suspend fun KotlinMetadataTarget.publishedMetadataCompilations(): List<KotlinCompilation<*>> {
+    return awaitMetadataCompilationsCreated().filter { compilation ->
+        /* Filter legacy compilation */
+        !(compilation is KotlinCommonCompilation && !compilation.isKlibCompilation)
+    }
+}
+
+internal val KotlinCompilation<*>.metadataPublishedArtifacts: FileCollection get() = output.classesDirs
+// FIXME: Use this everywhere we map between fragment name in PSM and the name of disk
+internal val KotlinCompilation<*>.metadataFragmentIdentifier: String get() = defaultSourceSet.name
+internal val KotlinCompilation<*>.metadataFragmentAttributes: Set<UklibFragmentPlatformAttribute> get() = defaultSourceSet.internal.compilations
+    .filterNot {
+        it is KotlinMetadataCompilation
+    }.map { it.uklibFragmentPlatformAttribute }.toSet()
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt
index 415f2eb..199dc82 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinNativeKlibArtifact.kt
@@ -95,6 +95,7 @@
     } else {
         klibProducingTask.flatMap { it.klibFile }
     }
+    // FIXME: Что такое DefaultArtifactPublicationSet?
     with(compilation.project.configurations.getByName(apiElementsName)) {
         outgoing.registerKlibArtifact(packedArtifactFile, compilation.compilationName, classifier)
         attributes.setAttribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, NativeArtifactFormat.KLIB) // should we do it here?
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt
index 3972652..0b9541d 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/KotlinUklibConsumptionSetupAction.kt
@@ -5,202 +5,142 @@
 
 package org.jetbrains.kotlin.gradle.artifacts
 
+import org.gradle.api.NamedDomainObjectCollection
+import org.gradle.api.NamedDomainObjectContainer
 import org.gradle.api.Project
 import org.gradle.api.artifacts.transform.InputArtifact
 import org.gradle.api.artifacts.transform.TransformAction
 import org.gradle.api.artifacts.transform.TransformOutputs
 import org.gradle.api.artifacts.transform.TransformParameters
 import org.gradle.api.attributes.*
-import org.gradle.api.attributes.java.TargetJvmEnvironment
 import org.gradle.api.file.*
 import org.gradle.api.provider.Property
 import org.gradle.api.provider.Provider
-import org.gradle.api.provider.SetProperty
 import org.gradle.api.tasks.Input
-import org.jetbrains.kotlin.*
-import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.setupPublication
-import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.uklibFragmentPlatformAttribute
 import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
 import org.jetbrains.kotlin.gradle.plugin.*
 import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseCompilations
-import org.jetbrains.kotlin.gradle.plugin.KotlinProjectSetupAction
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
-import org.jetbrains.kotlin.gradle.plugin.attributes.KlibPackaging
-import org.jetbrains.kotlin.gradle.plugin.await
-import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
-import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
-import org.jetbrains.kotlin.gradle.plugin.launch
 import org.jetbrains.kotlin.gradle.plugin.mpp.*
-import org.jetbrains.kotlin.gradle.plugin.mpp.publishing.configureResourcesPublicationAttributes
 import org.jetbrains.kotlin.gradle.plugin.sources.internal
 import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
+import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
 import org.jetbrains.kotlin.gradle.utils.named
 import org.jetbrains.kotlin.gradle.utils.setAttribute
 import javax.inject.Inject
 
-private val artifactType: Attribute<String> get() = Attribute.of("artifactType", String::class.java)
-private val uklibArtifactType: String get() = "uklib"
-private val uklibUnzippedArtifactType: String get() = "uklib-unzipped"
-
 internal val KotlinUklibConsumptionSetupAction = KotlinProjectSetupAction {
-
-    if (project.kotlinPropertiesProvider.publishUklibVariant) {
-        project.launch {
-            setupPublication()
-        }
-    }
-
     when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
-        UklibResolutionStrategy.PreferUklibVariant,
-        UklibResolutionStrategy.PreferPlatformSpecificVariant -> project.launch { setupConsumption() }
+        UklibResolutionStrategy.AllowResolvingUklibs -> project.launch { setupUklibConsumption() }
         UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant -> { /* do nothing */ }
     }
 }
 
-val uklibStateAttribute = Attribute.of("uklibState", String::class.java)
-val uklibStateZipped = "zipped"
-val uklibStateUnzipped = "unzipped"
+internal val uklibStateAttribute = Attribute.of("uklibState", String::class.java)
+internal val uklibStateZipped = "zipped"
+internal val uklibStateUnzipped = "unzipped"
 
-val uklibPlatformAttribute = Attribute.of("uklibPlatform", String::class.java)
-val uklibPlatformUnknown = "unknown"
-val uklibNativeSliceAttribute = Attribute.of("uklibNativeSlice", String::class.java)
-val uklibNativeSliceUnknown = "unknown"
+internal val uklibDestinationAttribute = Attribute.of("uklibDestination", String::class.java)
+internal val uklibDestinationUnknown = "unknown"
 
-private suspend fun Project.setupConsumption() {
+/**
+ * Resolve Uklib artifacts using transforms:
+ * - Request a known [uklibDestinationAttribute] in all resolvable configurations that should be able to resolve uklibs
+ * - Register transform "zipped -> unzipped uklib"
+ * - Register transform "unzipped uklib -> [uklibDestinationAttribute]"
+ */
+private suspend fun Project.setupUklibConsumption() {
     val sourceSets = multiplatformExtension.awaitSourceSets()
-    val metadataTarget = multiplatformExtension.awaitMetadataTarget()
     val targets = multiplatformExtension.awaitTargets()
     AfterFinaliseCompilations.await()
 
-    sourceSets.configureEach {
-        with(it.internal.resolvableMetadataConfiguration) {
-            attributes {
-                when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
-                    UklibResolutionStrategy.PreferUklibVariant -> it.attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_UKLIB))
-                    UklibResolutionStrategy.PreferPlatformSpecificVariant -> {
-                        /* rely on the default + compatibility rule */
-                    }
-                }
-                it.attribute(uklibStateAttribute, uklibStateUnzipped)
-                it.attribute(uklibPlatformAttribute, KotlinPlatformType.common.name)
-            }
-        }
-    }
-    // FIXME: Drop this transform and use the unzip transform instead
-    dependencies.registerTransform(UnzippedUklibToMetadataCompilationTransform::class.java) {
-        it.from
-            .attribute(uklibStateAttribute, uklibStateUnzipped)
-            .attribute(uklibPlatformAttribute, uklibPlatformUnknown)
-        it.to
-            .attribute(uklibStateAttribute, uklibStateUnzipped)
-            .attribute(uklibPlatformAttribute, KotlinPlatformType.common.name)
-    }
+    registerZippedUklibArtifact()
+    allowUklibsToUnzip()
+    allowMetadataConfigurationsToResolveUnzippedUklib(sourceSets)
+    allowPlatformCompilationsToResolvePlatformCompilationArtifactFromUklib(targets)
+}
 
+private fun Project.allowPlatformCompilationsToResolvePlatformCompilationArtifactFromUklib(
+    targets: NamedDomainObjectCollection<KotlinTarget>
+) {
     targets.configureEach { target ->
-        if (target is KotlinMetadataTarget) return@configureEach
-        if (target is KotlinNativeTarget) {
-            dependencies.registerTransform(UnzippedUklibToPlatformCompilationTransform::class.java) {
-                it.from
-                    .attribute(uklibStateAttribute, uklibStateUnzipped)
-                    .attribute(uklibPlatformAttribute, uklibPlatformUnknown)
-                    .attribute(uklibNativeSliceAttribute, uklibNativeSliceUnknown)
-                it.to
-                    .attribute(uklibStateAttribute, uklibStateUnzipped)
-                    .attribute(uklibPlatformAttribute, target.platformType.name)
-                    .attribute(uklibNativeSliceAttribute, target.targetName)
+        val destinationAttribute = when (target) {
+            is KotlinNativeTarget -> target.uklibFragmentPlatformAttribute
+            is KotlinJsIrTarget -> target.uklibFragmentPlatformAttribute
+            is KotlinJvmTarget -> target.uklibFragmentPlatformAttribute
+            else -> return@configureEach
+        }
 
-                it.parameters.targetAttributes.set(setOf(target.targetName))
-                it.parameters.fakeTransform.set(kotlinPropertiesProvider.fakeUkibTransforms)
-            }
-            target.compilations.configureEach {
-                listOfNotNull(
-                    it.internal.configurations.compileDependencyConfiguration,
-                    it.internal.configurations.runtimeDependencyConfiguration,
-                ).forEach { config ->
-                    with(config.attributes) {
-                        when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
-                            UklibResolutionStrategy.PreferUklibVariant -> attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_UKLIB))
-                            UklibResolutionStrategy.PreferPlatformSpecificVariant -> {
-                                /* rely on the default + compatibility rule */
-                            }
-                        }
-                        attribute(uklibStateAttribute, uklibStateUnzipped)
-                        attribute(uklibPlatformAttribute, target.platformType.name)
-                        attribute(uklibNativeSliceAttribute, target.targetName)
-                    }
-                }
-            }
-        } else {
-            dependencies.registerTransform(UnzippedUklibToPlatformCompilationTransform::class.java) {
-                it.from
-                    .attribute(uklibStateAttribute, uklibStateUnzipped)
-                    .attribute(uklibPlatformAttribute, uklibPlatformUnknown)
-                it.to
-                    .attribute(uklibStateAttribute, uklibStateUnzipped)
-                    .attribute(uklibPlatformAttribute, target.platformType.name)
+        dependencies.registerTransform(UnzippedUklibToPlatformCompilationTransform::class.java) {
+            it.from
+                .attribute(uklibStateAttribute, uklibStateUnzipped)
+                .attribute(uklibDestinationAttribute, uklibDestinationUnknown)
+            it.to
+                .attribute(uklibStateAttribute, uklibStateUnzipped)
+                .attribute(uklibDestinationAttribute, destinationAttribute.unwrap())
 
-                it.parameters.targetAttributes.set(setOf(target.targetName))
-                it.parameters.fakeTransform.set(kotlinPropertiesProvider.fakeUkibTransforms)
-            }
-            target.compilations.configureEach {
-                listOfNotNull(
-                    it.internal.configurations.compileDependencyConfiguration,
-                    it.internal.configurations.runtimeDependencyConfiguration,
-                ).forEach { config ->
-                    with(config.attributes) {
-                        when (project.kotlinPropertiesProvider.uklibResolutionStrategy) {
-                            UklibResolutionStrategy.PreferUklibVariant -> attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_UKLIB))
-                            UklibResolutionStrategy.PreferPlatformSpecificVariant -> {
-                                /* rely on the default + compatibility rule */
-                            }
-                        }
+            it.parameters.targetFragmentAttribute.set(destinationAttribute.unwrap())
+            it.parameters.fakeTransform.set(kotlinPropertiesProvider.fakeUkibTransforms)
+        }
 
-                        attribute(uklibStateAttribute, uklibStateUnzipped)
-                        attribute(uklibPlatformAttribute, target.platformType.name)
-                    }
+        // FIXME: Refactor this and encode what configurations should be allowed to transform per KotlinTarget somewhere around [uklibFragmentPlatformAttribute]
+        target.compilations.configureEach {
+            listOfNotNull(
+                it.internal.configurations.compileDependencyConfiguration,
+                it.internal.configurations.runtimeDependencyConfiguration,
+            ).forEach {
+                it.attributes {
+                    it.attribute(uklibStateAttribute, uklibStateUnzipped)
+                    it.attribute(uklibDestinationAttribute, destinationAttribute.unwrap())
                 }
             }
         }
     }
+}
 
-    with(dependencies.artifactTypes.create("uklib").attributes) {
+private fun Project.registerZippedUklibArtifact() {
+    with(dependencies.artifactTypes.create(Uklib.UKLIB_EXTENSION).attributes) {
         attribute(uklibStateAttribute, uklibStateZipped)
-        attribute(uklibPlatformAttribute, uklibPlatformUnknown)
-        attribute(uklibNativeSliceAttribute, uklibNativeSliceUnknown)
+        attribute(uklibDestinationAttribute, uklibDestinationUnknown)
     }
+}
 
-    dependencies.registerTransform(UklibUnzipTransform::class.java) {
+private fun Project.allowUklibsToUnzip() {
+    dependencies.registerTransform(UnzipUklibTransform::class.java) {
         it.from.attribute(uklibStateAttribute, uklibStateZipped)
         it.to.attribute(uklibStateAttribute, uklibStateUnzipped)
         it.parameters.performUnzip.set(!kotlinPropertiesProvider.fakeUkibTransforms)
     }
-
-    dependencies.attributesSchema.attribute(Usage.USAGE_ATTRIBUTE).compatibilityRules.add(
-        MakeUklibCompatibleWithPlatformCompilations::class.java
-    )
-    dependencies.attributesSchema.attribute(Usage.USAGE_ATTRIBUTE).compatibilityRules.add(
-        MakePlatformCompilationsCompatibleWithUklibCompilations::class.java
-    )
-    dependencies.attributesSchema.attribute(Usage.USAGE_ATTRIBUTE).disambiguationRules.add(
-        MakeJavaRuntimePreferableForUklibCompilations::class.java
-    )
-
-    dependencies.attributesSchema.attribute(KotlinPlatformType.attribute).compatibilityRules.add(
-        MakePlatformCompatibleWithUklibs::class.java
-    )
-    dependencies.attributesSchema.attribute(KotlinNativeTarget.konanTargetAttribute).compatibilityRules.add(
-        MakeKNSliceCompatibleWithUklibs::class.java
-    )
-    dependencies.attributesSchema.attribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE).compatibilityRules.add(
-        MakeTargetJvmEnvironmentCompatibleWithUklibs::class.java
-    )
-
 }
 
-abstract class UklibUnzipTransform @Inject constructor(
+private fun Project.allowMetadataConfigurationsToResolveUnzippedUklib(
+    sourceSets: NamedDomainObjectContainer<KotlinSourceSet>,
+) {
+    sourceSets.configureEach {
+        with(it.internal.resolvableMetadataConfiguration) {
+            attributes {
+                it.attribute(uklibStateAttribute, uklibStateUnzipped)
+                it.attribute(uklibDestinationAttribute, KotlinPlatformType.common.name)
+            }
+        }
+    }
+    dependencies.registerTransform(UnzippedUklibToMetadataCompilationTransform::class.java) {
+        it.from
+            .attribute(uklibStateAttribute, uklibStateUnzipped)
+            .attribute(uklibDestinationAttribute, uklibDestinationUnknown)
+        it.to
+            .attribute(uklibStateAttribute, uklibStateUnzipped)
+            .attribute(uklibDestinationAttribute, KotlinPlatformType.common.name)
+    }
+}
+
+
+internal abstract class UnzipUklibTransform @Inject constructor(
     private val fileOperations: FileSystemOperations,
     private val archiveOperations: ArchiveOperations,
-) : TransformAction<UklibUnzipTransform.Parameters> {
+) : TransformAction<UnzipUklibTransform.Parameters> {
     interface Parameters : TransformParameters {
         @get:Input
         val performUnzip: Property<Boolean>
@@ -210,11 +150,14 @@
     abstract val inputArtifact: Provider<FileSystemLocation>
 
     override fun transform(outputs: TransformOutputs) {
-        // FIXME: 25.11.2024 - When resolving a jar with uklib packaging Gradle comes here with the jar
         val input = inputArtifact.get().asFile
-        if (input.extension == "uklib") {
+        /**
+         * FIXME: Test this !!!
+         *
+         * Due to kotlin-api/runtime Usages being compatible with java Usages, we might see a jar in this transform
+         */
+        if (input.extension == Uklib.UKLIB_EXTENSION) {
             val outputDir = outputs.dir("unzipped_uklib_${input.name}")
-            // FIXME: 13.11.2024 - Throw this away because this is not really testable with UT?
             if (parameters.performUnzip.get()) {
                 fileOperations.copy {
                     it.from(archiveOperations.zipTree(inputArtifact.get().asFile))
@@ -225,9 +168,7 @@
     }
 }
 
-abstract class UnzippedUklibToMetadataCompilationTransform @Inject constructor() : TransformAction<UnzippedUklibToMetadataCompilationTransform.Parameters> {
-    interface Parameters : TransformParameters {}
-
+internal abstract class UnzippedUklibToMetadataCompilationTransform : TransformAction<TransformParameters.None> {
     @get:InputArtifact
     abstract val inputArtifact: Provider<FileSystemLocation>
 
@@ -236,11 +177,10 @@
     }
 }
 
-abstract class UnzippedUklibToPlatformCompilationTransform @Inject constructor(
-) : TransformAction<UnzippedUklibToPlatformCompilationTransform.Parameters> {
+internal abstract class UnzippedUklibToPlatformCompilationTransform : TransformAction<UnzippedUklibToPlatformCompilationTransform.Parameters> {
     interface Parameters : TransformParameters {
         @get:Input
-        val targetAttributes: SetProperty<String>
+        val targetFragmentAttribute: Property<String>
 
         @get:Input
         val fakeTransform: Property<Boolean>
@@ -256,115 +196,45 @@
         }
 
         val unzippedUklib = inputArtifact.get().asFile
-
-        val targetAttributes = parameters.targetAttributes.get()
-        val uklib = Uklib.deserializeFromDirectory(unzippedUklib)
-        // FIXME: Build up a Set<Attribute> -> Fragment instead?
-        val platformFragments = uklib.module.fragments.filter { it.attributes == targetAttributes }
+        val targetFragmentAttribute = parameters.targetFragmentAttribute.get()
+        // FIXME: Build up a Set<Attribute> -> Fragment map instead?
+        val platformFragments = Uklib.deserializeFromDirectory(unzippedUklib)
+            .module.fragments
+            .filter { it.attributes == setOf(targetFragmentAttribute) }
 
         if (platformFragments.isEmpty()) {
-            // The fragment is just not there. Skip this dependency
-            return
+            /**
+             * FIXME: Uklib spec mentions that there may be an intermediate fragment without refiners. Was this a crutch for kotlin-test? Should we check this case silently ignore this case here?
+             */
+            error("Couldn't resolve platform compilation artifact from ${unzippedUklib} failed. Needed fragment with attribute '${targetFragmentAttribute}', but only the following fragments were available ${platformFragments}")
         }
 
         if (platformFragments.size > 1) {
-            error("Somehow more than one platform fragment matches platform attributes: ${platformFragments}")
+            error("Matched multiple fragments from ${unzippedUklib}, but was expecting to find exactly one. Found fragments: ${platformFragments}")
         }
 
-        outputs.dir(uklib.fragmentToArtifact[platformFragments.single().identifier]!!)
+        outputs.dir(platformFragments.single().file())
     }
 }
 
 internal fun HasAttributes.configureUklibConfigurationAttributes(project: Project) {
     attributes.setAttribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
     attributes.setAttribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_UKLIB))
-
-    attributes.setAttribute(KotlinPlatformType.attribute, KotlinPlatformType.unknown)
-    attributes.setAttribute(KotlinNativeTarget.konanTargetAttribute, "???")
-    attributes.setAttribute(KlibPackaging.ATTRIBUTE, project.objects.named(KlibPackaging.PACKED))
-    attributes.setAttribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named("???"))
 }
 
-
-class MakeUklibCompatibleWithPlatformCompilations : AttributeCompatibilityRule<Usage> {
-    override fun execute(t: CompatibilityCheckDetails<Usage>) {
-        val allowedConsumers = setOf(
-            KotlinUsages.KOTLIN_API,
-            Usage.JAVA_API,
-            Usage.JAVA_RUNTIME,
-        )
-
-        if (t.producerValue?.name == KotlinUsages.KOTLIN_UKLIB && t.consumerValue?.name in allowedConsumers) {
-            t.compatible()
-        }
-    }
-}
-
-class MakePlatformCompilationsCompatibleWithUklibCompilations : AttributeCompatibilityRule<Usage> {
-    override fun execute(t: CompatibilityCheckDetails<Usage>) {
-        val allowedProducers = setOf(
-            KotlinUsages.KOTLIN_API,
-            Usage.JAVA_API,
-            Usage.JAVA_RUNTIME,
-        )
-
-        if (t.producerValue?.name in allowedProducers && t.consumerValue?.name == KotlinUsages.KOTLIN_UKLIB) {
-            t.compatible()
-        }
-    }
-}
-
-class MakeKNSliceCompatibleWithUklibs : AttributeCompatibilityRule<String> {
-    override fun execute(t: CompatibilityCheckDetails<String>) {
-        if (t.producerValue == "???") {
-            t.compatible()
-        }
-    }
-}
-
-class MakeTargetJvmEnvironmentCompatibleWithUklibs : AttributeCompatibilityRule<TargetJvmEnvironment> {
-    override fun execute(t: CompatibilityCheckDetails<TargetJvmEnvironment>) {
-        if (t.producerValue?.name == "???") {
-            t.compatible()
-        }
-    }
-}
-
-
-class MakePlatformCompatibleWithUklibs : AttributeCompatibilityRule<KotlinPlatformType> {
-    override fun execute(t: CompatibilityCheckDetails<KotlinPlatformType>) {
-        if (t.producerValue == KotlinPlatformType.unknown) {
-            t.compatible()
-        }
-    }
-}
-
-class MakeJavaRuntimePreferableForUklibCompilations : AttributeDisambiguationRule<Usage> {
-    override fun execute(p0: MultipleCandidatesDetails<Usage>) {
-        if (p0.consumerValue?.name == KotlinUsages.KOTLIN_UKLIB) {
-            p0.candidateValues.firstOrNull { it.name == Usage.JAVA_RUNTIME }?.let {
-                p0.closestMatch(it)
-            }
-        }
-    }
-}
-
-enum class UklibResolutionStrategy {
-    PreferUklibVariant,
-    PreferPlatformSpecificVariant,
+internal enum class UklibResolutionStrategy {
+    AllowResolvingUklibs,
     ResolveOnlyPlatformSpecificVariant;
 
     val propertyName: String
         get() = when (this) {
-            PreferUklibVariant -> "preferUklibVariant"
-            PreferPlatformSpecificVariant -> "preferPlatformSpecificVariant"
+            AllowResolvingUklibs -> "allowResolvingUklibs"
             ResolveOnlyPlatformSpecificVariant -> "resolveOnlyPlatformSpecificVariant"
         }
 
     companion object {
         fun fromProperty(name: String): UklibResolutionStrategy? = when (name) {
-            PreferUklibVariant.propertyName -> PreferUklibVariant
-            PreferPlatformSpecificVariant.propertyName -> PreferPlatformSpecificVariant
+            AllowResolvingUklibs.propertyName -> AllowResolvingUklibs
             ResolveOnlyPlatformSpecificVariant.propertyName -> ResolveOnlyPlatformSpecificVariant
             else -> null
         }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Resolve.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Resolve.kt
deleted file mode 100644
index 48212ee..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Resolve.kt
+++ /dev/null
@@ -1,214 +0,0 @@
-package org.jetbrains.kotlin
-
-import org.jetbrains.kotlin.tooling.core.withClosure
-import java.io.File
-
-/**
- * f1, f2, ... fN
- * ->
- * [
- *    (f1, f1), (f1, f2), ... (f1, fn),
- *    (f2, f1), (f2, f2), ... (f2, fn),
- *    (fn, f1), (fn, f2), ... (fn, fn),
- * ]
- * ->
- * 1. Filter p[0].canSee(p[1])
- * 2. Sort visible fragments by canSee and then by name
- */
-
-// Compilation -> publishedFile: File
-inline fun <Compilation, Target, reified SourceSet> transformKGPModelToUklibModel(
-    moduleIdentifier: String,
-    publishedCompilations: List<Compilation>,
-    publishedArtifact: Compilation.() -> File,
-    defaultSourceSet: Compilation.() -> SourceSet,
-    target: Compilation.() -> Target,
-    dependsOn: SourceSet.() -> Set<SourceSet>,
-    identifier: SourceSet.() -> String,
-//    sourceSetArtifact: SourceSet.() -> Compilation,
-): Uklib<Target> {
-    /**
-     * 1. No parts of the graph are isolated
-     * 2. There are no cycles (this is already done by KGP)
-     * 3. Everything is rooted in a single node (already checked in KGP)
-     * 4. There are no fragments with duplicated attributes
-     */
-    // Assume we did check everything
-
-    val sourceSetToTargets = mutableMapOf<SourceSet, MutableSet<Target>>()
-    val fragmentToArtifact = mutableMapOf<String, File>()
-    val publishedSourceSets = publishedCompilations.map { it.defaultSourceSet() }.toSet()
-    publishedCompilations.forEach { compilation ->
-        val compilationTarget = compilation.target()
-        compilation.defaultSourceSet().withClosure(dependsOn).filter { it in publishedSourceSets }.forEach { sourceSet ->
-            sourceSetToTargets.getOrPut(
-                sourceSet, { mutableSetOf() }
-            ).add(compilationTarget)
-        }
-        fragmentToArtifact[compilation.defaultSourceSet().identifier()] = compilation.publishedArtifact()
-    }
-
-    return Uklib(
-        module = Module(
-            identifier = moduleIdentifier,
-            fragments = sourceSetToTargets.map { (sourceSet, targets) ->
-                Fragment(
-                    identifier = sourceSet.identifier(),
-                    attributes = targets,
-                )
-            }.toSet()
-        ),
-        fragmentToArtifact = fragmentToArtifact
-    )
-}
-
-
-class ResolvedModuleClasspath<Target>(
-    val fullFragmentClasspath: Map<Fragment<Target>, List<File>>,
-    val exactlyMatchingFragmentClasspath: Map<Fragment<Target>, List<File>>,
-)
-
-
-fun <Target> resolveModuleFragmentClasspath(
-    module: Uklib<Target>,
-    dependencies: Set<Uklib<Target>>,
-): ResolvedModuleClasspath<Target> {
-    val moduleFragments = module.module.fragments.toList()
-    val fullFragmentClasspath = mutableMapOf<Fragment<Target>, MutableList<File>>()
-    val exactFragmentClasspath = mutableMapOf<Fragment<Target>, MutableList<File>>()
-    moduleFragments.forEach {
-        fullFragmentClasspath[it] = mutableListOf()
-        exactFragmentClasspath[it] = mutableListOf()
-    }
-
-    // FIXME: Do we ever want to resolve self fragments? Maybe we could refactor some KGP parts to better reflect this model, but not right now
-//    resolveFragmentRefinersWithinModule(moduleFragments).forEach { (fragment, refiners) ->
-//        fullFragmentClasspath.getOrPut(fragment, { mutableListOf() }).addAll(
-//            refiners.map { module.fragmentToArtifact[it.identifier]!! }
-//        )
-//    }
-
-    dependencies.forEach { dependency ->
-        val dependencyFragments = dependency.module.fragments.toList()
-        resolveFragmentDependencies(
-            targetFragments = moduleFragments,
-            dependencyFragments = dependencyFragments,
-        ).forEach { (fragment, dependencies) ->
-            fullFragmentClasspath[fragment]!!.addAll(
-                dependencies.map {
-                    dependency.fragmentToArtifact[it.identifier]!!
-                }
-            )
-        }
-        resolvePlatformFragmentDependencies(
-            targetPlatformFragments = moduleFragments,
-            dependencyFragments = dependencyFragments,
-        ).forEach { (fragment, dependencies) ->
-            exactFragmentClasspath[fragment]!!.addAll(
-                dependencies.map {
-                    dependency.fragmentToArtifact[it.identifier]!!
-                }
-            )
-        }
-    }
-
-
-    return ResolvedModuleClasspath(
-        fullFragmentClasspath = fullFragmentClasspath,
-        exactlyMatchingFragmentClasspath = exactFragmentClasspath,
-    )
-}
-
-/**
- * This function takes fragments of a module [moduleFragments] and outputs a map where the keys are [moduleFragments]
- * and the values are classpath-ordered refiners.
- */
-fun <Target> resolveFragmentRefinersWithinModule(
-    moduleFragments: List<Fragment<Target>>,
-) = resolveFragmentDependencies(
-    targetFragments = moduleFragments,
-    dependencyFragments = moduleFragments,
-    canSee = { attributes.isProperSubsetOf(it.attributes) }
-)
-
-/**
- * This function takes fragments [targetFragments] that depend on another module's fragments [dependencyFragments] and
- * outputs a map where the keys are [targetFragments] and the values are classpath-ordered [dependencyFragments] visible
- * from the target fragment
- */
-fun <Target> resolveFragmentDependencies(
-    targetFragments: List<Fragment<Target>>,
-    dependencyFragments: List<Fragment<Target>>,
-) = resolveFragmentDependencies(
-    targetFragments = targetFragments,
-    dependencyFragments = dependencyFragments,
-    canSee = { attributes.isSubsetOf(it.attributes) }
-)
-
-/**
- * This function takes fragments [targetPlatformFragments] that depend on another module's fragments [dependencyFragments] and
- * outputs a map where the keys are [targetPlatformFragments] and the values are empty of single element lists of [dependencyFragments]
- * matching
- */
-fun <Target> resolvePlatformFragmentDependencies(
-    targetPlatformFragments: List<Fragment<Target>>,
-    dependencyFragments: List<Fragment<Target>>,
-) = resolveFragmentDependencies(
-    targetFragments = targetPlatformFragments,
-    dependencyFragments = dependencyFragments,
-    canSee = { attributes == it.attributes }
-)
-
-fun <Target> resolveFragmentDependencies(
-    targetFragments: List<Fragment<Target>>,
-    dependencyFragments: List<Fragment<Target>>,
-    canSee: Fragment<Target>.(Fragment<Target>) -> Boolean,
-): Map<Fragment<Target>, List<Fragment<Target>>> {
-    val modulesFragmentClasspath = mutableMapOf<Fragment<Target>, List<Fragment<Target>>>()
-    targetFragments.forEach { fragment ->
-        val fragmentClasspath = dependencyFragments.filter {
-            fragment.canSee(it)
-        }.sortedWith(
-            object : Comparator<Fragment<Target>> {
-                override fun compare(left: Fragment<Target>, right: Fragment<Target>): Int {
-                    if (left.canSee(right)) {
-                        return -1
-                    } else if (right.canSee(left)) {
-                        return 1
-                    } else if (left == right) {
-                        return 0
-                    } else {
-                        /**
-                         * The target fragment can see left and right, but the fragments are incomparable. For example in:
-                         * ab; bc; b -> ab; b -> bc;
-                         * b can see ab and bc, but ab and bc are incomparable
-                         */
-                        return left.identifier.compareTo(right.identifier)
-                    }
-                }
-            }
-        )
-        modulesFragmentClasspath[fragment] = fragmentClasspath
-    }
-    return modulesFragmentClasspath
-}
-
-data class Module<Target>(
-    // Do we even need this identifier
-    val identifier: String,
-    val fragments: Set<Fragment<Target>>,
-) {
-//    override fun hashCode(): Int = identifier.hashCode()
-//    override fun equals(other: Any?): Boolean = identifier.equals(other?.toString())
-}
-
-data class Fragment<Target>(
-    val identifier: String,
-    val attributes: Set<Target>,
-) {
-//    override fun hashCode(): Int = attributes.hashCode()
-//    override fun equals(other: Any?): Boolean = other is Fragment<*> && attributes.equals(other.attributes)
-}
-
-fun <E> Set<E>.isProperSubsetOf(another: Set<E>): Boolean = another.size > size && isSubsetOf(another)
-fun <E> Set<E>.isSubsetOf(another: Set<E>): Boolean = another.containsAll(this)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Serialization.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Serialization.kt
deleted file mode 100644
index c65d9d8..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/Serialization.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.jetbrains.kotlin
-
-import com.google.gson.Gson
-import com.google.gson.GsonBuilder
-import java.io.File
-import java.nio.file.Path
-
-
-data class Uklib<Target>(
-    val module: Module<Target>,
-    val fragmentToArtifact: Map<String, File>,
-) {
-    fun serializeUklibToArchive(
-        outputZip: File,
-        temporariesDirectory: File,
-        serializeTarget: Target.() -> String = { this.toString() },
-    ) {
-        val gson = GsonBuilder().setPrettyPrinting().create()
-        val manifest = gson.toJson(
-            mapOf(
-                "identifier" to module.identifier,
-                // FIXME: How are we actually going to handle default target hierarchy cause bamboos?
-                "fragments" to module.fragments.filter { fragmentToArtifact[it.identifier]!!.exists() }.map {
-                    mapOf(
-                        "identifier" to it.identifier,
-                        "targets" to it.attributes.map(serializeTarget),
-                    )
-                }
-            )
-        )
-        zipFragments(
-            manifest = manifest,
-            fragmentToArtifact = fragmentToArtifact.filter { it.value.exists() },
-            outputZip = outputZip,
-            temporariesDirectory = temporariesDirectory,
-        )
-    }
-
-    companion object {
-        fun deserializeFromArchive(
-            archive: File,
-            unarchiveDirectory: Path,
-        ): Uklib<String> {
-            unzip(
-                zipFilePath = archive,
-                outputFolderPath = unarchiveDirectory.toFile(),
-            )
-            return deserializeFromDirectory(
-                unarchiveDirectory.toFile()
-            )
-        }
-
-        fun deserializeFromDirectory(directory: File): Uklib<String> {
-            val manifest = directory.resolve("umanifest")
-            if (!manifest.exists()) error("manifest doesn't exist")
-            val gson = Gson()
-            val map = gson.fromJson(manifest.readText(), Map::class.java) as Map<String, Any>
-            val identifier = map["identifier"] as String
-            val fragmentTokens = map["fragments"] as List<Map<String, Any>>
-
-            val fragments = fragmentTokens.map {
-                Fragment(
-                    identifier = it["identifier"] as String,
-                    attributes = (it["targets"] as List<String>).toSet(),
-                )
-            }.toSet()
-            return Uklib(
-                module = Module(
-                    identifier = identifier,
-                    fragments = fragments,
-                ),
-                fragmentToArtifact = fragments.map {
-                    it.identifier to directory.resolve(it.identifier)
-                }.toMap()
-            )
-        }
-    }
-}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibFragmentResolution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibFragmentResolution.kt
new file mode 100644
index 0000000..cf8e533
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibFragmentResolution.kt
@@ -0,0 +1,23 @@
+package org.jetbrains.kotlin.gradle.artifacts.uklibsModel
+
+import java.io.File
+
+//    /**
+//     * 1. No parts of the graph are isolated
+//     * 2. There are no cycles (this is already done by KGP)
+//     * 3. Everything is rooted in a single node (already checked in KGP)
+//     * 4. There are no fragments with duplicated attributes
+//     */
+
+data class Module(
+    val fragments: Set<Fragment>,
+)
+
+data class Fragment(
+    val identifier: String,
+    val attributes: Set<String>,
+    val file: () -> File,
+)
+
+fun <E> Set<E>.isProperSubsetOf(another: Set<E>): Boolean = another.size > size && isSubsetOf(another)
+fun <E> Set<E>.isSubsetOf(another: Set<E>): Boolean = another.containsAll(this)
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerialization.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerialization.kt
new file mode 100644
index 0000000..274a961
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerialization.kt
@@ -0,0 +1,93 @@
+package org.jetbrains.kotlin.gradle.artifacts.uklibsModel
+
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import org.jetbrains.kotlin.zipFragments
+import java.io.File
+
+
+internal data class Uklib(
+    val module: Module,
+    // FIXME: Use this version for a forward compatibility?
+    val manifestVersion: String,
+) {
+    fun serializeUklibToArchive(
+        outputZip: File,
+        temporariesDirectory: File,
+    ) {
+        val manifest = GsonBuilder().setPrettyPrinting().create().toJson(
+            mapOf(
+                FRAGMENTS to module.fragments.filter {
+                    // FIXME: Where was this coming from ???
+                    //fragmentIdentifierToArtifact[it.identifier]!!.exists()
+                    true
+                }.sortedBy {
+                    // Make sure we have some stable order of fragments
+                    it.identifier
+                }.map {
+                    mapOf(
+                        FRAGMENT_IDENTIFIER to it.identifier,
+                        ATTRIBUTES to it.attributes
+                            // Make sure we have some stable order of attributes
+                            .sorted(),
+                    )
+                },
+                UMANIFEST_VERSION to manifestVersion,
+            )
+        )
+        zipFragments(
+            manifest = manifest,
+            fragmentToArtifact = module.fragments.map {
+                it.identifier to it.file()
+            }.toMap(),
+            outputZip = outputZip,
+            temporariesDirectory = temporariesDirectory,
+        )
+    }
+
+    companion object {
+        fun deserializeFromDirectory(directory: File): Uklib {
+            val umanifest = directory.resolve(UMANIFEST_FILE_NAME)
+            if (!umanifest.exists()) error("Can't deserialize Uklib from ${directory} because ${UMANIFEST_FILE_NAME} doesn't exist")
+            val json = Gson().fromJson(umanifest.readText(), Map::class.java) as Map<String, Any>
+
+            val fragments = (json[FRAGMENTS] as List<Map<String, Any>>).map { fragment ->
+                val fragmentIdentifier = fragment[FRAGMENT_IDENTIFIER] as String
+                Fragment(
+                    identifier = fragmentIdentifier,
+                    attributes = (fragment[ATTRIBUTES] as List<String>).toSet(),
+                    file = {
+                        directory.resolve(fragmentIdentifier)
+                    }
+                )
+            }.toHashSet()
+            return Uklib(
+                module = Module(
+                    fragments = fragments,
+                ),
+                manifestVersion = json[UMANIFEST_VERSION] as String,
+            )
+        }
+
+        // Use this in diagnostics
+        const val UKLIB_NAME = "uklib"
+
+        // This extension has to be stable because we need to filter transitive jars in the transform
+        const val UKLIB_EXTENSION = "uklib"
+
+        /**
+         * The packaging must be equal to the extension because when resolving POM only components, Gradle prefers the artifact with the
+         * <packaging> POM value over the .jar (but falls back to jar if the artifact doesn't exist)
+         */
+        const val UKLIB_PACKAGING = UKLIB_EXTENSION
+
+        const val UMANIFEST_FILE_NAME = "umanifest"
+
+        const val FRAGMENTS = "fragments"
+        const val FRAGMENT_IDENTIFIER = "identifier"
+        const val ATTRIBUTES = "targets"
+        const val UMANIFEST_VERSION = "manifestVersion"
+
+        const val CURRENT_UMANIFEST_VERSION = "0.0.1"
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerializationUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerializationUtils.kt
new file mode 100644
index 0000000..438e6b2
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/UklibSerializationUtils.kt
@@ -0,0 +1,100 @@
+package org.jetbrains.kotlin
+
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.incremental.deleteDirectoryContents
+import java.io.BufferedOutputStream
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.nio.file.Files
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
+import java.util.zip.ZipOutputStream
+
+/**
+ * // FIXME: Test this!!!
+ *
+ * All of the rezipping happens at execution time in ArchiveUklibTask:
+ * - if the incoming fragment is a .klib or a .jar, just unzip it and zip into the .uklib zip
+ * - if the incoming fragment is a directory, probably it's an unpacked klib, so just copy it
+ */
+private val allowRepackingArchivesWithExtensions = setOf(
+    "klib",
+    "jar",
+)
+
+internal fun zipFragments(
+    manifest: String,
+    fragmentToArtifact: Map<String, File>,
+    outputZip: File,
+    temporariesDirectory: File,
+) {
+    ZipOutputStream(
+        BufferedOutputStream(
+            FileOutputStream(outputZip)
+        )
+    ).use { zipOutputStream ->
+        // Pack the manifest
+        zipOutputStream.putNextEntry(ZipEntry(Uklib.UMANIFEST_FILE_NAME))
+        manifest.byteInputStream().copyTo(zipOutputStream)
+
+        fragmentToArtifact.forEach { (identifier, file) ->
+            // Assume we are handling unpacked metadata and platform klibs
+            if (file.isDirectory) {
+                packDirectory(file, identifier, zipOutputStream)
+            } else if (file.extension in allowRepackingArchivesWithExtensions) {
+                val temp = temporariesDirectory.resolve(identifier)
+                if (temp.exists()) temp.deleteDirectoryContents()
+                temp.mkdirs()
+                unzip(
+                    zipFilePath = file,
+                    outputFolderPath = temp,
+                )
+                packDirectory(
+                    directory = temp,
+                    identifier = identifier,
+                    zipOutputStream = zipOutputStream,
+                )
+            } else {
+                error("Trying to pack invalid file in uklib: ${file}")
+            }
+        }
+        zipOutputStream.closeEntry()
+    }
+}
+
+private fun packDirectory(
+    directory: File,
+    identifier: String,
+    zipOutputStream: ZipOutputStream
+) {
+    Files.walk(directory.toPath()).forEach { path ->
+        val zipEntry = ZipEntry(identifier + "/" + path.toFile().toRelativeString(directory))
+        if (!Files.isDirectory(path)) {
+            zipOutputStream.putNextEntry(zipEntry)
+            Files.newInputStream(path).use { inputStream ->
+                inputStream.copyTo(zipOutputStream)
+            }
+            zipOutputStream.closeEntry()
+        }
+    }
+}
+
+private fun unzip(zipFilePath: File, outputFolderPath: File) {
+    ZipInputStream(FileInputStream(zipFilePath)).use { zipInputStream ->
+        var zipEntry: ZipEntry? = zipInputStream.nextEntry
+        while (zipEntry != null) {
+            val newFile = File(outputFolderPath, zipEntry.name)
+            if (zipEntry.isDirectory) {
+                newFile.mkdirs()
+            } else {
+                newFile.parentFile?.mkdirs()
+                FileOutputStream(newFile).use { fileOutputStream ->
+                    zipInputStream.copyTo(fileOutputStream)
+                }
+            }
+            zipEntry = zipInputStream.nextEntry
+        }
+        zipInputStream.closeEntry()
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/utils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/utils.kt
deleted file mode 100644
index 7a84ac4..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsModel/utils.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.jetbrains.kotlin
-
-import org.jetbrains.kotlin.incremental.deleteDirectoryContents
-import java.io.BufferedOutputStream
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileOutputStream
-import java.nio.file.Files
-import java.util.zip.ZipEntry
-import java.util.zip.ZipInputStream
-import java.util.zip.ZipOutputStream
-
-fun zipFragments(
-    manifest: String,
-    fragmentToArtifact: Map<String, File>,
-    outputZip: File,
-    temporariesDirectory: File,
-) {
-    ZipOutputStream(BufferedOutputStream(FileOutputStream(outputZip))).use { zos ->
-        fragmentToArtifact.forEach { (identifier, file) ->
-            // Unpacked metadata classes
-            if (file.isDirectory) {
-                packDirectory(file, identifier, zos)
-            } else if (file.extension == "klib") {
-                val temp = temporariesDirectory.resolve(identifier)
-                if (temp.exists()) temp.deleteDirectoryContents()
-                temp.mkdirs()
-                unzip(
-                    zipFilePath = file,
-                    outputFolderPath = temp,
-                )
-                packDirectory(
-                    directory = temp,
-                    identifier = identifier,
-                    zos = zos,
-                )
-            } else {
-                error("Trying to pack invalid file in uklib: ${file}")
-            }
-        }
-        zos.putNextEntry(ZipEntry("umanifest"))
-        manifest.byteInputStream().copyTo(zos)
-        zos.closeEntry()
-    }
-}
-
-private fun packDirectory(
-    directory: File,
-    identifier: String,
-    zos: ZipOutputStream
-) {
-    Files.walk(directory.toPath()).forEach { path ->
-        val zipEntry = ZipEntry(identifier + "/" + path.toFile().toRelativeString(directory))
-        if (!Files.isDirectory(path)) {
-            zos.putNextEntry(zipEntry)
-            Files.newInputStream(path).use { inputStream ->
-                inputStream.copyTo(zos)
-            }
-            zos.closeEntry()
-        }
-    }
-}
-
-fun unzip(zipFilePath: File, outputFolderPath: File) {
-    val buffer = ByteArray(1024)
-    ZipInputStream(FileInputStream(zipFilePath)).use { zis ->
-        var zipEntry: ZipEntry? = zis.nextEntry
-        while (zipEntry != null) {
-            val newFile = File(outputFolderPath, zipEntry.name)
-            if (zipEntry.isDirectory) {
-                newFile.mkdirs()
-            } else {
-                newFile.parentFile?.mkdirs()
-                FileOutputStream(newFile).use { fos ->
-                    zis.copyTo(fos)
-                }
-            }
-            zipEntry = zis.nextEntry
-        }
-        zis.closeEntry()
-    }
-}
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibArchiveTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/ArchiveUklibTask.kt
similarity index 82%
rename from libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibArchiveTask.kt
rename to libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/ArchiveUklibTask.kt
index 1c32e18..6f7e8e4 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibArchiveTask.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/ArchiveUklibTask.kt
@@ -12,16 +12,16 @@
 import org.gradle.api.tasks.Internal
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
-import org.jetbrains.kotlin.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
 import org.jetbrains.kotlin.gradle.utils.getFile
 
-internal abstract class UklibArchiveTask : DefaultTask() {
+internal abstract class ArchiveUklibTask : DefaultTask() {
     @get:Internal
-    abstract val model: Property<Uklib<String>>
+    abstract val model: Property<Uklib>
 
     @get:OutputFile
     val outputZip: RegularFileProperty = project.objects.fileProperty().convention(
-        project.layout.buildDirectory.file("output.uklib")
+        project.layout.buildDirectory.file("package.${Uklib.UKLIB_EXTENSION}")
     )
 
     @get:Internal
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupPublication.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupPublication.kt
deleted file mode 100644
index c4a2ffe..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupPublication.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
- */
-
-package org.jetbrains.kotlin.gradle.artifacts.uklibsPublication
-
-import org.gradle.api.Project
-import org.gradle.api.attributes.Usage
-import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
-import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
-import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
-import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
-import org.jetbrains.kotlin.gradle.plugin.await
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
-import org.jetbrains.kotlin.gradle.tasks.dependsOn
-
-internal suspend fun Project.setupPublication() {
-    val sourceSets = multiplatformExtension.awaitSourceSets()
-    val metadataTarget = multiplatformExtension.awaitMetadataTarget()
-    val targets = multiplatformExtension.awaitTargets()
-    KotlinPluginLifecycle.Stage.AfterFinaliseCompilations.await()
-
-    val packUklib = tasks.register("packUklib", UklibArchiveTask::class.java)
-
-    val kgpModel = uklibFromKGPModel(
-        targets = targets.toList(),
-        onPublishCompilation = {
-            packUklib.dependsOn(it.compileTaskProvider)
-        }
-    )
-
-    packUklib.configure {
-        it.model.set(kgpModel)
-    }
-    artifacts.add(metadataTarget.uklibElementsConfigurationName, packUklib)
-
-    if (kotlinPropertiesProvider.disablePlatformSpecificComponentsReferences) {
-        // FIXME: 20.11.2024 - ???
-        configurations.configureEach {
-            if (!it.isCanBeConsumed) return@configureEach
-            if (it.attributes.getAttribute(Usage.USAGE_ATTRIBUTE)?.name != KotlinUsages.KOTLIN_UKLIB) {
-                it.isCanBeConsumed = false
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupUklibPublication.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupUklibPublication.kt
new file mode 100644
index 0000000..d09f7ec
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/SetupUklibPublication.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.artifacts.uklibsPublication
+
+import org.gradle.api.Project
+import org.gradle.api.tasks.TaskProvider
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Module
+import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.tasks.locateTask
+
+internal suspend fun Project.archiveUklibTask(): TaskProvider<ArchiveUklibTask> {
+    val taskName = "archiveUklib"
+    tasks.locateTask<ArchiveUklibTask>(taskName)?.let { return it }
+
+    val archiveUklib = tasks.register(taskName, ArchiveUklibTask::class.java)
+
+    val metadataTarget = multiplatformExtension.awaitMetadataTarget()
+    val allTargets = multiplatformExtension.awaitTargets().toMutableList()
+
+    val kgpFragments = kgpFragments(
+        metadataTarget = metadataTarget,
+        allTargets = allTargets,
+    )
+
+    kgpFragments.forEach { fragment ->
+        archiveUklib.configure {
+            // outputFile might be a directory or a file
+            it.inputs.files(fragment.outputFile)
+            // some outputFiles are derived from a project.provider, use explicit task dependency
+            it.dependsOn(fragment.providingTask)
+        }
+    }
+
+    archiveUklib.configure {
+        it.model.set(
+            Uklib(
+                module = Module(
+                    fragments = kgpFragments.map {
+                        it.fragment
+                    }.toHashSet(),
+                ),
+                manifestVersion = Uklib.CURRENT_UMANIFEST_VERSION,
+            )
+        )
+    }
+
+    return archiveUklib
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt
index 78da1fa..fd31faa 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/artifacts/uklibsPublication/UklibFromKGPModel.kt
@@ -5,95 +5,193 @@
 
 package org.jetbrains.kotlin.gradle.artifacts.uklibsPublication
 
-import org.jetbrains.kotlin.Uklib
-import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
-import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
+import org.gradle.api.provider.Provider
+import org.gradle.api.tasks.TaskProvider
+import org.gradle.jvm.tasks.Jar
+import org.jetbrains.kotlin.gradle.artifacts.metadataFragmentAttributes
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Fragment
+import org.jetbrains.kotlin.gradle.artifacts.metadataFragmentIdentifier
+import org.jetbrains.kotlin.gradle.artifacts.metadataPublishedArtifacts
+import org.jetbrains.kotlin.gradle.artifacts.publishedMetadataCompilations
+import org.jetbrains.kotlin.gradle.plugin.mpp.*
 import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
 import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
-import org.jetbrains.kotlin.transformKGPModelToUklibModel
+import org.jetbrains.kotlin.gradle.plugin.*
+import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
+import org.jetbrains.kotlin.gradle.plugin.await
+import org.jetbrains.kotlin.gradle.plugin.mpp.external.DecoratedExternalKotlinTarget
+import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType
 import java.io.File
 
-internal fun uklibFromKGPModel(
-    targets: List<KotlinTarget>,
-    onPublishCompilation: (KotlinCompilation<*>) -> Unit = {}
-): Uklib<String> {
-    val compilationToArtifact = mutableMapOf<KotlinCompilation<*>, Iterable<File>>()
 
-    targets.forEach { target ->
+internal data class KGPFragment(
+    val fragment: Fragment,
+    val providingTask: TaskProvider<*>,
+    val outputFile: Provider<File>,
+)
+
+internal suspend fun kgpFragments(
+    metadataTarget: KotlinMetadataTarget,
+    allTargets: List<KotlinTarget>,
+): List<KGPFragment> {
+    // Guarantee that we can safely access any compilations
+    KotlinPluginLifecycle.Stage.AfterFinaliseCompilations.await()
+
+    val fragments = mutableListOf<KGPFragment>()
+
+    metadataTarget.publishedMetadataCompilations().forEach { metadataCompilation ->
+        val artifact = metadataCompilation.project.provider {
+            metadataCompilation.metadataPublishedArtifacts.singleFile
+        }
+        fragments.add(
+            KGPFragment(
+                fragment = Fragment(
+                    identifier = metadataCompilation.metadataFragmentIdentifier,
+                    attributes = metadataCompilation.metadataFragmentAttributes.map { it.unwrap() }.toSet(),
+                    file = {
+                        artifact.get()
+                    }
+                ),
+                providingTask = metadataCompilation.compileTaskProvider,
+                outputFile = artifact,
+            )
+        )
+    }
+
+    allTargets.filterNot {
+        it == metadataTarget
+    }.forEach { target ->
+        /**
+         * FIXME: Tie this implementation to the publication implementations that are hardcoded in KotlinTarget to make the dependency
+         * between the artifact that is published in Uklib and in the old publication model visible
+         */
         when (target) {
             is KotlinJsIrTarget -> {
-                error("...")
-//                    val mainComp = target.compilations.getByName(MAIN_COMPILATION_NAME)
-//                    compilationToArtifact[mainComp] = mainComp.out
-            }
-            is KotlinJvmTarget -> {
-                val mainComp = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
-                // FIXME: How do we handle that there are multiple classesDir?
-                /**
-                 * What should we do with multiple classes output:
-                 *
-                 * 1. What is going to happen if Foo collides across Kotlin and Java compilations. Is one picked over the other or is there a
-                 * class redeclaration error?
-                 * 2. Publication always has a single jar
-                 *
-                 * TODO: Discuss this case in text
-                 */
-                compilationToArtifact[mainComp] = mainComp.output.classesDirs
-                onPublishCompilation(mainComp)
+                val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
+                val file = mainCompilation.compileTaskProvider.flatMap { it.klibOutput }
+                fragments.add(
+                    KGPFragment(
+                        fragment = Fragment(
+                            identifier = mainCompilation.fragmentIdentifier,
+                            attributes = setOf(mainCompilation.uklibFragmentPlatformAttribute.unwrap()),
+                            file = {
+                                file.get()
+                            }
+                        ),
+                        providingTask = mainCompilation.compileTaskProvider,
+                        outputFile = file,
+                    )
+                )
             }
             is KotlinNativeTarget -> {
-                val mainComp = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
-                compilationToArtifact[mainComp] = listOf(
-                    // FIXME: Make this lazy
-                    // FIXME: We have to unzip this
-                    // FIXME: 13.11 - Just use unpacked compilation directly
-                    mainComp.compileTaskProvider.flatMap {
-                        it.outputFile
-                    }.get()
+                val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
+                val file = mainCompilation.compileTaskProvider.flatMap { it.klibOutput }
+                fragments.add(
+                    KGPFragment(
+                        fragment = Fragment(
+                            identifier = mainCompilation.fragmentIdentifier,
+                            attributes = setOf(mainCompilation.uklibFragmentPlatformAttribute.unwrap()),
+                            file = {
+                                file.get()
+                            }
+                        ),
+                        providingTask = mainCompilation.compileTaskProvider,
+                        outputFile = file,
+                    )
                 )
-                onPublishCompilation(mainComp)
             }
-            // FIXME: Metadata target forms a natural bamboo with default target hierarchy
-            /**
-             * What to do with bamboo and default target hierarchy: this is actually a problem because this works in KGP, but with Uklibs
-             * this is not going to work
-             *
-             *
-             * 1. Can we refactor metadata compilations to compile all same-target compilations: no because expect/actuals must not be in the same compilation
-             * But maybe we could relax this inside the compiler
-             *
-             * 2. Source set target context feature? It will allow declaring e.g. commonMain that is constrained to ios and jvm, but providing jvm
-             * will not be required.
-             *
-             * 3. Prohibit bamboo source set configuration in. This will work for cases where there are no expect/actuals across metadata compilations
-             *
-             * Typical use case:
-             *
-             * TODO: Write communication about this in the channel
-             */
-            is KotlinMetadataTarget -> {
-                target.compilations
-                    // Probably this is not needed
-                    .filterNot { it is KotlinCommonCompilation && !it.isKlibCompilation }
-                    .forEach { compilation ->
-                        // FIXME: Aren't test compilations going to be here?
-                        compilationToArtifact[compilation] = compilation.output.classesDirs
-                        onPublishCompilation(compilation)
-                    }
+            is KotlinJvmTarget -> {
+                val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
+                @Suppress("UNCHECKED_CAST")
+                val jarTask = (target.project.tasks.named(target.artifactsTaskName) as TaskProvider<Jar>)
+                val jarArtifact = jarTask.flatMap {
+                    it.archiveFile.map { it.asFile }
+                }
+                fragments.add(
+                    KGPFragment(
+                        fragment = Fragment(
+                            identifier = mainCompilation.fragmentIdentifier,
+                            attributes = setOf(mainCompilation.uklibFragmentPlatformAttribute.unwrap()),
+                            file = {
+                                jarArtifact.get()
+                            }
+                        ),
+                        providingTask = jarTask,
+                        outputFile = jarArtifact,
+                    )
+                )
+            }
+            else -> {
+                when (target.uklibFragmentPlatformAttribute) {
+                    is UklibFragmentPlatformAttribute.OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication -> { /* Do nothing for AGP */ }
+                    is UklibFragmentPlatformAttribute.PublishAndConsumeInAllCompilations -> { /* FIXME: rewrite the logic above */ }
+                    is UklibFragmentPlatformAttribute.FailOnPublicationAndIgnoreForConsumption -> target.uklibFragmentPlatformAttribute.unwrap()
+                }
             }
         }
     }
 
-    return transformKGPModelToUklibModel(
-        "stub",
-        publishedCompilations = compilationToArtifact.keys.toList(),
-        publishedArtifact = { compilationToArtifact[this]!!.single() },
-        defaultSourceSet = { this.defaultSourceSet },
-        target = { this.target.targetName },
-        dependsOn = { this.dependsOn },
-        identifier = { this.name }
-    )
-}
\ No newline at end of file
+    return fragments
+}
+
+internal enum class UklibJsTargetIdentifier {
+    js_ir,
+    wasm_js,
+    wasm_wasi;
+
+    fun deserialize(value: String): UklibJsTargetIdentifier {
+        return enumValueOf<UklibJsTargetIdentifier>(value)
+    }
+}
+
+internal sealed class UklibFragmentPlatformAttribute {
+    // Jvm, native, js
+    data class PublishAndConsumeInAllCompilations(val attribute: String) : UklibFragmentPlatformAttribute()
+    // Android
+    data class OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication(val attribute: String) : UklibFragmentPlatformAttribute()
+    // External target
+    data class FailOnPublicationAndIgnoreForConsumption(val error: String) : UklibFragmentPlatformAttribute()
+
+    // FIXME: Separate unwrap to consume for publication vs compilation
+    fun unwrap(): String = when (this) {
+        is PublishAndConsumeInAllCompilations -> attribute
+        is OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication -> attribute
+        is FailOnPublicationAndIgnoreForConsumption -> error(error)
+    }
+}
+
+internal val KotlinCompilation<*>.uklibFragmentPlatformAttribute: UklibFragmentPlatformAttribute get() = this.target.uklibFragmentPlatformAttribute
+internal val KotlinTarget.uklibFragmentPlatformAttribute: UklibFragmentPlatformAttribute
+    get() {
+        // FIXME: Actually maybe request jvm transform in Android?
+        if (this is KotlinAndroidTarget) {
+            return UklibFragmentPlatformAttribute.OnlyConsumeInMetadataCompilationsAndIgnoreAtPublication(targetName)
+        }
+
+        when (this) {
+            is KotlinNativeTarget -> konanTarget.name
+            is KotlinJsIrTarget -> when (platformType) {
+                KotlinPlatformType.js -> UklibJsTargetIdentifier.js_ir.name
+                KotlinPlatformType.wasm -> when (wasmTargetType ?: error("${KotlinJsIrTarget::class} missing wasm type in wasm platform ")) {
+                    KotlinWasmTargetType.JS -> UklibJsTargetIdentifier.wasm_js.name
+                    KotlinWasmTargetType.WASI -> UklibJsTargetIdentifier.wasm_wasi.name
+                }
+                else -> error("${KotlinJsIrTarget::class} unexpected platform type ${platformType}")
+            }
+            // FIXME: Is this correct?
+            is KotlinJvmTarget -> targetName
+            else -> null
+        }?.let {
+            return UklibFragmentPlatformAttribute.PublishAndConsumeInAllCompilations(it)
+        }
+
+        val error = when (this) {
+            is KotlinMetadataTarget -> "Metadata target does't have a platform attribute"
+            // FIXME: Test this !!!
+            is DecoratedExternalKotlinTarget -> "FIXME: This is explicitly unsupported"
+            else -> "???"
+        }
+        return UklibFragmentPlatformAttribute.FailOnPublicationAndIgnoreForConsumption(error)
+    }
+
+internal val KotlinCompilation<*>.fragmentIdentifier: String get() = defaultSourceSet.name
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt
index d19ecba..65301db 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/AbstractKotlinNativeBinaryContainer.kt
@@ -5,6 +5,7 @@
 import org.gradle.api.Project
 import org.jetbrains.kotlin.gradle.plugin.mpp.*
 import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
+import java.util.concurrent.atomic.AtomicReference
 
 // DO NOT EDIT MANUALLY! Generated by org.jetbrains.kotlin.generators.gradle.dsl.MppNativeBinaryDSLCodegenKt
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt
index 96b9512..0140d41 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt
@@ -184,7 +184,7 @@
 
     KotlinPlatformType.js -> if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_JS_MODULE_NAME
     KotlinPlatformType.wasm -> KOTLIN_STDLIB_MODULE_NAME
-    KotlinPlatformType.native, KotlinPlatformType.unknown -> null
+    KotlinPlatformType.native -> null
     KotlinPlatformType.common -> // there's no platform compilation that the source set is default for
         if (isVersionWithGradleMetadata) KOTLIN_STDLIB_MODULE_NAME else KOTLIN_STDLIB_COMMON_MODULE_NAME
 }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt
index fc31597..8e83fb3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt
@@ -40,7 +40,7 @@
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_RESOURCES_PUBLICATION
-import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB_VARIANT
+import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_FILTER_RESOURCES_BY_EXTENSION
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT
@@ -195,10 +195,10 @@
     val uklibResolutionStrategy: UklibResolutionStrategy
         get() = this.get(KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY)?.let {
             UklibResolutionStrategy.fromProperty(it)
-        } ?: UklibResolutionStrategy.PreferUklibVariant
+        } ?: UklibResolutionStrategy.AllowResolvingUklibs
 
-    val publishUklibVariant: Boolean
-        get() = booleanProperty(KOTLIN_MPP_PUBLISH_UKLIB_VARIANT) ?: false
+    val publishUklib: Boolean
+        get() = booleanProperty(KOTLIN_MPP_PUBLISH_UKLIB) ?: false
 
     val fakeUkibTransforms: Boolean
         get() = booleanProperty(KOTLIN_MPP_FAKE_UKLIB_TRANSFORMS) ?: false
@@ -639,7 +639,7 @@
         val KOTLIN_JS_STDLIB_DOM_API_INCLUDED = property("kotlin.js.stdlib.dom.api.included")
         val KOTLIN_JS_YARN = property("kotlin.js.yarn")
 
-        val KOTLIN_MPP_PUBLISH_UKLIB_VARIANT = property("kotlin.mpp.publishUklibVariant")
+        val KOTLIN_MPP_PUBLISH_UKLIB = property("kotlin.mpp.publishUklib")
         val KOTLIN_MPP_FAKE_UKLIB_TRANSFORMS = property("kotlin.mpp.fakeUklibTransforms")
         val KOTLIN_MPP_DISABLE_PLATFORM_SPECIFIC_COMPONENTS_REFERENCES = property("kotlin.mpp.disablePlatformSpecificComponentsReferences")
         val KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY = property("kotlin.mpp.uklibResolutionStrategy")
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt
index bc47212..06eab08 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectCompileOnlyDependenciesChecker.kt
@@ -105,7 +105,7 @@
             KotlinPlatformType.js,
             -> false
 
-            KotlinPlatformType.native, KotlinPlatformType.unknown -> {
+            KotlinPlatformType.native -> {
                 @Suppress("DEPRECATION")
                 PropertiesProvider(project).ignoreIncorrectNativeDependencies == true
             }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt
index f382249..458380f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/IdeMultiplatformImportFactory.kt
@@ -11,6 +11,8 @@
 import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.SourceSetConstraint
 import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.*
 import org.jetbrains.kotlin.gradle.plugin.ide.dependencyTransformers.IdePlatformStdlibCommonDependencyFilter
+import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
 import org.jetbrains.kotlin.gradle.targets.native.internal.commonizerTarget
 
 internal fun IdeMultiplatformImport(extension: KotlinProjectExtension): IdeMultiplatformImport {
@@ -65,6 +67,7 @@
             priority = IdeMultiplatformImport.Priority.normal
         )
 
+        // Этот мы используем для резолва метадаты
         registerDependencyResolver(
             resolver = IdeTransformedMetadataDependencyResolver,
             constraint = !SourceSetConstraint.isSingleKotlinTarget and !SourceSetConstraint.isJvmAndAndroid,
@@ -72,6 +75,7 @@
             priority = IdeMultiplatformImport.Priority.normal
         )
 
+        // Не понимаю зачем это нужно если есть верхний матчер
         registerDependencyResolver(
             resolver = IdeOriginalMetadataDependencyResolver,
             constraint = !SourceSetConstraint.isLeaf,
@@ -81,6 +85,7 @@
 
         registerDependencyResolver(
             resolver = IdeBinaryDependencyResolver(),
+            // FIXME: Why is this single platform and not target?
             constraint = SourceSetConstraint.isSinglePlatformType,
             phase = IdeMultiplatformImport.DependencyResolutionPhase.BinaryDependencyResolution,
             priority = IdeMultiplatformImport.Priority.normal
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt
index 359961a..7a2e1e3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt
@@ -14,6 +14,9 @@
 import org.gradle.internal.component.local.model.OpaqueComponentArtifactIdentifier
 import org.gradle.internal.resolve.ModuleVersionResolveException
 import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
+import org.jetbrains.kotlin.gradle.artifacts.uklibDestinationAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateUnzipped
 import org.jetbrains.kotlin.gradle.idea.tcs.*
 import org.jetbrains.kotlin.gradle.idea.tcs.extras.artifactsClasspath
 import org.jetbrains.kotlin.gradle.idea.tcs.extras.isOpaqueFileDependency
@@ -23,7 +26,6 @@
 import org.jetbrains.kotlin.gradle.plugin.ide.*
 import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver.Companion.gradleArtifact
 import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeBinaryDependencyResolver.ArtifactResolutionStrategy
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation
 import org.jetbrains.kotlin.gradle.plugin.mpp.internal
 import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
 import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
@@ -166,7 +168,7 @@
                 is ModuleComponentIdentifier -> {
                     // FIXME: Где-то тут разламывается AS интеграция из-за того что совпадает id?
                     if (artifact.variant.attributes.getAttribute(uklibStateAttribute) == uklibStateUnzipped) {
-                        val platform = artifact.variant.attributes.getAttribute(uklibPlatformAttribute)
+                        val platform = artifact.variant.attributes.getAttribute(uklibDestinationAttribute)
                         IdeaKotlinResolvedBinaryDependency(
                             coordinates = IdeaKotlinBinaryCoordinates(
                                 group = componentId.group,
@@ -251,10 +253,11 @@
         Prevent case where this resolver was configured to resolve dependencies for a metadata compilation:
         Refuse resolution. Write your own code if you really want to do this!
          */
-        if (compilation is KotlinMetadataCompilation<*>) {
-            logger.warn("Unexpected ${KotlinMetadataCompilation::class.java}(${compilation.name}) for $sourceSet")
-            return null
-        }
+        // FIXME: Why?
+//        if (compilation is KotlinMetadataCompilation<*>) {
+//            logger.warn("Unexpected ${KotlinMetadataCompilation::class.java}(${compilation.name}) for $sourceSet")
+//            return null
+//        }
 
         return createArtifactViewFromConfiguration(sourceSet, compilation.internal.configurations.compileDependencyConfiguration)
     }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt
index 1719ea8..e04ad15 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/AbstractKotlinTarget.kt
@@ -92,7 +92,7 @@
             )
         )
 
-        val result = createKotlinVariant(componentName, mainCompilation, usageContexts)
+        val result = createKotlinVariant(componentName, usageContexts)
 
         setOf(result)
     }
@@ -107,19 +107,18 @@
 
     protected open fun createKotlinVariant(
         componentName: String,
-        compilation: KotlinCompilation<*>,
         usageContexts: Set<DefaultKotlinUsageContext>
     ): KotlinVariant {
         val kotlinExtension = project.kotlinExtension
 
         val result =
             if (kotlinExtension !is KotlinMultiplatformExtension || targetName == KotlinMetadataTarget.METADATA_TARGET_NAME)
-                KotlinVariantWithCoordinates(compilation, usageContexts)
+                KotlinVariantWithCoordinates(this, usageContexts)
             else {
                 val metadataTarget =
                     kotlinExtension.targets.getByName(KotlinMetadataTarget.METADATA_TARGET_NAME) as AbstractKotlinTarget
 
-                KotlinVariantWithMetadataVariant(compilation, usageContexts, metadataTarget)
+                KotlinVariantWithMetadataVariant(this, usageContexts, metadataTarget)
             }
 
         result.componentName = componentName
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt
index 22df14d..37afd0f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt
@@ -17,6 +17,10 @@
 import org.jetbrains.kotlin.*
 import org.jetbrains.kotlin.gradle.artifacts.uklibStateAttribute
 import org.jetbrains.kotlin.gradle.artifacts.uklibStateUnzipped
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Fragment
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.isSubsetOf
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.uklibFragmentPlatformAttribute
 import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
 import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
 import org.jetbrains.kotlin.gradle.plugin.*
@@ -47,6 +51,9 @@
         return "$verb, dependency = $dependency"
     }
 
+    /**
+     * KeepOriginalDependency нужен для кейса если в GMT попали настоящие jar'ники?
+     */
     class KeepOriginalDependency(
         dependency: ResolvedComponentResult,
     ) : MetadataDependencyResolution(dependency)
@@ -116,8 +123,7 @@
         val objects: ObjectFactory,
         val kotlinKmpProjectIsolationEnabled: Boolean,
         val sourceSetMetadataLocationsOfProjectDependencies: KotlinProjectSharedDataProvider<SourceSetMetadataLocations>,
-        // FIXME: ???
-        val sourceSetTargetMembership: Set<String>,
+        val uklibFragmentAttributes: Set<String>,
     ) {
         constructor(project: Project, kotlinSourceSet: KotlinSourceSet) : this(
             build = project.currentBuild,
@@ -133,11 +139,10 @@
             kotlinKmpProjectIsolationEnabled = project.kotlinPropertiesProvider.kotlinKmpProjectIsolationEnabled,
             sourceSetMetadataLocationsOfProjectDependencies = project.kotlinSecondaryVariantsDataSharing
                 .consumeCommonSourceSetMetadataLocations(kotlinSourceSet.internal.resolvableMetadataConfiguration),
-            sourceSetTargetMembership = kotlinSourceSet.internal.compilations
+            uklibFragmentAttributes = kotlinSourceSet.internal.compilations
                 .map { it.target }
                 .filter { it !is KotlinMetadataTarget }
-                // FIXME: See uklibFromKGPModel
-                .map { it.targetName }
+                .map { it.uklibFragmentPlatformAttribute.unwrap() }
                 .toSet()
         )
     }
@@ -161,6 +166,7 @@
     private fun doTransform(): Iterable<MetadataDependencyResolution> {
         val result = mutableListOf<MetadataDependencyResolution>()
 
+        // Это очередь из порезолвленных компонентнов?
         val resolvedDependencyQueue: Queue<ResolvedDependencyResult> = ArrayDeque<ResolvedDependencyResult>().apply {
             addAll(
                 params.resolvedMetadataConfiguration
@@ -234,13 +240,25 @@
      * * based on the project structure metadata, determine which of the module's dependencies are requested by the
      *   source sets in *S*, then consider only these transitive dependencies, ignore the others;
      */
+    // По идее эта логика исполняется на зависимость, на каждый потребляющий SS
     private fun processDependency(
         dependency: ResolvedDependencyResult,
+        // Я не понимаю откуда приходят эти SS
+        /**
+         * 24.11.2024 - Наверное для iosMain они приходят из commonMain. Это точно так, они приходят из parent тасок которые делают GMT
+         */
         sourceSetsVisibleInParents: Set<String>,
     ): MetadataDependencyResolution {
         val module = dependency.selected
         val moduleId = module.id
 
+        /**
+         * FIXME: 01.12-2024 - Add diagnostics:
+         *
+         * 1. Look at the graph of
+         */
+
+        // Это .jar ник с метадатными klib'ами
         val artifact = params
             .resolvedMetadataConfiguration
             .getArtifacts(dependency)
@@ -266,44 +284,43 @@
                 moduleId,
                 sourceSetsVisibleInParents,
 
-                sourceSetName = params.sourceSetName,
-                targetMembership = params.sourceSetTargetMembership,
+                //sourceSetName = params.sourceSetName,
+                uklibFragmentAttributes = params.uklibFragmentAttributes,
             )
         } else {
             return MetadataDependencyResolution.KeepOriginalDependency(module)
         }
     }
 
+    // FIXME: How do we ensure classpath ordering for PSM dependencies ???
     private fun processUklibDependency(
         compositeMetadataArtifact: ResolvedArtifactResult,
         dependency: ResolvedDependencyResult,
         module: ResolvedComponentResult,
         moduleId: ComponentIdentifier,
-        // FIXME: ???
-        sourceSetsVisibleInParents: Set<String>,
 
-        sourceSetName: String,
-        targetMembership: Set<String>,
+        sourceSetsVisibleInParents: Set<String>,
+        uklibFragmentAttributes: Set<String>,
     ): MetadataDependencyResolution {
+        // Validate that
+
         val uklibDependency = Uklib.deserializeFromDirectory(
             compositeMetadataArtifact.file,
         )
 
-        val fragment = Fragment(sourceSetName, targetMembership)
-        val canSee: Fragment<String>.(Fragment<String>) -> Boolean = { attributes.isSubsetOf(it.attributes) }
-
+        val fragmentCanSee: Fragment.(Fragment) -> Boolean = { attributes.isSubsetOf(it.attributes) }
         val visibleFragments = uklibDependency.module.fragments.filter {
-            fragment.canSee(it)
-                    // FIXME: ??
+            uklibFragmentAttributes.isSubsetOf(it.attributes)
+                    // FIXME: Is this the correct place to filter out compilations transformed by the parent ?? See allVisibleSourceSetNames and visibleSourceSetNamesExcludingDependsOn
                     && it.identifier !in sourceSetsVisibleInParents
         }.sortedWith(
-            object : Comparator<Fragment<String>> {
-                override fun compare(left: Fragment<String>, right: Fragment<String>): Int {
-                    if (left.canSee(right)) {
+            object : Comparator<Fragment> {
+                override fun compare(left: Fragment, right: Fragment): Int {
+                    if (left.fragmentCanSee(right)) {
                         return -1
-                    } else if (right.canSee(left)) {
+                    } else if (right.fragmentCanSee(left)) {
                         return 1
-                    } else if (left == right) {
+                    } else if (left.attributes == right.attributes) {
                         return 0
                     } else {
                         return left.identifier.compareTo(right.identifier)
@@ -318,12 +335,12 @@
             dependency = dependency.selected,
             projectStructureMetadata = null,
             // FIXME: Don't filter this
-            allVisibleSourceSetNames = visibleFragments.map { it.identifier }.toSet(),
+            allVisibleSourceSetNames = visibleFragments.map { it.identifier }.toHashSet(),
             // FIXME: Only filter this, but for some reason this doesn't work???
-            visibleSourceSetNamesExcludingDependsOn = visibleFragments.map { it.identifier }.toSet(),
+            visibleSourceSetNamesExcludingDependsOn = visibleFragments.map { it.identifier }.toHashSet(),
 
             // 26.11.2024 - This is likely only used to walk further dependencies, so we want all of them
-            visibleTransitiveDependencies = dependency.selected.dependencies.filterIsInstance<ResolvedDependencyResult>().toSet(),
+            visibleTransitiveDependencies = dependency.selected.dependencies.filterIsInstance<ResolvedDependencyResult>().toHashSet(),
             metadataProvider = ArtifactMetadataProvider(
                 object : CompositeMetadataArtifact {
 
@@ -359,7 +376,7 @@
                                                     get() = ""
 
                                                 override fun copyTo(file: File): Boolean {
-                                                    return uklibDependency.fragmentToArtifact[fragment.identifier]!!.copyRecursively(
+                                                    return fragment.file().copyRecursively(
                                                         file,
                                                         overwrite = true,
                                                     )
@@ -431,11 +448,18 @@
                 isResolvedToProject
             )
 
+        // Тут будут те SS которые видит потребитель? Но где тогда происходит маппинг между SS?
+        /**
+         * 24.11.2024 - Все это происходит в рамках resolve'а classpath текущего SS
+         */
         val allVisibleSourceSets = sourceSetVisibility.visibleSourceSetNames
 
         // Keep only the transitive dependencies requested by the visible source sets:
         // Visit the transitive dependencies visible by parents, too (i.e. allVisibleSourceSets), as this source set might get a more
         // concrete view on them:
+        /**
+         * Набираем то, какие зависимости были указаны в рамках SS
+         */
         val requestedTransitiveDependencies: Set<ModuleDependencyIdentifier> =
             mutableSetOf<ModuleDependencyIdentifier>().apply {
                 projectStructureMetadata.sourceSetModuleDependencies.forEach { (sourceSetName, moduleDependencies) ->
@@ -449,9 +473,15 @@
             .filterIsInstance<ResolvedDependencyResult>()
             .filterTo(mutableSetOf()) { it.toModuleDependencyIdentifier() in requestedTransitiveDependencies }
 
+        /**
+         * Кажется мы проверяем, что SS в котором мы сейчас не платформенный и что он не порезолвился в проектную зависимость
+         *
+         * Не понимаю зачем это нужно, особенно как работает часть про !isResolvedToProject
+         */
         if (params.sourceSetName in params.platformCompilationSourceSets && !isResolvedToProject)
             return MetadataDependencyResolution.Exclude.PublishedPlatformSourceSetDependency(module, transitiveDependenciesToVisit)
 
+        // Наверное тут будут только новые видимые SS которые еще не были видны в parent SS
         val visibleSourceSetsExcludingDependsOn = allVisibleSourceSets.filterTo(mutableSetOf()) { it !in sourceSetsVisibleInParents }
 
         val metadataProvider = when (mppDependencyMetadataExtractor) {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt
index c549d2f..55c18ea 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt
@@ -6,13 +6,16 @@
 package org.jetbrains.kotlin.gradle.plugin.mpp
 
 import org.gradle.api.Project
+import org.gradle.api.artifacts.ModuleVersionIdentifier
+import org.gradle.api.artifacts.PublishArtifact
+import org.gradle.api.component.ComponentWithCoordinates
 import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
 import org.jetbrains.kotlin.gradle.dsl.HasConfigurableKotlinCompilerOptions
 import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
 import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptionsDefault
-import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
-import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
-import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.plugin.*
+import org.jetbrains.kotlin.gradle.plugin.launch
 import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
 import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
 import org.jetbrains.kotlin.gradle.utils.newInstance
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt
index 6a0d735..70e32cd 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt
@@ -86,7 +86,7 @@
                 // overrideConfigurationArtifacts = project.setProperty { listOf(allMetadataArtifact) }
             )
 
-            if (project.kotlinPropertiesProvider.publishUklibVariant) {
+            if (project.kotlinPropertiesProvider.publishUklib) {
                 this += DefaultKotlinUsageContext(
                     compilation = metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME),
                     mavenScope = KotlinUsageContext.MavenScope.COMPILE,
@@ -202,10 +202,15 @@
     override fun getDependencyConstraints(): MutableSet<out DependencyConstraint> =
         configuration.incoming.dependencyConstraints
 
-    override fun getArtifacts(): Set<PublishArtifact> =
-        overrideConfigurationArtifacts?.get()?.toSet() ?:
+    override fun getArtifacts(): Set<PublishArtifact> {
+        // Don't publish anything except the uklib
+        // FIXME: 11.11.2024 - I used this to disable the publication of all other artifacts
+        // FIXME: 19.11.2024 - Use this under a feature toggle?
+        // if (configuration.name != "metadataUklibElements") return emptySet()
+        return overrideConfigurationArtifacts?.get()?.toSet() ?:
         // TODO Gradle Java plugin does that in a different way; check whether we can improve this
         configuration.artifacts
+    }
 
     override fun getAttributes(): AttributeContainer {
         val configurationAttributes = overrideConfigurationAttributes ?: configuration.attributes
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt
index 9aa5e8d..9bb4906 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt
@@ -59,7 +59,13 @@
     private const val JAVA_RUNTIME_CLASSES = "java-runtime-classes"
     private const val JAVA_RUNTIME_RESOURCES = "java-runtime-resources"
 
+    // FIXME: Rename this?
     val values = setOf(KOTLIN_API, KOTLIN_RUNTIME)
+    val compatibleKotlinConsumerUsages = mapOf(
+        setOf(KOTLIN_API) to setOf(JAVA_API, "java-api-jars"),
+        // This should really only list KOTLIN_RUNTIME
+        setOf(KOTLIN_API, KOTLIN_RUNTIME) to setOf(JAVA_RUNTIME, "java-runtime-jars"),
+    )
 
     private val jvmPlatformTypes: Set<KotlinPlatformType> = setOf(jvm, androidJvm)
 
@@ -113,6 +119,7 @@
             when {
                 consumerValue?.name == KOTLIN_API && producerValue?.name.let { it == JAVA_API || it == "java-api-jars" } ->
                     compatible()
+                // FIXME: This can't really match KOTLIN_API because it matches the case above???
                 consumerValue?.name in values && producerValue?.name.let { it == JAVA_RUNTIME || it == "java-runtime-jars" } ->
                     compatible()
             }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt
index e39d08c..ef39d98 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt
@@ -139,6 +139,7 @@
 
     @TaskAction
     fun transformMetadata() {
+        // Не понимаю, это parent всмысле как commonMain для iosMain
         val parentLibrariesRecords: List<List<TransformedMetadataLibraryRecord>> = parentLibrariesIndexFiles
             .get()
             .map { librariesIndexFile -> librariesIndexFile.records() }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt
index 7597d55..b0f9a2c 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependenciesProjectStructureMetadataExtractorFactoryDeprecated.kt
@@ -41,8 +41,11 @@
     ): MppDependencyProjectStructureMetadataExtractor {
         val moduleId = metadataArtifact.variant.owner
 
+
         return if (moduleId is ProjectComponentIdentifier) {
+            // Чекаем участвует ли эта зависимость в билде? Зачем
             if (moduleId in currentBuild) {
+                // Это легаси логика которая ходит в рутовый проект и ищет там (in-memory?) PSM
                 val projectStructureMetadataProvider = currentBuildProjectStructureMetadataProviders[moduleId.projectPath]
                     ?: error("Project structure metadata not found for project '${moduleId.projectPath}'")
 
@@ -51,6 +54,7 @@
                     projectStructureMetadataProvider = projectStructureMetadataProvider::value
                 )
             } else {
+                // Это что-то про included build
                 /*
                 We switched to using 'buildPath' instead of 'buildName' in 1.9.20,
                 (See: https://youtrack.jetbrains.com/issue/KT-58157/)
@@ -70,6 +74,7 @@
                 )
             }
         } else {
+            // Просто достаем PSM из jar'ника
             JarMppDependencyProjectStructureMetadataExtractor(metadataArtifact.file)
         }
     }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt
index f3b53c0..054e05d 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt
@@ -81,21 +81,41 @@
      * the Gradle API for dependency variants behaves differently for project dependencies and published ones.
      */
     fun getVisibleSourceSets(
+        // e.g. commonMain
         visibleFromSourceSet: KotlinSourceSetName,
+        // Это порезолвленная зависимость (вероятно ее компонент в котором лежит PSM)
         resolvedRootMppDependency: ResolvedDependencyResult,
+        // Это видимо PSM этой зависимости
         dependencyProjectStructureMetadata: KotlinProjectStructureMetadata,
+        // Это просто значит, что это проектная зависимость
         resolvedToOtherProject: Boolean,
     ): SourceSetVisibilityResult {
         val resolvedRootMppDependencyId = resolvedRootMppDependency.selected.id
 
         val platformCompilationsByResolvedVariantName = mutableMapOf<String, PlatformCompilationData>()
 
+        /** Откуда берутся platformCompilations?
+         * platformCompilations это платформенные компиляции текущего модуля который делает GMT резолв
+         *
+         * 1. Берем платформенные компиляции
+         * 2. Только те которые участвуют в компиляции этого SS
+         * 3. Смотрим какие variant'ы порезолвили эти конфигурации и восстанавливаем
+        */
         val visiblePlatformVariantNames: List<Set<String>> = platformCompilations
+            /**
+             * Visibility алгоритм работает на конкретном SS. Тут мы отфильтировываем платформенные компиляции до тех который включают в себя этот SS
+             */
             .filter { visibleFromSourceSet in it.allSourceSets }
             .mapNotNull { platformCompilationData ->
                 val resolvedPlatformDependencies = platformCompilationData
+                    /**
+                     * resolvedDependenciesConfiguration это конфигурация которую платформенная компиляция будет резолвить для получения платформенных артефактов
+                     */
                     .resolvedDependenciesConfiguration
                     .allResolvedDependencies
+                    /**
+                     * Мне кажется тут Антон рассказывал про проблемы с shouldResolveConsistently
+                     */
                     .filter { it.selected.id isEqualsIgnoringVersion resolvedRootMppDependencyId }
                     /*
                     Returning null if we can't find the given dependency in a certain platform compilations dependencies.
@@ -111,7 +131,14 @@
                     */
                     .ifEmpty { return@mapNotNull null }
 
+                /**
+                 * Смотрим на зависимости которые порезолвила плафтморенная compileDependencyConfiguration. А именно на variant'ы которые
+                 * она порезолвила
+                 */
                 resolvedPlatformDependencies.map { resolvedPlatformDependency ->
+                    /**
+                     * Дропаем "-published" маркер названия варианта и восстанавливаем из него resolved variant
+                     */
                     val resolvedVariant = kotlinVariantNameFromPublishedVariantName(
                         resolvedPlatformDependency.resolvedVariant.displayName
                     )
@@ -128,6 +155,7 @@
             return SourceSetVisibilityResult(emptySet(), emptyMap())
         }
 
+
         val visibleSourceSetNames = visiblePlatformVariantNames
             .mapNotNull { platformVariants ->
                 platformVariants
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt
index 66168bf..b77fe0e 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinCompilation.kt
@@ -38,7 +38,7 @@
             KotlinPlatformType.jvm -> KotlinJvmCompilerOptionsFactory
             KotlinPlatformType.androidJvm -> KotlinJvmCompilerOptionsFactory
             KotlinPlatformType.js -> KotlinJsCompilerOptionsFactory
-            KotlinPlatformType.native, KotlinPlatformType.unknown -> KotlinNativeCompilerOptionsFactory
+            KotlinPlatformType.native -> KotlinNativeCompilerOptionsFactory
             KotlinPlatformType.wasm -> KotlinMultiplatformCommonCompilerOptionsFactory
         },
         compilationSourceSetsContainerFactory = { _, _ -> KotlinCompilationSourceSetsContainer(descriptor.defaultSourceSet) },
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt
index f9eea0e..b91887e 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/external/createExternalKotlinTarget.kt
@@ -77,7 +77,7 @@
         KotlinPlatformType.wasm,
         KotlinPlatformType.js -> project.objects.newInstance<KotlinJsCompilerOptionsDefault>()
         KotlinPlatformType.common -> project.objects.newInstance<KotlinCommonCompilerOptionsDefault>()
-        KotlinPlatformType.native, KotlinPlatformType.unknown -> project.objects.newInstance<KotlinNativeCompilerOptionsDefault>()
+        KotlinPlatformType.native -> project.objects.newInstance<KotlinNativeCompilerOptionsDefault>()
     }
 
     val target = ExternalKotlinTargetImpl(
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt
index ab9c94c..50c9281 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt
@@ -50,19 +50,16 @@
 }
 
 open class KotlinVariant(
-    val producingCompilation: KotlinCompilation<*>,
+    override val target: KotlinTarget,
     private val usages: Set<DefaultKotlinUsageContext>
 ) : InternalKotlinTargetComponent(), KotlinTargetComponentWithPublication {
     var componentName: String? = null
 
     var artifactTargetName: String = target.targetName
 
-    final override val target: KotlinTarget
-        get() = producingCompilation.target
-
     override fun getUsages(): Set<KotlinUsageContext> = usages.publishableUsages()
 
-    override fun getName(): String = componentName ?: producingCompilation.target.targetName
+    override fun getName(): String = componentName ?: target.targetName
 
     override var publishable: Boolean = true
     override val publishableOnCurrentHost: Boolean
@@ -90,16 +87,16 @@
 }
 
 open class KotlinVariantWithCoordinates(
-    producingCompilation: KotlinCompilation<*>,
+    target: KotlinTarget,
     usages: Set<DefaultKotlinUsageContext>,
-) : KotlinVariant(producingCompilation, usages),
+) : KotlinVariant(target, usages),
     KotlinTargetComponentWithCoordinatesAndPublication /* Gradle 4.7+ API, don't use with older versions */
 
 class KotlinVariantWithMetadataVariant(
-    producingCompilation: KotlinCompilation<*>,
+    target: KotlinTarget,
     usages: Set<DefaultKotlinUsageContext>,
     internal val metadataTarget: AbstractKotlinTarget,
-) : KotlinVariantWithCoordinates(producingCompilation, usages), ComponentWithVariants {
+) : KotlinVariantWithCoordinates(target, usages), ComponentWithVariants {
     override fun getVariants() = metadataTarget.components
 }
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt
index c07be88..876a662 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/PomDependenciesRewriter.kt
@@ -30,6 +30,7 @@
     }
 }
 
+// FIXME: 28.11.2024 - Наверное смысл PomDependenciesRewriter'а в том чтобы переписывать зависимости на платформенные слайсы
 internal abstract class PomDependenciesRewriter {
 
     open val taskDependencies: Any? get() = null
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt
index e35ab96..0c0e630 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/publishing/Publishing.kt
@@ -12,6 +12,9 @@
 import org.gradle.api.publish.PublishingExtension
 import org.gradle.api.publish.maven.MavenPublication
 import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
+import org.jetbrains.kotlin.gradle.artifacts.uklibsModel.Uklib
+import org.jetbrains.kotlin.gradle.artifacts.uklibsPublication.archiveUklibTask
+import org.jetbrains.kotlin.gradle.dsl.awaitMetadataTarget
 import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
 import org.jetbrains.kotlin.gradle.plugin.*
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
@@ -34,6 +37,7 @@
             project.extensions.configure(PublishingExtension::class.java) { publishing ->
                 createRootPublication(project, publishing).also(kotlinMultiplatformRootPublicationImpl::complete)
                 createTargetPublications(project, publishing)
+                createUklibSpecificMavenPublications(project, publishing)
             }
         } else {
             kotlinMultiplatformRootPublicationImpl.complete(null)
@@ -55,6 +59,9 @@
         (this as MavenPublicationInternal).publishWithOriginalFileName()
 
         addKotlinToolingMetadataArtifactIfNeeded(project)
+        if (project.kotlinPropertiesProvider.publishUklib) {
+            addUklibArtifactAndChangePackaging(project)
+        }
     }
 }
 
@@ -67,6 +74,16 @@
     }
 }
 
+private fun MavenPublication.addUklibArtifactAndChangePackaging(project: Project) {
+    // FIXME: This will break coroutines !!!
+    pom.packaging = Uklib.UKLIB_PACKAGING
+    project.launch {
+        artifact(project.archiveUklibTask()) { artifact ->
+            artifact.extension = Uklib.UKLIB_EXTENSION
+        }
+    }
+}
+
 private fun createTargetPublications(project: Project, publishing: PublishingExtension) {
     val kotlin = project.multiplatformExtension
     // Enforce the order of creating the publications, since the metadata publication is used in the other publications:
@@ -84,6 +101,22 @@
         }
 }
 
+private fun createUklibSpecificMavenPublications(project: Project, publishing: PublishingExtension) {
+    val publications = publishing.publications
+    project.launch {
+        val metadataTarget = project.multiplatformExtension.awaitMetadataTarget()
+        val componentPublication = publications.create("uklib", MavenPublication::class.java).apply {
+            artifactId = "${artifactId}-uklib"
+
+            // FIXME: jvm + uklib
+//            artifact(
+//
+//            )
+        }
+        metadataTarget.onPublicationCreated(componentPublication)
+    }
+}
+
 private fun InternalKotlinTarget.createTargetSpecificMavenPublications(publications: PublicationContainer) {
     kotlinComponents
         .filter { kotlinComponent -> kotlinComponent.publishableOnCurrentHost }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt
index da42660..df4a03c 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt
@@ -137,6 +137,8 @@
     }
 
     KotlinTargetArtifact.extensionPoint.apply {
+        // FIXME: This isn't mpp only
+        // FIXME: Disabling this breaks KotlinTargetSoftwareComponentImpl
         register(project, KotlinMetadataArtifact)
         register(project, KotlinLegacyCompatibilityMetadataArtifact)
         register(project, KotlinLegacyMetadataArtifact)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt
index a23dd77..02408f2 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt
@@ -133,7 +133,12 @@
     }
 
     if (target is KotlinMetadataTarget) {
-        if (target.project.kotlinPropertiesProvider.publishUklibVariant) {
+        if (target.project.kotlinPropertiesProvider.publishUklib) {
+            /**
+             * FIXME: 29.11.2024 - Do we actually want/need a consumable configuration?
+             *
+             * How will the POM publish with a project dependency and a multi-project publication?
+             */
             configurations.maybeCreateConsumable(target.internal.uklibElementsConfigurationName).apply {
                 description = "Resource files of main compilation of ${target.name}."
                 isVisible = false
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt
index f15c43a..5c5e93a 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/KotlinAndroidTarget.kt
@@ -192,7 +192,6 @@
 
                 createKotlinVariant(
                     lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()),
-                    compilation,
                     usageContexts,
                 ).apply {
                     publishable = isVariantPublished(androidVariant)
@@ -281,6 +280,7 @@
                 compilation,
                 mavenScope,
                 dependencyConfigurationName,
+                // !!!
                 overrideConfigurationArtifacts = project.setProperty { listOf(artifact) },
                 overrideConfigurationAttributes = configuration.attributes.filterOutAndroidVariantAttributes()
             )
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt
index a4badad..b58226b 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt
@@ -95,17 +95,16 @@
             )
         )
 
-        val result = createKotlinVariant(componentName, mainCompilation, usageContexts)
+        val result = createKotlinVariant(componentName, usageContexts)
 
         setOf(result)
     }
 
     override fun createKotlinVariant(
         componentName: String,
-        compilation: KotlinCompilation<*>,
         usageContexts: Set<DefaultKotlinUsageContext>,
     ): KotlinVariant {
-        return super.createKotlinVariant(componentName, compilation, usageContexts).apply {
+        return super.createKotlinVariant(componentName, usageContexts).apply {
             artifactTargetName = wasmDecamelizedDefaultNameOrNull() ?: componentName
         }
     }
@@ -120,6 +119,7 @@
                     compilation = compilations.getByName(MAIN_COMPILATION_NAME),
                     mavenScope = KotlinUsageContext.MavenScope.COMPILE,
                     dependencyConfigurationName = commonFakeApiElementsConfigurationName,
+                    // !!!
                     overrideConfigurationArtifacts = project.setProperty { emptyList() }
                 )
     }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt
index 900b6c0..0c1e278 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt
@@ -11,6 +11,8 @@
 import org.gradle.api.file.FileCollection
 import org.gradle.api.tasks.TaskProvider
 import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateAttribute
+import org.jetbrains.kotlin.gradle.artifacts.uklibStateUnzipped
 import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
 import org.jetbrains.kotlin.gradle.dsl.metadataTarget
 import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
@@ -263,6 +265,7 @@
     }
 
     private val ResolvedArtifactResult.isMpp: Boolean get() = variant.attributes.containsMultiplatformAttributes
+            || variant.attributes.getAttribute(uklibStateAttribute) == uklibStateUnzipped
 }
 
 internal fun Project.locateOrRegisterGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> =
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt
index 059487d..fddb4f3 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTarget.kt
@@ -67,7 +67,7 @@
                         mainCompilation,
                         KotlinUsageContext.MavenScope.COMPILE,
                         hostSpecificMetadataElementsConfigurationName,
-                        includeIntoProjectStructureMetadata = false
+                        includeIntoProjectStructureMetadata = false,
                     )
                 )
             }
@@ -87,7 +87,7 @@
             )
         )
 
-        val result = createKotlinVariant(targetName, mainCompilation, mutableUsageContexts)
+        val result = createKotlinVariant(targetName, mutableUsageContexts)
 
         setOf(result)
     }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt
index 57dea70..113cd18 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/KotlinPlatformTypeUtils.kt
@@ -14,6 +14,6 @@
         KotlinPlatformType.jvm -> "Kotlin/JVM"
         KotlinPlatformType.js -> "Kotlin/JS"
         KotlinPlatformType.androidJvm -> "Kotlin/Android"
-        KotlinPlatformType.native, KotlinPlatformType.unknown -> "Kotlin/Native"
+        KotlinPlatformType.native -> "Kotlin/Native"
         KotlinPlatformType.wasm -> "Kotlin/Wasm"
     }
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform.kt
similarity index 93%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform.kt
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform.kt
index fbfe006..0f511d7 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/regressionTests/KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform.kt
@@ -14,7 +14,7 @@
 import kotlin.test.Test
 import kotlin.test.assertNull
 
-class KT71398KotlinNativeBundleConfigurationOnUnsupportedPlatform {
+class KT71398KotlinNativeBundleConfigurationOnFailOnPublicationAndIgnoreForConsumptionPlatform {
 
     @Test
     fun `KT-71398 - project with multiplatform plugin should not add kotlinNativeBundleConfiguration`() {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt
index b2500bd..b03ec8b 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/IdeKotilnCompilerArgumentsResolverTest.kt
@@ -62,7 +62,7 @@
                 else parseCommandLineArguments<K2MetadataCompilerArguments>(argumentsList)
                 KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> parseCommandLineArguments<K2JVMCompilerArguments>(argumentsList)
                 KotlinPlatformType.js, KotlinPlatformType.wasm -> parseCommandLineArguments<K2JSCompilerArguments>(argumentsList)
-                KotlinPlatformType.native, KotlinPlatformType.unknown -> parseCommandLineArguments<K2NativeCompilerArguments>(argumentsList)
+                KotlinPlatformType.native -> parseCommandLineArguments<K2NativeCompilerArguments>(argumentsList)
             }
 
             val parsedArgumentsList = parsedArguments.toArgumentStrings(shortArgumentKeys = true, compactArgumentValues = false)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibResolutionTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibResolutionTests.kt
new file mode 100644
index 0000000..b49741d
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibResolutionTests.kt
@@ -0,0 +1,761 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.gradle.unitTests
+
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.attributes.Attribute
+import org.gradle.kotlin.dsl.maven
+import org.jetbrains.kotlin.gradle.artifacts.UklibResolutionStrategy
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
+import org.jetbrains.kotlin.gradle.util.*
+import org.jetbrains.kotlin.gradle.utils.projectPathOrNull
+import org.jetbrains.kotlin.utils.keysToMap
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.reflect.full.*
+
+class UklibResolutionTests {
+
+    @Test
+    fun `uklib resolution - from direct pom dependency with uklib packaging`() {
+        val consumer = consumer(UklibResolutionStrategy.AllowResolvingUklibs) {
+            jvm()
+            iosArm64()
+            iosX64()
+            js()
+            wasmJs()
+            wasmWasi()
+
+            sourceSets.commonMain.dependencies {
+                implementation("foo.bar:pure-maven-uklib:1.0")
+            }
+        }
+
+        val metadataCompilationVariants = consumer.multiplatformExtension.sourceSets.getByName("commonMain")
+            .internal.resolvableMetadataConfiguration
+            .resolveProjectDependencyComponentsWithArtifacts()
+        val iosArm64CompilationVariants = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+            .configurations.compileDependencyConfiguration.resolveProjectDependencyComponentsWithArtifacts()
+        val jvmRuntimeVariants = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+        val jsRuntimeVariants = consumer.multiplatformExtension.js().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+        val wasmJsVariants = consumer.multiplatformExtension.wasmJs().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+        val wasmWasiVariants = consumer.multiplatformExtension.wasmWasi().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="commonMainResolvableDependenciesMetadata",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationMetadataAttributes)
+                ),
+            ),
+            metadataCompilationVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64CompileKlibraries",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationIosArm64Attributes)
+                ),
+            ),
+            iosArm64CompilationVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJvmAttributes)
+                ),
+            ),
+            jvmRuntimeVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="jsRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJsAttributes)
+                ),
+            ),
+            jsRuntimeVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="wasmJsRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationWasmJsAttributes)
+                ),
+            ),
+            wasmJsVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="wasmWasiRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationWasmWasiAttributes)
+                ),
+            ),
+            wasmWasiVariants
+        )
+    }
+
+    @Test
+    fun `uklib resolution - from direct pom dependency with uklib packaging points to untrasformed uklib - when uklibs are not allowed to resolve`() {
+        val consumer = consumer(UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant) {
+            jvm()
+            iosArm64()
+            iosX64()
+
+            sourceSets.commonMain.dependencies {
+                implementation("foo.bar:pure-maven-uklib:1.0")
+            }
+        }
+
+        /**
+         * FIXME: This is unfortunate and in opposition to how KMP dependencies resolve right now because:
+         *
+         * KMP dependencies will fail to resolve if they have a missing platform/native type attribute
+         *
+         * but this is similar to how pure java dependencies (e.g. com.google.guava:guava:+) will resolve just fine
+         */
+
+        val metadataCompilationVariants = consumer.multiplatformExtension.sourceSets.getByName("commonMain")
+            .internal.resolvableMetadataConfiguration
+            .resolveProjectDependencyComponentsWithArtifacts()
+        val iosArm64CompilationVariants = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+            .configurations.compileDependencyConfiguration.resolveProjectDependencyComponentsWithArtifacts()
+        val jvmRuntimeVariants = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="commonMainResolvableDependenciesMetadata",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + uklibArtifact)
+                ),
+            ),
+            metadataCompilationVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64CompileKlibraries",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + uklibArtifact)
+                ),
+            ),
+            iosArm64CompilationVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-uklib:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibArtifact)
+                ),
+            ),
+            jvmRuntimeVariants
+        )
+    }
+
+    // consumer <- pure jvm <- uklib <- PSM-only
+    @Test
+    fun `uklib resolution - from transitive uklib dependency`() {
+        val consumer = consumer(UklibResolutionStrategy.AllowResolvingUklibs) {
+            jvm()
+            iosArm64()
+            iosX64()
+
+            sourceSets.commonMain.dependencies {
+                implementation("foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0")
+            }
+        }
+
+        val metadataCompilationVariants = consumer.multiplatformExtension.sourceSets.getByName("commonMain")
+            .internal.resolvableMetadataConfiguration
+            .resolveProjectDependencyComponentsWithArtifacts()
+
+        val iosArm64CompilationVariants = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+            .configurations.compileDependencyConfiguration.resolveProjectDependencyComponentsWithArtifacts()
+
+        val jvmRuntimeVariants = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!.resolveProjectDependencyComponentsWithArtifacts()
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="commonMainResolvableDependenciesMetadata",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + jarArtifact)
+                ),
+                "foo.bar:pure-maven-uklib-with-transitive-non-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationMetadataAttributes)
+                ),
+                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="metadataApiElements",
+                    artifacts=mutableListOf(metadataVariantAttributes + releaseStatus)
+                ),
+            ).pp(),
+            metadataCompilationVariants.pp()
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + jarArtifact)
+                ),
+                "foo.bar:pure-maven-uklib-with-transitive-non-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="runtime",
+                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJvmAttributes)
+                ),
+                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeElements-published",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:uklib-maven-gradle-packaging-jvm:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeElements-published",
+                    artifacts=mutableListOf(platformJvmVariantAttributes + releaseStatus)
+                ),
+            ),
+            jvmRuntimeVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64CompileKlibraries",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:pure-maven-jvm-with-trasitive-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + jarArtifact)
+                ),
+                "foo.bar:pure-maven-uklib-with-transitive-non-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="compile",
+                    artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationIosArm64Attributes)
+                ),
+                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64ApiElements-published",
+                    artifacts=mutableListOf()
+                ),
+                "foo.bar:uklib-maven-gradle-packaging-iosarm64:1.0" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64ApiElements-published",
+                    // klib + cinterop klib
+                    artifacts=mutableListOf(
+                        platformIosArm64Attributes + releaseStatus,
+                        platformIosArm64Attributes + releaseStatus,
+                    )
+                ),
+            ),
+            iosArm64CompilationVariants
+        )
+    }
+
+//    @Test
+    fun `resolve uklib - in Swift Export and ObjC binaries export configurations`() {
+        error("TODO")
+    }
+
+//    @Test
+    fun `resolve uklib - in resolvable JS configurations with klibs`() {
+        error("TODO")
+    }
+
+    // ---
+    private fun consumer(
+        strategy: UklibResolutionStrategy,
+        configure: KotlinMultiplatformExtension.() -> Unit,
+    ): Project {
+        return buildProjectWithMPP(
+            preApplyCode = {
+                publishUklibVariant()
+                fakeUklibTransforms()
+                setUklibResolutionStrategy(strategy)
+                // Test stdlib in a separate test
+                enableDefaultStdlibDependency(false)
+                enableDefaultJsDomApiDependency(false)
+            }
+        ) {
+            kotlin {
+                configure()
+            }
+
+            repositories.maven(javaClass.getResource("/dependenciesResolution/UklibTests/repo")!!)
+        }.evaluate()
+    }
+
+    // @Test
+    fun `prefer klib variant`() {
+        val consumer = mixedCompilationsGraphConsumer(
+            uklibResolutionStrategy = UklibResolutionStrategy.AllowResolvingUklibs,
+        )
+
+        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+            .configurations.compileDependencyConfiguration
+        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!
+        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+        assertEquals(
+            mapOf(
+                ":E_consumes_D" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeElements",
+                    artifacts=mutableListOf(platformJvmVariantAttributes)
+                ),
+                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
+                ),
+                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeElements",
+                    artifacts=mutableListOf(platformJvmVariantAttributes)
+                ),
+                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeElements",
+                    artifacts=mutableListOf(platformJvmVariantAttributes),
+                )
+            ),
+            jvmResolvedVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":E_consumes_D" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64CompileKlibraries",
+                    artifacts=mutableListOf()
+                ),
+                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64ApiElements",
+                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
+                ),
+                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
+                ),
+                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64ApiElements",
+                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
+                ),
+                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64ApiElements",
+                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked),
+                )
+            ),
+            iosArm64ResolvedVariants
+        )
+    }
+
+    // @Test
+    fun `prefer uklib variant`() {
+        val consumer = mixedCompilationsGraphConsumer(
+            uklibResolutionStrategy = UklibResolutionStrategy.AllowResolvingUklibs,
+        )
+
+        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
+            .configurations.compileDependencyConfiguration
+        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
+            .configurations.runtimeDependencyConfiguration!!
+        // FIXME: java-api variant doesn't resolve A
+        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
+
+        assertEquals(
+            mapOf(
+                ":E_consumes_D" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeClasspath",
+                    artifacts=mutableListOf()
+                ),
+                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
+                ),
+                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
+                ),
+                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+                    configuration="jvmRuntimeElements",
+                    artifacts=mutableListOf(platformJvmVariantAttributes)
+                ),
+                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes),
+                )
+            ),
+            jvmResolvedVariants
+        )
+
+        assertEquals(
+            mapOf(
+                ":E_consumes_D" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64CompileKlibraries",
+                    artifacts=mutableListOf()
+                ),
+                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
+                ),
+                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
+                ),
+                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
+                    configuration="iosArm64ApiElements",
+                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
+                ),
+                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
+                    configuration="metadataUklibElements",
+                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes),
+                )
+            ),
+            iosArm64ResolvedVariants
+        )
+    }
+
+    private fun mixedCompilationsGraphConsumer(
+        uklibResolutionStrategy: UklibResolutionStrategy,
+    ): Project {
+        val root = buildProject()
+        return root.child(
+            "E_consumes_D",
+            uklibResolutionStrategy = uklibResolutionStrategy,
+            consume= root.child(
+                "D_produces_uklib_consumes_C",
+                consume = root.child(
+                    "C_produces_only_uklib_consumes_B",
+                    disablePlatformComponentReferences = true,
+                    consume = root.child(
+                        "B_produces_only_platform_variant_consumes_A",
+                        publishUklibVariant = false,
+                        consume = root.child(
+                            "A_produces_uklib",
+                            consume = null
+                        )
+                    )
+                )
+            )
+        )
+    }
+
+    private val uklibTransformationIosArm64Attributes = mapOf(
+        "artifactType" to "uklib",
+        "uklibDestination" to "ios_arm64",
+        "uklibState" to "unzipped",
+    )
+
+    private val uklibTransformationJvmAttributes = mapOf(
+        "artifactType" to "uklib",
+        "uklibDestination" to "jvm",
+        "uklibState" to "unzipped",
+    )
+
+    private val uklibTransformationMetadataAttributes = mapOf(
+        "artifactType" to "uklib",
+        "uklibDestination" to "common",
+        "uklibState" to "unzipped",
+    )
+
+    private val uklibTransformationJsAttributes = mapOf(
+        "artifactType" to "uklib",
+        "uklibDestination" to "js_ir",
+        "uklibState" to "unzipped",
+    )
+
+    private val uklibTransformationWasmJsAttributes = mapOf(
+        "artifactType" to "uklib",
+        "uklibDestination" to "wasm_js",
+        "uklibState" to "unzipped",
+    )
+
+    private val uklibTransformationWasmWasiAttributes = mapOf(
+        "artifactType" to "uklib",
+        "uklibDestination" to "wasm_wasi",
+        "uklibState" to "unzipped",
+    )
+
+    private val uklibVariantAttributes = mapOf(
+        "org.gradle.category" to "library",
+        "org.gradle.jvm.environment" to "???",
+        "org.gradle.usage" to "kotlin-uklib",
+        "org.jetbrains.kotlin.klib.packaging" to "packed",
+        "org.jetbrains.kotlin.native.target" to "???",
+        "org.jetbrains.kotlin.platform.type" to "unknown",
+    )
+
+    private val jvmPomRuntimeAttributes = mapOf(
+        "org.gradle.category" to "library",
+        "org.gradle.libraryelements" to "jar",
+        "org.gradle.status" to "release",
+        "org.gradle.usage" to "java-runtime",
+    )
+
+    private val jvmPomApiAttributes = mapOf(
+        "org.gradle.category" to "library",
+        "org.gradle.libraryelements" to "jar",
+        "org.gradle.status" to "release",
+        "org.gradle.usage" to "java-api",
+    )
+
+    private val platformJvmVariantAttributes = mapOf(
+        "artifactType" to "jar",
+        "org.gradle.category" to "library",
+        "org.gradle.jvm.environment" to "standard-jvm",
+        "org.gradle.libraryelements" to "jar",
+        "org.gradle.usage" to "java-runtime",
+        "org.jetbrains.kotlin.platform.type" to "jvm",
+    )
+
+    private val metadataVariantAttributes = mapOf(
+        "artifactType" to "jar",
+        "org.gradle.category" to "library",
+        "org.gradle.jvm.environment" to "non-jvm",
+        "org.gradle.libraryelements" to "jar",
+        "org.gradle.usage" to "kotlin-metadata",
+        "org.jetbrains.kotlin.platform.type" to "common",
+    )
+
+    private val releaseStatus = mapOf(
+        "org.gradle.status" to "release",
+    )
+
+    // We only emit packing in secondary variants which are not published?
+    private val nonPacked = mapOf(
+        "org.jetbrains.kotlin.klib.packaging" to "non-packed",
+    )
+
+    private val jarArtifact = mapOf(
+        "artifactType" to "jar",
+    )
+
+    private val uklibArtifact = mapOf(
+        "artifactType" to "uklib",
+    )
+
+    private val platformIosArm64Attributes = mapOf(
+        "artifactType" to "org.jetbrains.kotlin.klib",
+        "org.gradle.category" to "library",
+        "org.gradle.jvm.environment" to "non-jvm",
+        "org.gradle.usage" to "kotlin-api",
+        "org.jetbrains.kotlin.cinteropCommonizerArtifactType" to "klib",
+        "org.jetbrains.kotlin.native.target" to "ios_arm64",
+        "org.jetbrains.kotlin.platform.type" to "native",
+    )
+
+    data class ResolvedComponentWithArtifacts(
+        val configuration: String,
+        val artifacts: MutableList<Map<String, String>> = mutableListOf(),
+    )
+
+    private fun Configuration.resolveProjectDependencyComponentsWithArtifacts(): Map<String, ResolvedComponentWithArtifacts> {
+        val artifacts = resolveProjectDependencyVariantsFromArtifacts()
+        val components = resolveProjectDependencyComponents()
+        val componentToArtifacts = LinkedHashMap<String, ResolvedComponentWithArtifacts>()
+        components.forEach { component ->
+            if (componentToArtifacts[component.path] == null) {
+                componentToArtifacts[component.path] = ResolvedComponentWithArtifacts(component.configuration)
+            } else {
+                error("${component} resolved multiple times?")
+            }
+        }
+        artifacts.forEach { artifact ->
+            componentToArtifacts[artifact.path]?.let {
+                it.artifacts.add(artifact.attributes)
+            } ?: error("Missing resolved component for artifact: ${artifact}")
+        }
+        return componentToArtifacts
+    }
+
+    data class ResolvedVariant(
+        val path: String,
+        val attributes: Map<String, String>,
+    )
+
+    private fun Configuration.resolveProjectDependencyVariantsFromArtifacts(): List<ResolvedVariant> {
+        return incoming.artifacts.artifacts
+            .map { artifact ->
+                val uklibAttributes: List<Attribute<*>> = artifact.variant.attributes.keySet()
+                    .sortedBy { it.name }
+                ResolvedVariant(
+                    artifact.variant.owner.projectPathOrNull ?: artifact.variant.owner.displayName,
+                    uklibAttributes.keysToMap {
+                        artifact.variant.attributes.getAttribute(it as Attribute<*>).toString()
+                    }.mapKeys { it.key.name }
+                )
+            }
+    }
+
+    data class ResolvedComponent(
+        val path: String,
+        val configuration: String,
+    )
+
+    private fun Configuration.resolveProjectDependencyComponents(): List<ResolvedComponent> {
+        return incoming.resolutionResult.allComponents
+            .map { component ->
+                ResolvedComponent(
+                    component.id.projectPathOrNull ?: component.id.displayName,
+                    // Expect a single variant to always be selected?
+                    component.variants.single().displayName
+                )
+            }
+    }
+
+    private fun Project.child(
+        name: String,
+        consume: Project?,
+        publishUklibVariant: Boolean = true,
+        disablePlatformComponentReferences: Boolean = false,
+        uklibResolutionStrategy: UklibResolutionStrategy = UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant,
+    ): Project {
+        val parent = this
+        return buildProjectWithMPP(
+            preApplyCode = {
+                if (publishUklibVariant) {
+                    publishUklibVariant()
+                }
+                fakeUklibTransforms()
+                setUklibResolutionStrategy(uklibResolutionStrategy)
+                disablePlatformSpecificComponentReferences(disablePlatformComponentReferences)
+                // Test stdlib in a separate test
+                enableDefaultStdlibDependency(false)
+                enableDefaultJsDomApiDependency(false)
+            },
+            projectBuilder = {
+                withParent(parent)
+                withName(name)
+            }
+        ) {
+            kotlin {
+                iosArm64()
+                iosX64()
+                jvm()
+
+                if (consume != null) {
+                    sourceSets.commonMain.dependencies {
+                        implementation(project(consume.project.path))
+                    }
+                }
+            }
+        }.evaluate()
+    }
+}
+
+class PP(
+    val value: Any,
+    val indentation: Int,
+) {
+    override fun toString(): String {
+        val twoSpaces = " ".repeat(2)
+        val indentationSpace = " ".repeat(indentation)
+        val nextIndentationDepth = indentation + 2
+        val elements: Array<String> = when (value) {
+            is Map<*, *> -> arrayOf(
+                "{",
+                *value.map { it }.sortedBy { it.key.toString() }.map { "${twoSpaces}${it.key}=${it.value?.pp(nextIndentationDepth)}," }.toTypedArray(),
+                "}",
+            )
+            is List<*> -> arrayOf(
+                "[",
+                *value.map { "${twoSpaces}${it?.pp(nextIndentationDepth)}," }.toTypedArray(),
+                "]",
+            )
+            else -> {
+                val packageName = value::class.java.packageName
+                if (packageName.startsWith("kotlin.") || packageName.startsWith("java.")) {
+                    arrayOf(value.toString())
+                } else {
+                    val kClass = value::class
+                    arrayOf(
+                        "${kClass.simpleName}(",
+                        *kClass.memberProperties.map { prop ->
+                            "${twoSpaces}${prop.name}=${prop.getter.call(value)?.pp(nextIndentationDepth)},"
+                        }.toTypedArray(),
+                        ")",
+                    )
+                }
+            }
+        }
+
+        if (elements.size == 1) return elements[0]
+
+        return (listOf(elements[0]) + elements.toList().subList(1, elements.size).map { "${indentationSpace}${it}" }).joinToString("\n")
+    }
+
+    override fun hashCode(): Int {
+        return value.hashCode()
+    }
+
+    override fun equals(other: Any?): Boolean {
+        var otherUnwrapped = other
+        if (other is PP) otherUnwrapped = other.value
+        return value.equals(otherUnwrapped)
+    }
+}
+
+private fun Any.pp(indentation: Int = 0): PP = PP(this, indentation)
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibTests.kt
deleted file mode 100644
index 8aa653a..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/UklibTests.kt
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
- * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
- */
-
-package org.jetbrains.kotlin.gradle.unitTests
-
-import org.gradle.api.Project
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.attributes.Attribute
-import org.gradle.api.attributes.Usage
-import org.gradle.kotlin.dsl.maven
-import org.gradle.kotlin.dsl.named
-import org.jetbrains.kotlin.gradle.artifacts.UklibResolutionStrategy
-import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
-import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
-import org.jetbrains.kotlin.gradle.util.*
-import org.jetbrains.kotlin.gradle.utils.projectPathOrNull
-import org.jetbrains.kotlin.utils.keysToMap
-import kotlin.test.Test
-import kotlin.test.assertEquals
-
-class UklibTests {
-
-    @Test
-    fun `resolve uklib - from pom with uklib packaging`() {
-        val consumer = consumer(UklibResolutionStrategy.PreferPlatformSpecificVariant) {
-            sourceSets.commonMain.dependencies {
-                // FIXME: Everything works kind of nicely, but either the consumer has to publish a separate component for pure Maven jar consumption, or Maven has to know about uklibs
-                implementation("foo.bar:regular-maven-jar-packaging-with-uklib-uklib-dependency:1.0")
-            }
-        }
-
-        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
-            .configurations.compileDependencyConfiguration
-        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
-            .configurations.runtimeDependencyConfiguration!!
-        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        assertEquals(
-            mapOf(
-                ":" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeClasspath",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:regular-maven-jar-packaging-with-uklib-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="runtime",
-                    artifacts=mutableListOf(jvmPomRuntimeAttributes + jarArtifact)
-                ),
-                "foo.bar:uklib-maven-uklib-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="runtime",
-                    artifacts=mutableListOf(jvmPomRuntimeAttributes + uklibTransformationJvmAttributes)
-                ),
-                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements-published",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:uklib-maven-gradle-packaging-jvm:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements-published",
-                    artifacts=mutableListOf(platformJvmVariantAttributes + releaseStatus)
-                ),
-            ),
-            jvmResolvedVariants
-        )
-
-        assertEquals(
-            mapOf(
-                ":" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64CompileKlibraries",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:regular-maven-jar-packaging-with-uklib-uklib-dependency:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="compile",
-                    artifacts=mutableListOf(jvmPomApiAttributes + jarArtifact)
-                ),
-                "foo.bar:uklib-maven-uklib-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="compile",
-                    artifacts=mutableListOf(jvmPomApiAttributes + uklibTransformationIosArm64Attributes)
-                ),
-                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements-published",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:uklib-maven-gradle-packaging-iosarm64:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements-published",
-                    // klib + cinterop klib
-                    artifacts=mutableListOf(
-                        platformIosArm64Attributes + releaseStatus,
-                        platformIosArm64Attributes + releaseStatus,
-                    )
-                ),
-            ),
-            iosArm64ResolvedVariants
-        )
-    }
-
-    @Test
-    fun `resolve uklib - from pom with jar packaging - with explicit extension`() {
-        val consumer = consumer(UklibResolutionStrategy.PreferPlatformSpecificVariant) {
-            sourceSets.commonMain.dependencies {
-                /**
-                 * FIXME: If this dependency is brought transitively, it's unclear how the regular-maven-jar-packaging POM should specify the dependency on a uklib, such that both KGP and Maven consumers can depend on it easily
-                 *
-                 * This could work with variant reselection, but then we have to use artifactViews
-                 */
-                // implementation("foo.bar:regular-maven-jar-packaging:1.0")
-                implementation("foo.bar:uklib-maven-jar-packaging:1.0@uklib") {
-                    // FIXME: Why does explicit extension specification unset transitiveness?
-                    assert(!isTransitive)
-                    isTransitive = true
-                }
-            }
-        }
-
-        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
-            .configurations.compileDependencyConfiguration
-        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
-            .configurations.runtimeDependencyConfiguration!!
-        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        assertEquals(
-            mapOf(
-                ":" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeClasspath",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:uklib-maven-jar-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="runtime",
-                    artifacts=mutableListOf(uklibTransformationJvmAttributes + releaseStatus)
-                ),
-                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements-published",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:uklib-maven-gradle-packaging-jvm:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements-published",
-                    artifacts=mutableListOf(platformJvmVariantAttributes + releaseStatus)
-                ),
-            ),
-            jvmResolvedVariants
-        )
-
-        assertEquals(
-            mapOf(
-                ":" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64CompileKlibraries",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:uklib-maven-jar-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="compile",
-                    artifacts=mutableListOf(uklibTransformationIosArm64Attributes + releaseStatus)
-                ),
-                "foo.bar:uklib-maven-gradle-packaging:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements-published",
-                    artifacts=mutableListOf()
-                ),
-                "foo.bar:uklib-maven-gradle-packaging-iosarm64:1.0" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements-published",
-                    artifacts=mutableListOf(
-                        platformIosArm64Attributes + releaseStatus,
-                        platformIosArm64Attributes + releaseStatus,
-                    )
-                ),
-            ),
-            iosArm64ResolvedVariants
-        )
-    }
-
-
-    // FIXME: Maybe this is usable?
-//        consumer.configurations.configureEach {
-//            if (it.isCanBeResolved) {
-//                it.resolutionStrategy.eachDependency {
-//                    it.artifactSelection {
-//
-//                    }
-//                }
-//                it.resolutionStrategy.componentSelection.all {
-//                    it.
-//                }
-//            }
-//        }
-    @Test
-    fun `resolve uklib - from pom with jar packaging - with explicit extension - and component rule`() {
-        val consumer = consumer(UklibResolutionStrategy.PreferUklibVariant) {
-            sourceSets.commonMain.dependencies {
-                // implementation("foo.bar:uklib-maven-jar-packaging:1.0")
-                // consume "foo.bar:uklib-maven-jar-packaging:1.0" transitively
-                // FIXME: With a naive component metadata rule regular jars fail to resolve
-                implementation("foo.bar:regular-maven-jar-packaging-with-uklib-jar-dependency:1.0")
-            }
-
-            project.dependencies.components.all { component ->
-                component.maybeAddVariant(
-                    "uklib",
-                    // FIXME: runtime?
-                    "compile",
-                ) {
-                    // How do you know that the file will be there?
-                    it.withFiles {
-                        // When there are multiple artifacts, Gradle doesn't set artifactType
-                        it.removeAllFiles()
-                        it.addFile("${component.id.name}-${component.id.version}.uklib")
-                    }
-                    it.attributes.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(KotlinUsages.KOTLIN_UKLIB))
-                }
-            }
-        }
-
-        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
-            .configurations.compileDependencyConfiguration
-        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
-            .configurations.runtimeDependencyConfiguration!!
-        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        // ???
-    }
-
-    // @Test
-    // FIXME: This is probably pretty useless because with the classifier artifactType has to be jar and its unclear how to force a transform
-    fun `resolve uklib - from pom with jar packaging - with explicit classifier`() {
-        val consumer = consumer(UklibResolutionStrategy.PreferPlatformSpecificVariant) {
-            sourceSets.commonMain.dependencies {
-                implementation("foo.bar:uklib-maven-jar-packaging-classifier:1.0:uklib")
-            }
-        }
-
-        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
-            .configurations.compileDependencyConfiguration
-        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
-            .configurations.runtimeDependencyConfiguration!!
-        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        // ???
-    }
-
-    private fun consumer(
-        strategy: UklibResolutionStrategy,
-        configure: KotlinMultiplatformExtension.() -> Unit,
-    ): Project {
-        return buildProjectWithMPP(
-            preApplyCode = {
-                publishUklibVariant()
-                fakeUklibTransforms()
-                setUklibResolutionStrategy(strategy)
-                // Test stdlib in a separate test
-                enableDefaultStdlibDependency(false)
-            }
-        ) {
-            kotlin {
-                iosArm64()
-                iosX64()
-                jvm()
-
-                configure()
-            }
-
-            repositories.maven(javaClass.getResource("/dependenciesResolution/UklibTests/repo")!!)
-        }.evaluate()
-    }
-
-    @Test
-    fun `prefer klib variant`() {
-        val consumer = mixedCompilationsGraphConsumer(
-            uklibResolutionStrategy = UklibResolutionStrategy.PreferPlatformSpecificVariant,
-        )
-
-        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
-            .configurations.compileDependencyConfiguration
-        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
-            .configurations.runtimeDependencyConfiguration!!
-        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        assertEquals(
-            mapOf(
-                ":E_consumes_D" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeClasspath",
-                    artifacts=mutableListOf()
-                ),
-                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements",
-                    artifacts=mutableListOf(platformJvmVariantAttributes)
-                ),
-                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
-                ),
-                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements",
-                    artifacts=mutableListOf(platformJvmVariantAttributes)
-                ),
-                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements",
-                    artifacts=mutableListOf(platformJvmVariantAttributes),
-                )
-            ),
-            jvmResolvedVariants
-        )
-
-        assertEquals(
-            mapOf(
-                ":E_consumes_D" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64CompileKlibraries",
-                    artifacts=mutableListOf()
-                ),
-                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements",
-                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
-                ),
-                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
-                ),
-                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements",
-                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
-                ),
-                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements",
-                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked),
-                )
-            ),
-            iosArm64ResolvedVariants
-        )
-    }
-
-    @Test
-    fun `prefer uklib variant`() {
-        val consumer = mixedCompilationsGraphConsumer(
-            uklibResolutionStrategy = UklibResolutionStrategy.PreferUklibVariant,
-        )
-
-        val iosArm64CompilationDependencies = consumer.multiplatformExtension.iosArm64().compilations.getByName("main")
-            .configurations.compileDependencyConfiguration
-        val iosArm64ResolvedVariants = iosArm64CompilationDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        val jvmRuntimeDependencies = consumer.multiplatformExtension.jvm().compilations.getByName("main")
-            .configurations.runtimeDependencyConfiguration!!
-        // FIXME: java-api variant doesn't resolve A
-        val jvmResolvedVariants = jvmRuntimeDependencies.resolveProjectDependencyComponentsWithArtifacts()
-
-        assertEquals(
-            mapOf(
-                ":E_consumes_D" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeClasspath",
-                    artifacts=mutableListOf()
-                ),
-                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
-                ),
-                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes)
-                ),
-                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
-                    configuration="jvmRuntimeElements",
-                    artifacts=mutableListOf(platformJvmVariantAttributes)
-                ),
-                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationJvmAttributes),
-                )
-            ),
-            jvmResolvedVariants
-        )
-
-        assertEquals(
-            mapOf(
-                ":E_consumes_D" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64CompileKlibraries",
-                    artifacts=mutableListOf()
-                ),
-                ":D_produces_uklib_consumes_C" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
-                ),
-                ":C_produces_only_uklib_consumes_B" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes)
-                ),
-                ":B_produces_only_platform_variant_consumes_A" to ResolvedComponentWithArtifacts(
-                    configuration="iosArm64ApiElements",
-                    artifacts=mutableListOf(platformIosArm64Attributes + nonPacked)
-                ),
-                ":A_produces_uklib" to ResolvedComponentWithArtifacts(
-                    configuration="metadataUklibElements",
-                    artifacts=mutableListOf(uklibVariantAttributes + uklibTransformationIosArm64Attributes),
-                )
-            ),
-            iosArm64ResolvedVariants
-        )
-    }
-
-    private fun mixedCompilationsGraphConsumer(
-        uklibResolutionStrategy: UklibResolutionStrategy,
-    ): Project {
-        val root = buildProject()
-        return root.child(
-            "E_consumes_D",
-            uklibResolutionStrategy = uklibResolutionStrategy,
-            consume= root.child(
-                "D_produces_uklib_consumes_C",
-                consume = root.child(
-                    "C_produces_only_uklib_consumes_B",
-                    disablePlatformComponentReferences = true,
-                    consume = root.child(
-                        "B_produces_only_platform_variant_consumes_A",
-                        publishUklibVariant = false,
-                        consume = root.child(
-                            "A_produces_uklib",
-                            consume = null
-                        )
-                    )
-                )
-            )
-        )
-    }
-
-    private val uklibTransformationIosArm64Attributes = mapOf(
-        "artifactType" to "uklib",
-        "uklibNativeSlice" to "iosArm64",
-        "uklibPlatform" to "native",
-        "uklibState" to "unzipped",
-    )
-
-    private val uklibTransformationJvmAttributes = mapOf(
-        "artifactType" to "uklib",
-        "uklibNativeSlice" to "unknown",
-        "uklibPlatform" to "jvm",
-        "uklibState" to "unzipped",
-    )
-
-    private val uklibVariantAttributes = mapOf(
-        "org.gradle.category" to "library",
-        "org.gradle.jvm.environment" to "???",
-        "org.gradle.usage" to "kotlin-uklib",
-        "org.jetbrains.kotlin.klib.packaging" to "packed",
-        "org.jetbrains.kotlin.native.target" to "???",
-        "org.jetbrains.kotlin.platform.type" to "unknown",
-    )
-
-    private val jvmPomRuntimeAttributes = mapOf(
-        "org.gradle.category" to "library",
-        "org.gradle.libraryelements" to "jar",
-        "org.gradle.status" to "release",
-        "org.gradle.usage" to "java-runtime",
-    )
-
-    private val jvmPomApiAttributes = mapOf(
-        "org.gradle.category" to "library",
-        "org.gradle.libraryelements" to "jar",
-        "org.gradle.status" to "release",
-        "org.gradle.usage" to "java-api",
-    )
-
-    private val platformJvmVariantAttributes = mapOf(
-        "artifactType" to "jar",
-        "org.gradle.category" to "library",
-        "org.gradle.jvm.environment" to "standard-jvm",
-        "org.gradle.libraryelements" to "jar",
-        "org.gradle.usage" to "java-runtime",
-        "org.jetbrains.kotlin.platform.type" to "jvm",
-    )
-
-    private val releaseStatus = mapOf(
-        "org.gradle.status" to "release",
-    )
-
-    // We only emit packing in secondary variants which are not published?
-    private val nonPacked = mapOf(
-        "org.jetbrains.kotlin.klib.packaging" to "non-packed",
-    )
-
-    private val jarArtifact = mapOf(
-        "artifactType" to "jar",
-    )
-
-    private val platformIosArm64Attributes = mapOf(
-        "artifactType" to "org.jetbrains.kotlin.klib",
-        "org.gradle.category" to "library",
-        "org.gradle.jvm.environment" to "non-jvm",
-        "org.gradle.usage" to "kotlin-api",
-        "org.jetbrains.kotlin.cinteropCommonizerArtifactType" to "klib",
-        "org.jetbrains.kotlin.native.target" to "ios_arm64",
-        "org.jetbrains.kotlin.platform.type" to "native",
-    )
-
-    data class ResolvedComponentWithArtifacts(
-        val configuration: String,
-        val artifacts: MutableList<Map<String, String>> = mutableListOf(),
-    )
-
-    private fun Configuration.resolveProjectDependencyComponentsWithArtifacts(): Map<String, ResolvedComponentWithArtifacts> {
-        val artifacts = resolveProjectDependencyVariantsFromArtifacts()
-        val components = resolveProjectDependencyComponents()
-        val componentToArtifacts = LinkedHashMap<String, ResolvedComponentWithArtifacts>()
-        components.forEach { component ->
-            if (componentToArtifacts[component.path] == null) {
-                componentToArtifacts[component.path] = ResolvedComponentWithArtifacts(component.configuration)
-            } else {
-                error("${component} resolved multiple times?")
-            }
-        }
-        artifacts.forEach { artifact ->
-            componentToArtifacts[artifact.path]?.let {
-                it.artifacts.add(artifact.attributes)
-            } ?: error("Missing resolved component for artifact: ${artifact}")
-        }
-        return componentToArtifacts
-    }
-
-    data class ResolvedVariant(
-        val path: String,
-        val attributes: Map<String, String>,
-    )
-
-    private fun Configuration.resolveProjectDependencyVariantsFromArtifacts(): List<ResolvedVariant> {
-        return incoming.artifacts.artifacts
-            .map { artifact ->
-                val uklibAttributes: List<Attribute<*>> = artifact.variant.attributes.keySet()
-                    .sortedBy { it.name }
-                ResolvedVariant(
-                    artifact.variant.owner.projectPathOrNull ?: artifact.variant.owner.displayName,
-                    uklibAttributes.keysToMap {
-                        artifact.variant.attributes.getAttribute(it as Attribute<*>).toString()
-                    }.mapKeys { it.key.name }
-                )
-            }
-    }
-
-    data class ResolvedComponent(
-        val path: String,
-        val configuration: String,
-    )
-
-    private fun Configuration.resolveProjectDependencyComponents(): List<ResolvedComponent> {
-        return incoming.resolutionResult.allComponents
-            .map { component ->
-                ResolvedComponent(
-                    component.id.projectPathOrNull ?: component.id.displayName,
-                    // Expect a single variant to always be selected?
-                    component.variants.single().displayName
-                )
-            }
-    }
-
-    private fun Project.child(
-        name: String,
-        consume: Project?,
-        publishUklibVariant: Boolean = true,
-        disablePlatformComponentReferences: Boolean = false,
-        uklibResolutionStrategy: UklibResolutionStrategy = UklibResolutionStrategy.ResolveOnlyPlatformSpecificVariant,
-    ): Project {
-        val parent = this
-        return buildProjectWithMPP(
-            preApplyCode = {
-                if (publishUklibVariant) {
-                    publishUklibVariant()
-                }
-                fakeUklibTransforms()
-                setUklibResolutionStrategy(uklibResolutionStrategy)
-                disablePlatformSpecificComponentReferences(disablePlatformComponentReferences)
-                // Test stdlib in a separate test
-                enableDefaultStdlibDependency(false)
-            },
-            projectBuilder = {
-                withParent(parent)
-                withName(name)
-            }
-        ) {
-            kotlin {
-                iosArm64()
-                iosX64()
-                jvm()
-
-                if (consume != null) {
-                    sourceSets.commonMain.dependencies {
-                        implementation(project(consume.project.path))
-                    }
-                }
-            }
-        }.evaluate()
-    }
-
-}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt
index 762da67..3e3b9ac 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/buildProject.kt
@@ -135,10 +135,10 @@
 }
 
 fun Project.publishUklibVariant(enabled: Boolean = true) {
-    propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB_VARIANT, enabled.toString())
+    propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_PUBLISH_UKLIB, enabled.toString())
 }
 
-fun Project.setUklibResolutionStrategy(strategy: UklibResolutionStrategy) {
+internal fun Project.setUklibResolutionStrategy(strategy: UklibResolutionStrategy) {
     propertiesExtension.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_UKLIB_RESOLUTION_STRATEGY, strategy.propertyName)
 }
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.jar
similarity index 100%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.jar
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.jar
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.pom
similarity index 74%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.pom
index 176d810..6e0ac2b 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-jvm-with-trasitive-uklib-dependency/1.0/pure-maven-jvm-with-trasitive-uklib-dependency-1.0.pom
@@ -3,13 +3,12 @@
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
   <groupId>foo.bar</groupId>
-  <artifactId>uklib-maven-uklib-packaging</artifactId>
+  <artifactId>pure-maven-jvm-with-trasitive-uklib-dependency</artifactId>
   <version>1.0</version>
-  <packaging>uklib</packaging>
   <dependencies>
     <dependency>
       <groupId>foo.bar</groupId>
-      <artifactId>uklib-maven-gradle-packaging</artifactId>
+      <artifactId>pure-maven-uklib-with-transitive-non-uklib-dependency</artifactId>
       <version>1.0</version>
     </dependency>
   </dependencies>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.jar
similarity index 100%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.jar
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.pom
similarity index 86%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.pom
index 176d810..0b56a7f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.pom
@@ -3,7 +3,7 @@
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
   <groupId>foo.bar</groupId>
-  <artifactId>uklib-maven-uklib-packaging</artifactId>
+  <artifactId>pure-maven-uklib-with-transitive-non-uklib-dependency</artifactId>
   <version>1.0</version>
   <packaging>uklib</packaging>
   <dependencies>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.uklib
similarity index 100%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib-with-transitive-non-uklib-dependency/1.0/pure-maven-uklib-with-transitive-non-uklib-dependency-1.0.uklib
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.jar
similarity index 100%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.jar
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.pom
similarity index 60%
copy from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
copy to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.pom
index 176d810..062ba26 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.pom
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.pom
@@ -3,14 +3,7 @@
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
   <groupId>foo.bar</groupId>
-  <artifactId>uklib-maven-uklib-packaging</artifactId>
+  <artifactId>pure-maven-uklib</artifactId>
   <version>1.0</version>
   <packaging>uklib</packaging>
-  <dependencies>
-    <dependency>
-      <groupId>foo.bar</groupId>
-      <artifactId>uklib-maven-gradle-packaging</artifactId>
-      <version>1.0</version>
-    </dependency>
-  </dependencies>
 </project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.uklib
similarity index 100%
rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.uklib
rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/pure-maven-uklib/1.0/pure-maven-uklib-1.0.uklib
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.pom
deleted file mode 100644
index 8402982..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-jar-dependency/1.0/regular-maven-jar-packaging-with-uklib-jar-dependency-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>foo.bar</groupId>
-  <artifactId>regular-maven-jar-packaging-with-uklib-jar-dependency</artifactId>
-  <version>1.0</version>
-<!--  This is the implicit default-->
-<!--  <packaging>jar</packaging>-->
-  <dependencies>
-    <dependency>
-      <groupId>foo.bar</groupId>
-      <artifactId>uklib-maven-jar-packaging</artifactId>
-      <version>1.0</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.pom
deleted file mode 100644
index d4bcedf..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/regular-maven-jar-packaging-with-uklib-uklib-dependency/1.0/regular-maven-jar-packaging-with-uklib-uklib-dependency-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>foo.bar</groupId>
-  <artifactId>regular-maven-jar-packaging-with-uklib-uklib-dependency</artifactId>
-  <version>1.0</version>
-<!--  This is the implicit default-->
-<!--  <packaging>jar</packaging>-->
-  <dependencies>
-    <dependency>
-      <groupId>foo.bar</groupId>
-      <artifactId>uklib-maven-uklib-packaging</artifactId>
-      <version>1.0</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0-uklib.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0-uklib.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0-uklib.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.pom
deleted file mode 100644
index 625e1ab..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging-classifier/1.0/uklib-maven-jar-packaging-classifier-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>foo.bar</groupId>
-  <artifactId>uklib-maven-jar-packaging-classifier</artifactId>
-  <version>1.0</version>
-<!--  This is the implicit default-->
-<!--  <packaging>jar</packaging>-->
-  <dependencies>
-    <dependency>
-      <groupId>foo.bar</groupId>
-      <artifactId>uklib-maven-gradle-packaging</artifactId>
-      <version>1.0</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.pom b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.pom
deleted file mode 100644
index 57a198b..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-jar-packaging/1.0/uklib-maven-jar-packaging-1.0.pom
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>foo.bar</groupId>
-  <artifactId>uklib-maven-jar-packaging</artifactId>
-  <version>1.0</version>
-<!--  This is the implicit default-->
-<!--  <packaging>jar</packaging>-->
-  <dependencies>
-    <dependency>
-      <groupId>foo.bar</groupId>
-      <artifactId>uklib-maven-gradle-packaging</artifactId>
-      <version>1.0</version>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.jar b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.jar
deleted file mode 100644
index 8b13789..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.uklib b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.uklib
deleted file mode 100644
index e69de29..0000000
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/dependenciesResolution/UklibTests/repo/foo/bar/uklib-maven-uklib-packaging/1.0/uklib-maven-uklib-packaging-1.0.uklib
+++ /dev/null