[Gradle] k2 structure fix
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/AssociatedCompilationsMetadataDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/AssociatedCompilationsMetadataDependenciesContributor.kt
new file mode 100644
index 0000000..29d2574
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/AssociatedCompilationsMetadataDependenciesContributor.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.targets.metadata.findMetadataCompilation
+
+internal class AssociatedCompilationMetadataDependencies(
+    val associatedSourceSet: KotlinSourceSet,
+    override val files: FileCollection
+) : KotlinSourceSetDependencies
+
+internal object AssociatedCompilationsMetadataDependenciesContributor :
+    KotlinSourceSetDependenciesContributor<AssociatedCompilationMetadataDependencies> {
+
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<AssociatedCompilationMetadataDependencies>? {
+        val project = sourceSet.project
+        val associatedSourceSets = sourceSet.getAdditionalVisibleSourceSets()
+        return associatedSourceSets.mapNotNull { associatedSourceSet ->
+            val metadataCompilation = project.findMetadataCompilation(associatedSourceSet) ?: return@mapNotNull null
+            AssociatedCompilationMetadataDependencies(associatedSourceSet, metadataCompilation.output.classesDirs)
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/CommonizedNativeDistributionDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/CommonizedNativeDistributionDependenciesContributor.kt
new file mode 100644
index 0000000..b0a04a2
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/CommonizedNativeDistributionDependenciesContributor.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.commonizer.CommonizerTarget
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
+import org.jetbrains.kotlin.gradle.targets.native.internal.commonizedNativeDistributionKlibsOrNull
+import org.jetbrains.kotlin.gradle.targets.native.internal.sharedCommonizerTarget
+
+internal class CommonizedNativeDistributionDependencies(
+    val commonizerTarget: CommonizerTarget,
+    override val files: FileCollection
+) : KotlinSourceSetDependencies {}
+
+internal object CommonizedNativeDistributionDependenciesContributor :
+    KotlinSourceSetDependenciesContributor<CommonizedNativeDistributionDependencies> {
+
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<CommonizedNativeDistributionDependencies>? {
+        val project = sourceSet.project
+        val commonizerTarget = sourceSet.internal.sharedCommonizerTarget.await() ?: return null
+        val files = project.commonizedNativeDistributionKlibsOrNull(commonizerTarget) ?: return null
+        val fileCollection = project.files(files)
+        return listOf(
+            CommonizedNativeDistributionDependencies(commonizerTarget, fileCollection)
+        )
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinConfigurationDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinConfigurationDependenciesContributor.kt
new file mode 100644
index 0000000..7ccb614
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinConfigurationDependenciesContributor.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.targets.metadata.singleKotlinCompilationOrNull
+
+internal class KotlinDependencyFromConfiguration(
+    val configurationName: String,
+    override val files: FileCollection,
+) : KotlinSourceSetDependencies
+
+internal object KotlinDependencyFromConfigurationContributor :
+    KotlinSourceSetDependenciesContributor<KotlinDependencyFromConfiguration> {
+
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<KotlinDependencyFromConfiguration>? {
+        val compilation = sourceSet.singleKotlinCompilationOrNull() ?: return null
+
+        /** Exclude Android because its compileDependencyConfiguration can't be resolved directly */
+        if (compilation.target is KotlinAndroidTarget) return null
+        val project = sourceSet.project
+        val configuration = project.configurations.getByName(compilation.compileDependencyConfigurationName)
+        val files = configuration.incoming.files
+
+        return listOf(KotlinDependencyFromConfiguration(configuration.name, files))
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinDependsOnSourceSetMetadataDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinDependsOnSourceSetMetadataDependenciesContributor.kt
new file mode 100644
index 0000000..84fe167
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinDependsOnSourceSetMetadataDependenciesContributor.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.targets.metadata.findMetadataCompilation
+
+internal class KotlinDependsOnSourceSetMetadataDependencies(
+    val sourceSetName: String,
+    override val files: FileCollection
+): KotlinSourceSetDependencies
+
+internal object KotlinDependsOnSourceSetMetadataDependenciesContributor : KotlinSourceSetDependenciesContributor<KotlinDependsOnSourceSetMetadataDependencies> {
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<KotlinDependsOnSourceSetMetadataDependencies>? {
+        val project = sourceSet.project
+        return sourceSet.dependsOnClosure.mapNotNull { dependsOnSourceSet ->
+            val metadataCompilation = project.findMetadataCompilation(dependsOnSourceSet) ?: return@mapNotNull null
+            KotlinDependsOnSourceSetMetadataDependencies(
+                sourceSetName = dependsOnSourceSet.name,
+                files = metadataCompilation.output.classesDirs
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinNativePlatformDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinNativePlatformDependenciesContributor.kt
new file mode 100644
index 0000000..34c5bf1
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinNativePlatformDependenciesContributor.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinNativeCompilation
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.targets.metadata.singleKotlinCompilationOrNull
+import org.jetbrains.kotlin.gradle.targets.native.internal.retrievePlatformDependencies
+
+internal class KotlinNativePlatformDependency(
+    val platformType: String,
+    override val files: FileCollection,
+) : KotlinSourceSetDependencies
+
+internal object KotlinNativePlatformDependenciesContributor :
+    KotlinSourceSetDependenciesContributor<KotlinNativePlatformDependency> {
+
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<KotlinNativePlatformDependency>? {
+        val compilation = sourceSet.singleKotlinCompilationOrNull() ?: return null
+        if (compilation !is AbstractKotlinNativeCompilation) return null
+
+        val dependencies = compilation.retrievePlatformDependencies()
+        return listOf(KotlinNativePlatformDependency(
+                platformType = compilation.konanTarget.name,
+                files = dependencies
+            )
+        )
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinNativeStdlibDependencyContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinNativeStdlibDependencyContributor.kt
new file mode 100644
index 0000000..24f5bac
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinNativeStdlibDependencyContributor.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.commonizer.stdlib
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.targets.metadata.isNativeSourceSet
+import org.jetbrains.kotlin.gradle.utils.konanDistribution
+
+internal class KotlinNativeStdlibDependency(
+    override val files: FileCollection,
+) : KotlinSourceSetDependencies
+
+internal object KotlinNativeStdlibDependencyContributor :
+    KotlinSourceSetDependenciesContributor<KotlinNativeStdlibDependency> {
+
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<KotlinNativeStdlibDependency>? {
+        if (!sourceSet.isNativeSourceSet.await()) return null
+        val project = sourceSet.project
+
+        return listOf(
+            KotlinNativeStdlibDependency(
+                project.files(project.konanDistribution.stdlib)
+            )
+        )
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinSourceSetDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinSourceSetDependenciesContributor.kt
new file mode 100644
index 0000000..9dee9f1
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/KotlinSourceSetDependenciesContributor.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.plugin.KotlinGradlePluginExtensionPoint
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
+
+internal interface KotlinSourceSetDependenciesContributor<T: KotlinSourceSetDependencies> {
+    suspend operator fun invoke(sourceSet: InternalKotlinSourceSet): List<T>?
+
+    companion object {
+        val extensionPoint = KotlinGradlePluginExtensionPoint<KotlinSourceSetDependenciesContributor<*>>()
+
+        private val cache = mutableMapOf<InternalKotlinSourceSet, List<KotlinSourceSetDependencies>>()
+        suspend fun getOrEvaluate(sourceSet: InternalKotlinSourceSet): List<KotlinSourceSetDependencies> =
+            cache.getOrPut(sourceSet) {
+                val res = mutableListOf<KotlinSourceSetDependencies>()
+                extensionPoint[sourceSet.internal.project].forEach { contributor ->
+                    val contribution = contributor(sourceSet) ?: emptyList()
+                    res.addAll(contribution)
+                }
+                res
+            }
+    }
+}
+
+internal fun <T: KotlinSourceSetDependencies> KotlinSourceSetDependenciesContributor(
+    code: suspend (InternalKotlinSourceSet) -> List<T>?
+) = object : KotlinSourceSetDependenciesContributor<T> {
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<T>? = code(sourceSet)
+}
+
+
+internal suspend fun KotlinSourceSet.dependencies(): List<KotlinSourceSetDependencies> =
+    KotlinSourceSetDependenciesContributor.getOrEvaluate(internal)
+
+sealed interface KotlinSourceSetDependencies {
+    val files: FileCollection
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/TransformedMetadataDependenciesContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/TransformedMetadataDependenciesContributor.kt
new file mode 100644
index 0000000..fe7aeca
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dependencies/TransformedMetadataDependenciesContributor.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2025 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.dependencies
+
+import org.gradle.api.file.FileCollection
+import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
+import org.jetbrains.kotlin.gradle.plugin.KotlinProjectSetupCoroutine
+import org.jetbrains.kotlin.gradle.plugin.mpp.locateOrRegisterMetadataDependencyTransformationTask
+import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet
+import org.jetbrains.kotlin.gradle.plugin.sources.internal
+import org.jetbrains.kotlin.gradle.plugin.sources.isSharedSourceSet
+
+internal class TransformedMetadataDependencies(
+    override val files: FileCollection
+): KotlinSourceSetDependencies
+
+internal object TransformedMetadataDependenciesContributor : KotlinSourceSetDependenciesContributor<TransformedMetadataDependencies> {
+    override suspend fun invoke(sourceSet: InternalKotlinSourceSet): List<TransformedMetadataDependencies>? {
+        val project = sourceSet.project
+        if (!sourceSet.isSharedSourceSet()) return null
+
+        val transformationTask = project.locateOrRegisterMetadataDependencyTransformationTask(sourceSet)
+        val ownTransformedLibraries = transformationTask.map { it.ownTransformedLibraries() }
+        val fileCollection = project.files(ownTransformedLibraries)
+        return listOf(TransformedMetadataDependencies(fileCollection))
+    }
+}
+
+internal val CreateTransformedMetadataDependencies = KotlinProjectSetupCoroutine {
+    val sharedSourceSets = project.multiplatformExtension.awaitSourceSets().filter { it.internal.isSharedSourceSet() }
+    sharedSourceSets.forEach { sourceSet -> project.locateOrRegisterMetadataDependencyTransformationTask(sourceSet) }
+}
\ No newline at end of file
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 76cd110..422863f 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
@@ -137,7 +137,7 @@
                 ),
                 key = "SeparateKmpCompilation"
             )
-        }.orElse(false)
+        }.orElse(true)
 
     val incrementalJs: Boolean?
         get() = booleanProperty("kotlin.incremental.js")
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSourceSetDependencies.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSourceSetDependencies.kt
new file mode 100644
index 0000000..f0c56b6
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSourceSetDependencies.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2025 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.plugin.mpp
+
+///**
+// * Single source of truth for dependencies of a Kotlin source set.
+// */
+//internal suspend fun KotlinSourceSet.allSourceSetDependencies(): List<KotlinSourceSetDependency> {
+//    return listOfNotNull(
+////    gradleConfigurationDependencies(),
+////        nativeStdlibDependency(),
+////        transformedMetadataDependencies(),
+////        cinteropDependencies(),
+//    ).flatten()
+//    // types of KotlinSourceSets:
+//    // 1. Common
+//    // 2. Common Native
+//    // 3. Native platform
+//    // 4. JVM platform
+//    // 5. Android platform
+//    // 6. JS platform
+//    // 8. Wasm platform
+//}
+
+//private suspend fun KotlinSourceSet.nonPublishableSourceSetMetadataDependencies(): List<KotlinSourceSetDependency> {
+//    val platformCompilations = internal.awaitPlatformCompilations()
+//    if (!platformCompilations.any { compilation -> !compilation.isMain() }) return emptyList()
+//
+//}
+//
+//internal sealed class KotlinSourceSetDependency {
+//    data class ResolvedDependency(val resolvedArtifact: ResolvedArtifact) : KotlinSourceSetDependency()
+//    data class KotlinNativeBundleStdlib(val provider: Provider<File>) : KotlinSourceSetDependency()
+//    data class TransformedMetadataKlibDependency(val provider: Provider<File>): KotlinSourceSetDependency()
+//}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/KotlinCompilationK2MultiplatformConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/KotlinCompilationK2MultiplatformConfigurator.kt
index 496c938..caa26b7 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/KotlinCompilationK2MultiplatformConfigurator.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/KotlinCompilationK2MultiplatformConfigurator.kt
@@ -7,144 +7,133 @@
 
 import org.gradle.api.Project
 import org.gradle.api.file.FileCollection
-import org.jetbrains.kotlin.commonizer.stdlib
+import org.gradle.api.provider.SetProperty
+import org.jetbrains.kotlin.gradle.dependencies.KotlinSourceSetDependencies
+import org.jetbrains.kotlin.gradle.dependencies.dependencies
+import org.jetbrains.kotlin.gradle.dsl.KotlinDependencies
 import org.jetbrains.kotlin.gradle.dsl.usesK2
+import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
 import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
-import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinNativeCompilation
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
+import org.jetbrains.kotlin.gradle.plugin.launch
+import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
+import org.jetbrains.kotlin.gradle.plugin.mpp.awaitAllKotlinSourceSets
 import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory.KotlinCompilationImplFactory
 import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOrNull
-import org.jetbrains.kotlin.gradle.plugin.sources.awaitPlatformCompilations
 import org.jetbrains.kotlin.gradle.plugin.sources.internal
-import org.jetbrains.kotlin.gradle.plugin.sources.isSharedSourceSet
-import org.jetbrains.kotlin.gradle.targets.metadata.isNativeSourceSet
-import org.jetbrains.kotlin.gradle.targets.metadata.retrieveExternalDependencies
-import org.jetbrains.kotlin.gradle.targets.native.internal.retrievePlatformDependencies
 import org.jetbrains.kotlin.gradle.tasks.K2MultiplatformCompilationTask
 import org.jetbrains.kotlin.gradle.tasks.K2MultiplatformStructure
-import org.jetbrains.kotlin.gradle.utils.Future
-import org.jetbrains.kotlin.gradle.utils.filesProvider
-import org.jetbrains.kotlin.gradle.utils.future
-import org.jetbrains.kotlin.gradle.utils.konanDistribution
-import org.jetbrains.kotlin.gradle.utils.lazyFuture
-import org.jetbrains.kotlin.utils.topologicalSort
 
 internal object KotlinCompilationK2MultiplatformConfigurator : KotlinCompilationImplFactory.PreConfigure {
-    override fun configure(compilation: KotlinCompilationImpl) {
-        val project = compilation.project
-        compilation.project.tasks.configureEach { compileTask ->
-            if (compileTask.name != compilation.compileKotlinTaskName) return@configureEach
-            if (compileTask !is K2MultiplatformCompilationTask) return@configureEach
+    /**
+     * Returns fragment name of [this]
+     * by default it is name of [KotlinSourceSet] but for android it should name of compilation's default source set.
+     * i.e. all android-specific source sets (fragments) should be combined into one.
+     * See KT-62508 for detailed explanation
+     */
+    private fun KotlinSourceSet.fragmentName(): String =
+        if (androidSourceSetInfoOrNull != null) {
+            androidSourceSetInfoOrNull!!.androidVariantType.name
+        } else {
+            name
+        }
 
-            /**
-             * Returns fragment name of [this]
-             * by default it is name of [KotlinSourceSet] but for android it should name of compilation's default source set.
-             * i.e. all android-specific source sets (fragments) should be combined into one.
-             * See KT-62508 for detailed explanation
-             */
-            fun KotlinSourceSet.fragmentName(): String =
-                if (androidSourceSetInfoOrNull != null) {
-                    compilation.defaultSourceSet.name
-                } else {
-                    name
-                }
+    private fun <T : Any> K2MultiplatformCompilationTask.setIfK2Enabled(
+        propertyGetter: K2MultiplatformStructure.() -> SetProperty<T>,
+        value: () -> Iterable<T>,
+    ): SetProperty<T> {
+        val property = multiplatformStructure.propertyGetter()
+        property.set(compilerOptions.usesK2.map {
+            @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // looks like a bug
+            if (it) value() else null
+        })
+        return property
+    }
 
-            compileTask.multiplatformStructure.refinesEdges.set(compilation.project.provider {
-                if (!compileTask.compilerOptions.usesK2.get()) return@provider emptyList()
-                compilation.allKotlinSourceSets.flatMap { sourceSet ->
-                    sourceSet.dependsOn.mapNotNull { dependsOn ->
-                        val from = sourceSet.fragmentName()
-                        val to = dependsOn.fragmentName()
-                        if (from == to) return@mapNotNull null
-                        K2MultiplatformStructure.RefinesEdge(from, to)
-                    }
-                }
-            })
-
-            compileTask.multiplatformStructure.fragments.set(compilation.project.provider {
-                if (!compileTask.compilerOptions.usesK2.get()) return@provider emptyList()
-
-                val mostCommonFragmentPerNativePlatforms = project.lazyFuture {
-                    val refinementGraph = buildMap<String, MutableSet<String>> {
-                        compileTask.multiplatformStructure.refinesEdges.get().forEach { edge ->
-                            getOrPut(edge.fromFragmentName) { mutableSetOf() }.add(edge.toFragmentName)
-                        }
-                    }
-
-                    compilation.allKotlinSourceSets
-                        .filter { it.internal.isSharedSourceSet() }
-                        .filter { it.isNativeSourceSet.await() }
-                        .map { // fragment -> native platforms
-                            it.fragmentName() to it.internal.awaitPlatformCompilations().filterIsInstance<AbstractKotlinNativeCompilation>()
-                                .map { compilation -> compilation.konanTarget.name }.toSet()
-                        }
-                        .groupBy({ it.second }) { it.first } // native platforms -> fragments
-                        .mapValues { (_, fragments) -> fragments.toSet() }
-                        .mapValues { (_, fragments) -> // the most common fragments go first
-                            topologicalSort(fragments) {
-                                refinementGraph[this]?.filter { it in fragments } ?: emptySet()
-                            }.reversed()
-                        }
-                        .mapValues { (_, fragments) -> fragments.first() }
-                }
-
-                compilation.allKotlinSourceSets
-                    .groupBy { it.fragmentName() }
-                    .map { (fragmentName, sourceSets) ->
-                        val sourceFiles = sourceSets.map { it.kotlin.asFileTree }
-                            .reduce { acc, fileTree -> acc + fileTree }
-                        K2MultiplatformStructure.Fragment(
-                            fragmentName,
-                            sourceFiles,
-                            if (project.kotlinPropertiesProvider.separateKmpCompilation.get()) {
-                                compilation.project.retrieveFragmentDependencies(
-                                    sourceSets,
-                                    fragmentName,
-                                    mostCommonFragmentPerNativePlatforms
-                                )
-                            } else {
-                                project.files()
-                            }
-                        )
-                    }
-            })
-
-            compileTask.multiplatformStructure.defaultFragmentName.set(compilation.defaultSourceSet.fragmentName())
+    private fun KotlinCompilationImpl.fetchRefinesEdges(): List<K2MultiplatformStructure.RefinesEdge> {
+        return allKotlinSourceSets.flatMap { sourceSet ->
+            sourceSet.dependsOn.mapNotNull { dependsOn ->
+                val from = sourceSet.fragmentName()
+                val to = dependsOn.fragmentName()
+                if (from == to) return@mapNotNull null
+                K2MultiplatformStructure.RefinesEdge(from, to)
+            }
         }
     }
 
-    private fun Project.retrieveFragmentDependencies(
-        sourceSets: List<KotlinSourceSet>,
-        fragmentName: String,
-        mostCommonFragmentPerNativePlatformsFuture: Future<Map<Set<String>, String>>,
-    ): FileCollection = filesProvider {
-        future {
-            buildSet {
-                for (sourceSet in sourceSets) {
-                    val internalSourceSet = sourceSet.internal
-                    if (!internalSourceSet.isSharedSourceSet()) continue
-                    if (internalSourceSet.isNativeSourceSet.await()) {
-                        val mostCommonFragmentPerNativePlatforms = mostCommonFragmentPerNativePlatformsFuture.await()
-                        val mostCommonNativeFragment = mostCommonFragmentPerNativePlatforms.maxBy { it.key.size }.value
-                        if (mostCommonNativeFragment == fragmentName) {
-                            add(project.konanDistribution.stdlib)
-                        }
-                        val metadataCompilation = internalSourceSet.compilations.filterIsInstance<KotlinSharedNativeCompilation>()
-                            .find { it.name == sourceSet.name }
-                        if (metadataCompilation != null) {
-                            val nativePlatforms = internalSourceSet.awaitPlatformCompilations()
-                                .filterIsInstance<AbstractKotlinNativeCompilation>()
-                                .map { compilation -> compilation.konanTarget.name }.toSet()
-                            if (mostCommonFragmentPerNativePlatforms[nativePlatforms] == fragmentName) {
-                                add(metadataCompilation.retrievePlatformDependencies())
-                            }
-                        }
-                    }
-                    // We do not need transitive dependencies defined on higher levels of the hierarchy here
-                    add(sourceSet.retrieveExternalDependencies(transitive = false))
-                }
+    override fun configure(compilation: KotlinCompilationImpl) {
+        val project = compilation.project
+        project.launch {
+            val fragments = compilationFragments(compilation, project)
+            compilation.compileTaskProvider.configure configureTask@{ compileTask ->
+                if (compileTask !is K2MultiplatformCompilationTask) return@configureTask
+                compileTask.setIfK2Enabled(K2MultiplatformStructure::refinesEdges) { compilation.fetchRefinesEdges() }
+                compileTask.multiplatformStructure.fragments.set(fragments)
+                compileTask.multiplatformStructure.defaultFragmentName.set(compilation.defaultSourceSet.fragmentName())
             }
-        }.getOrThrow()
+        }
+    }
+
+    internal suspend fun compilationDependencies(compilation: InternalKotlinCompilation<*>): Map<KotlinSourceSet, Set<KotlinSourceSetDependencies>> {
+        val allSourceSets = compilation.awaitAllKotlinSourceSets()
+        val reversedDependsOnEdges = mutableMapOf<KotlinSourceSet, MutableSet<KotlinSourceSet>>()
+        allSourceSets.forEach { sourceSet ->
+            sourceSet.dependsOn.forEach { dependsOn ->
+                reversedDependsOnEdges.getOrPut(dependsOn) { mutableSetOf() }.add(sourceSet)
+            }
+        }
+
+        val rootSourceSets = allSourceSets.toMutableSet()
+        reversedDependsOnEdges.values.forEach { rootSourceSets.removeAll(it) }
+
+        class Node(
+            val sourceSet: KotlinSourceSet,
+            val allDependencies: Set<KotlinSourceSetDependencies>,
+        )
+
+        val queue = ArrayDeque<Node>()
+        rootSourceSets.forEach { queue.add(Node(it, mutableSetOf())) }
+
+        // bfs
+        val result = mutableMapOf<KotlinSourceSet, MutableSet<KotlinSourceSetDependencies>>()
+        while (queue.isNotEmpty()) {
+            val node = queue.removeFirst()
+            val nodeDependencies = result.getOrPut(node.sourceSet) { node.sourceSet.dependencies().toMutableSet() }
+            nodeDependencies.removeAll(node.allDependencies)
+
+            val nextNodes = reversedDependsOnEdges[node.sourceSet] ?: continue
+            val allDependencies = node.allDependencies + nodeDependencies
+            for (nextNode in nextNodes) {
+                queue.addLast(Node(nextNode, allDependencies))
+            }
+        }
+
+        return result
+    }
+
+    private suspend fun compilationFragments(
+        compilation: KotlinCompilationImpl,
+        project: Project,
+    ): List<K2MultiplatformStructure.Fragment> {
+        // val isSeparateKmpCompilation = project.kotlinPropertiesProvider.separateKmpCompilation.get()
+
+        //val compilationDependencies = compilationDependencies(compilation)
+        val compilationDependencies = compilation.awaitAllKotlinSourceSets().associateWith { it.dependencies() }
+
+        return compilation.awaitAllKotlinSourceSets()
+            .flatMap { it.internal.withDependsOnClosure }
+            .groupBy { it.fragmentName() }
+            .map { (fragmentName, sourceSets) ->
+                val sourceFiles = sourceSets.map { it.kotlin.asFileTree }.reduce { acc, fileTree -> acc + fileTree }
+                val dependencies = compilationDependencies[sourceSets.first()] ?: emptySet()
+
+                val fileDependencies = project.files()
+                dependencies.forEach { fileDependencies.from(it.files) }
+                K2MultiplatformStructure.Fragment(
+                    fragmentName,
+                    sourceFiles,
+                    fileDependencies,
+                )
+            }
     }
 }
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 f5d78b5..8173d41 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
@@ -7,7 +7,7 @@
 
 import org.gradle.api.Project
 import org.jetbrains.kotlin.gradle.artifacts.*
-import org.jetbrains.kotlin.gradle.plugin.mpp.uklibs.diagnostics.UklibPublicationDiagnosticsSetupAction
+import org.jetbrains.kotlin.gradle.dependencies.*
 import org.jetbrains.kotlin.gradle.dsl.*
 import org.jetbrains.kotlin.gradle.internal.CustomizeKotlinDependenciesSetupAction
 import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
@@ -32,6 +32,7 @@
 import org.jetbrains.kotlin.gradle.plugin.mpp.resources.publication.SetUpMultiplatformAndroidAssetsAndResourcesPublicationAction
 import org.jetbrains.kotlin.gradle.plugin.mpp.resources.publication.SetUpMultiplatformJvmResourcesPublicationAction
 import org.jetbrains.kotlin.gradle.plugin.mpp.uklibs.consumption.UklibConsumptionSetupAction
+import org.jetbrains.kotlin.gradle.plugin.mpp.uklibs.diagnostics.UklibPublicationDiagnosticsSetupAction
 import org.jetbrains.kotlin.gradle.plugin.sources.KotlinMultiplatformSourceSetSetupAction
 import org.jetbrains.kotlin.gradle.plugin.sources.LanguageSettingsSetupAction
 import org.jetbrains.kotlin.gradle.plugin.statistics.FinalizeConfigurationFusMetricAction
@@ -39,8 +40,8 @@
 import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubpluginSetupAction
 import org.jetbrains.kotlin.gradle.targets.*
 import org.jetbrains.kotlin.gradle.targets.js.npm.AddNpmDependencyExtensionProjectSetupAction
-import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmCompilationWireJavaSourcesSideEffect
 import org.jetbrains.kotlin.gradle.targets.jvm.ConfigureJavaTestFixturesSideEffect
+import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmCompilationWireJavaSourcesSideEffect
 import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetSetupAction
 import org.jetbrains.kotlin.gradle.targets.native.ConfigureFrameworkExportSideEffect
 import org.jetbrains.kotlin.gradle.targets.native.CreateFatFrameworksSetupAction
@@ -101,6 +102,7 @@
             register(project, SetUpMultiplatformAndroidAssetsAndResourcesPublicationAction)
             register(project, SetUpSwiftExportAction)
             register(project, ConfigureKotlinTopLevelDependenciesDSL)
+            register(project, CreateTransformedMetadataDependencies)
 
             if (isKmpProjectIsolationEnabled) {
                 register(project, ProjectStructureMetadataForKMPSetupAction)
@@ -146,6 +148,7 @@
         register(project, KotlinCreateNativeCInteropTasksSideEffect)
         register(project, KotlinCreateCompilationArchivesTask)
         register(project, KotlinJvmCompilationWireJavaSourcesSideEffect)
+//        register(project, ConfigureK2MultiplatformStructureDumpTasks)
     }
 
     KotlinTargetArtifact.extensionPoint.apply {
@@ -196,6 +199,18 @@
             register(project, NativeBinaryConfigurationChecker)
         }
     }
+
+    if (project.kotlinPropertiesProvider.separateKmpCompilation.get()) {
+        KotlinSourceSetDependenciesContributor.extensionPoint.apply {
+            register(project, KotlinDependencyFromConfigurationContributor)
+            register(project, KotlinNativeStdlibDependencyContributor)
+            register(project, KotlinNativePlatformDependenciesContributor)
+            register(project, CommonizedNativeDistributionDependenciesContributor)
+            register(project, TransformedMetadataDependenciesContributor)
+            register(project, AssociatedCompilationsMetadataDependenciesContributor)
+//            register(project, KotlinDependsOnSourceSetMetadataDependenciesContributor)
+        }
+    }
 }
 
 private val Project.isKmpProjectIsolationEnabled get() = PropertiesProvider(project).kotlinKmpProjectIsolationEnabled
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt
index 6fda1f8..e1c3570 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultKotlinSourceSet.kt
@@ -138,7 +138,7 @@
         return getDependenciesTransformation()
     }
 
-    fun getAdditionalVisibleSourceSets(): List<KotlinSourceSet> = getVisibleSourceSetsFromAssociateCompilations(this)
+    override fun getAdditionalVisibleSourceSets(): List<KotlinSourceSet> = getVisibleSourceSetsFromAssociateCompilations(this)
 
     internal fun getDependenciesTransformation(): Iterable<MetadataDependencyTransformation> {
         val metadataDependencyResolutionByModule =
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt
index 0b0ac15..695fb52 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/InternalKotlinSourceSet.kt
@@ -23,6 +23,7 @@
     val dependsOnClosure: ObservableSet<KotlinSourceSet>
     val withDependsOnClosure: ObservableSet<KotlinSourceSet>
     val compilations: MutableObservableSet<KotlinCompilation<*>>
+    fun getAdditionalVisibleSourceSets(): List<KotlinSourceSet>
 }
 
 internal suspend fun InternalKotlinSourceSet.awaitPlatformCompilations(): Set<KotlinCompilation<*>> {
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 2d1c035d8..3a483d5 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
@@ -276,6 +276,9 @@
 internal fun isSingleKotlinTargetSourceSet(sourceSet: KotlinSourceSet): Boolean =
     sourceSet.platformCompilations().map { it.target }.toSet().size == 1
 
+internal fun InternalKotlinSourceSet.singleKotlinCompilationOrNull(): KotlinCompilation<*>? =
+    platformCompilations().distinctBy { it.target }.singleOrNull()
+
 internal fun isMultipleKotlinTargetSourceSet(sourceSet: KotlinSourceSet): Boolean =
     sourceSet.platformCompilations().map { it.target }.toSet().size > 1
 
diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/K2MultiplatformStructure.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/K2MultiplatformStructure.kt
index 058f2d4..f6f6189 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/K2MultiplatformStructure.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/K2MultiplatformStructure.kt
@@ -5,6 +5,8 @@
 
 package org.jetbrains.kotlin.gradle.tasks
 
+import com.google.gson.GsonBuilder
+import com.google.gson.JsonObject
 import org.gradle.api.file.FileCollection
 import org.gradle.api.provider.ListProperty
 import org.gradle.api.provider.Property
@@ -14,6 +16,7 @@
 import org.gradle.work.Incremental
 import org.gradle.work.NormalizeLineEndings
 import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
+import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationSideEffect
 import java.io.File
 
 @InternalKotlinGradlePluginApi
@@ -109,3 +112,91 @@
         "${edge.fromFragmentName}:${edge.toFragmentName}"
     }.toTypedArray()
 
+//internal abstract class K2MultiplatformStructureDumpTask : DefaultTask() {
+//    @get:Nested
+//    abstract val structure: Property<K2MultiplatformStructure>
+//
+//    @get:OutputFile
+//    abstract val output: RegularFileProperty
+//
+//    @TaskAction
+//    fun action() {
+//        val structure = structure.get()
+//        val output = output.get().asFile
+//        output.writeText(structure.toJson())
+//    }
+//}
+
+internal val ConfigureK2MultiplatformStructureDumpTasks = KotlinCompilationSideEffect { compilation ->
+    val project = compilation.project
+    println("Compilation ${compilation.name} of target ${compilation.target.name} of project ${project.path}")
+    println("Has task name: ${compilation.compileTaskProvider.name}")
+    compilation.compileTaskProvider.configure { task ->
+        println("Configure Task: ${task.name} of project ${project.path}")
+        if (task !is K2MultiplatformCompilationTask) return@configure
+        val k2StructureOutput = project.layout.buildDirectory.file("kgp-debug-data/compilations/${task.name}-k2-structure.json")
+        val classpathOutput = project.layout.buildDirectory.file("kgp-debug-data/compilations/${task.name}-classpath.txt")
+
+        task.outputs.files(k2StructureOutput)
+        task.doLast {
+            if (task is KotlinCompileTool) {
+                println("Writing libraries classpath to ${classpathOutput.get().asFile.absolutePath}")
+                classpathOutput.get().asFile.writeText(task.libraries.files.joinToString("\n"))
+            }
+
+            println("Writing K2MultiplatformStructure to ${k2StructureOutput.get().asFile.absolutePath}")
+            k2StructureOutput.get().asFile.writeText(task.multiplatformStructure.toJson())
+        }
+    }
+
+//    project.tasks.register(compilation.disambiguateName("K2MultiplatformStructureDump"), K2MultiplatformStructureDumpTask::class.java) {
+//        val compileTaskProvider = compilation.compileTaskProvider
+//        val structureProvider = compileTaskProvider.map { compileTask ->
+//            (compileTask as K2MultiplatformCompilationTask).multiplatformStructure
+//        }
+//        it.dependsOn(compileTaskProvider)
+//        it.structure.set(structureProvider)
+//        it.output.set(project.layout.buildDirectory.file("k2MultiplatformStructure/${compilation.disambiguatedName}.json"))
+//    }
+}
+
+private fun K2MultiplatformStructure.toJson(): String {
+    val root = JsonObject()
+
+    // Materialize defaultFragmentName if present
+    this.defaultFragmentName.orNull?.let { root.addProperty("defaultFragmentName", it) }
+
+    // Materialize fragments with sources and dependencies as lists of files
+    val fragmentsArray = com.google.gson.JsonArray()
+    for (fragment in this.fragments.get()) {
+        val fragmentObj = JsonObject()
+        fragmentObj.addProperty("fragmentName", fragment.fragmentName)
+
+        val sourcesArray = com.google.gson.JsonArray()
+        for (file in fragment.sources.files) {
+            sourcesArray.add(file.absolutePath)
+        }
+        fragmentObj.add("sources", sourcesArray)
+
+        val depsArray = com.google.gson.JsonArray()
+        for (file in fragment.dependencies.files) {
+            depsArray.add(file.absolutePath)
+        }
+        fragmentObj.add("dependencies", depsArray)
+
+        fragmentsArray.add(fragmentObj)
+    }
+    root.add("fragments", fragmentsArray)
+
+    // Materialize refines edges
+    val edgesArray = com.google.gson.JsonArray()
+    for (edge in this.refinesEdges.get()) {
+        val edgeObj = JsonObject()
+        edgeObj.addProperty("fromFragmentName", edge.fromFragmentName)
+        edgeObj.addProperty("toFragmentName", edge.toFragmentName)
+        edgesArray.add(edgeObj)
+    }
+    root.add("refinesEdges", edgesArray)
+
+    return GsonBuilder().setPrettyPrinting().create().toJson(root)
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/MavenRepositoryMock.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/MavenRepositoryMock.kt
index a8f3bdc..f8b95e4 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/MavenRepositoryMock.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/MavenRepositoryMock.kt
@@ -6,9 +6,13 @@
 package org.jetbrains.kotlin.gradle.dependencyResolutionTests
 
 import org.gradle.api.Project
+import org.gradle.api.attributes.AttributeContainer
 import org.gradle.kotlin.dsl.maven
 import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
 import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinUsageContext
+import org.jetbrains.kotlin.gradle.plugin.mpp.internal
+import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
 import org.jetbrains.kotlin.gradle.utils.targets
 import java.io.File
 
@@ -21,6 +25,11 @@
         val asMavenNotation get() = moduleKey(group, name, version)
         val dependencies: MutableSet<Module> = mutableSetOf()
 
+        fun artifactName(target: KotlinTarget, usageContext: DefaultKotlinUsageContext): String {
+            val extension = if (target is KotlinJvmTarget) "jar" else "klib"
+            return "$name-${usageContext.dependencyConfigurationName}-$version.$extension"
+        }
+
         /**
          * Limitation! All modules should be defined outside of the [variantDependencies] lambda
          */
@@ -40,6 +49,9 @@
 
     fun applyToProject(project: Project, repositoryDir: File) {
         project.allprojects { it.repositories.maven(repositoryDir) }
+    }
+
+    fun publishMocks(project: Project, repositoryDir: File) {
         val targets = project.kotlinExtension.targets.toList()
         declaredModules.values.forEach { module -> module.publishAsMockedLibrary(repositoryDir, targets) }
     }
@@ -73,7 +85,7 @@
     init: MavenRepositoryMockDsl.() -> Unit,
 ): MavenRepositoryMock {
     val mock = mockMavenRepository(init)
-    mock.applyToProject(this, repositoryDir)
+    mock.publishMocks(this, repositoryDir)
     return mock
 }
 
@@ -112,10 +124,18 @@
             </project>
         """.trimIndent()
     )
+
+    kotlinTargets.forEach { target ->
+        target.publishableUsageContexts().forEach { usageContext ->
+            val artifactName = artifactName(target, usageContext)
+            val artifactFile = moduleRootDir.resolve(artifactName)
+            artifactFile.writeText("Mocked artifact content for $target / ${usageContext.name}")
+        }
+    }
 }
 
 private fun MavenRepositoryMock.Module.publishedMockedGradleMetadata(kotlinTargets: List<KotlinTarget>): String {
-    val variants = kotlinTargets.joinToString(",") { variantJson(it) + "\n" }
+    val variants = kotlinTargets.flatMap { variantJsons(it) }.joinToString(",") { "$it\n" }
     return """
             {
               "formatVersion": "1.1",
@@ -134,15 +154,31 @@
         """.trimIndent()
 }
 
-private fun MavenRepositoryMock.Module.variantJson(target: KotlinTarget): String {
-    val apiElements = target.project.configurations.getByName(target.apiElementsConfigurationName)
-    val attributesString = apiElements
-        .attributes
+private fun KotlinTarget.publishableUsageContexts() = internal
+    .kotlinComponents.flatMap { component ->
+        if (!component.publishable) return@flatMap emptyList()
+        component.internal.usages.filterIsInstance<DefaultKotlinUsageContext>()
+    }
+
+private fun MavenRepositoryMock.Module.variantJsons(target: KotlinTarget): List<String> =
+    target.publishableUsageContexts().map { usageContext ->
+        val artifactName = artifactName(target, usageContext)
+        val variantDependencies = variantDependencies(target)
+        val variantName = usageContext.name
+        variantJsons(artifactName, variantDependencies, variantName, usageContext.attributes)
+    }
+
+private fun MavenRepositoryMock.Module.variantJsons(
+    artifactName: String,
+    variantDependencies: Iterable<MavenRepositoryMock.Module>,
+    variantName: String,
+    attributes: AttributeContainer
+): String {
+    val attributesString = attributes
         .keySet()
-        .map { it to apiElements.attributes.getAttribute(it) }
+        .map { it to attributes.getAttribute(it) }
         .joinToString(",\n") { "\"${it.first.name}\": \"${it.second}\"" }
 
-    val variantDependencies = target.variantDependencies()
     val allDependencies = dependencies + variantDependencies
 
     val dependenciesJson = allDependencies.joinToString(", \n") { moduleDependency ->
@@ -159,11 +195,17 @@
 
     return """
                 {
-                  "name": "${target.name.ifEmpty { "apiElements" }}",
+                  "name": "$variantName",
                   "attributes": {
                     $attributesString
                   },
-                  "dependencies": [ $dependenciesJson ]                  
+                  "dependencies": [ $dependenciesJson ],
+                  "files": [
+                    {
+                      "name": "$artifactName",
+                      "url": "$artifactName"
+                    }
+                  ]
                 }
             """.trimIndent()
 }
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/SourceSetDependenciesResolution.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/SourceSetDependenciesResolution.kt
index d000fd5..b2a3a35 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/SourceSetDependenciesResolution.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/SourceSetDependenciesResolution.kt
@@ -7,22 +7,29 @@
 
 import org.gradle.api.Project
 import org.gradle.api.internal.project.ProjectInternal
+import org.jetbrains.kotlin.gradle.dependencies.KotlinSourceSetDependencies
+import org.jetbrains.kotlin.gradle.dependencies.KotlinSourceSetDependenciesContributor
 import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
 import org.jetbrains.kotlin.gradle.dsl.platformTargets
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
 import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
 import org.jetbrains.kotlin.gradle.plugin.sources.internal
+import org.jetbrains.kotlin.gradle.testing.prettyPrinted
 import org.jetbrains.kotlin.gradle.util.*
+import org.jetbrains.kotlin.gradle.utils.future
 import org.jetbrains.kotlin.gradle.utils.targets
 import org.jetbrains.kotlin.test.KotlinTestUtils
 import org.junit.Rule
 import org.junit.rules.TemporaryFolder
+import java.io.File
+import kotlin.test.assertEquals
 
 abstract class SourceSetDependenciesResolution {
     @get:Rule
     val tempFolder = TemporaryFolder()
 
     class SourceSetDependenciesDsl(
-        private val project: Project
+        val project: Project
     ) {
         val mavenRepositoryMock = MavenRepositoryMock()
 
@@ -60,6 +67,25 @@
         configure: SourceSetDependenciesDsl.(Project) -> Unit
     ) {
         val repoRoot = tempFolder.newFolder()
+        val project = prepareProject(repoRoot, withProject, configure)
+
+        val actualResult = project.resolveAllSourceSetDependencies().sanitize()
+        val expectedFile = resourcesRoot
+            .resolve("dependenciesResolution")
+            .resolve(this.javaClass.simpleName)
+            .resolve(expectedFilePath)
+
+        KotlinTestUtils.assertEqualsToFile(expectedFile.toFile(), actualResult) {
+            // remove comment lines
+            it.replace("""\s+//.+""".toRegex(), "")
+        }
+    }
+
+    private fun prepareProject(
+        repoRoot: File,
+        withProject: ProjectInternal?,
+        configure: SourceSetDependenciesDsl.(Project) -> Unit,
+    ): Project {
         val project = withProject ?: buildProject {
             // Disable stdlib and kotlin-dom-api for default tests, as they just pollute dependencies dumps
             enableDefaultStdlibDependency(false)
@@ -76,16 +102,29 @@
 
         project.evaluate()
 
-        val actualResult = project.resolveAllSourceSetDependencies().sanitize()
-        val expectedFile = resourcesRoot
-            .resolve("dependenciesResolution")
-            .resolve(this.javaClass.simpleName)
-            .resolve(expectedFilePath)
+        dsl.mavenRepositoryMock.publishMocks(project, repoRoot)
+        return project
+    }
 
-        KotlinTestUtils.assertEqualsToFile(expectedFile.toFile(), actualResult) {
-            // remove comment lines
-            it.replace("""\s+//.+""".toRegex(), "")
+    internal fun <T : KotlinSourceSetDependencies> testKotlinSourceSetDependenciesContributor(
+        contributor: KotlinSourceSetDependenciesContributor<T>,
+        expectedDependencies: Map<String, Any>,
+        withProject: ProjectInternal? = null,
+        configure: SourceSetDependenciesDsl.(Project) -> Unit
+    ) {
+        val repoRoot = tempFolder.newFolder()
+        val project = prepareProject(repoRoot, withProject, configure)
+        val res: Map<KotlinSourceSet, List<T>?> = project.future {
+            project.kotlinExtension.sourceSets.associateWith { contributor.invoke(it.internal) }
+        }.getOrThrow()
+
+        val dependencies = res.mapKeys { (key, _) -> key.name }.mapValues { (_, value) ->
+            value?.map { it.files }
         }
+        assertEquals(
+            expectedDependencies.prettyPrinted.toString(),
+            dependencies.prettyPrinted.toString()
+        )
     }
 
     private fun Project.resolveAllSourceSetDependencies(): String {
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/contributors/KotlinDependencyFromConfigurationContributorTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/contributors/KotlinDependencyFromConfigurationContributorTest.kt
new file mode 100644
index 0000000..3f2ed11
--- /dev/null
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/contributors/KotlinDependencyFromConfigurationContributorTest.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2010-2025 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.
+ */
+
+@file:Suppress("FunctionName")
+
+package org.jetbrains.kotlin.gradle.dependencyResolutionTests.contributors
+
+import org.gradle.api.Project
+import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
+import org.jetbrains.kotlin.gradle.dependencies.KotlinDependencyFromConfigurationContributor
+import org.jetbrains.kotlin.gradle.dependencyResolutionTests.SourceSetDependenciesResolution
+import org.jetbrains.kotlin.gradle.util.applyMultiplatformPlugin
+import org.jetbrains.kotlin.gradle.util.configureDefaults
+import org.jetbrains.kotlin.gradle.util.kotlin
+import org.jetbrains.kotlin.gradle.util.setMultiplatformAndroidSourceSetLayoutVersion
+import org.jetbrains.kotlin.gradle.utils.androidExtension
+import kotlin.test.Test
+
+@OptIn(ExperimentalWasmDsl::class)
+internal class KotlinDependencyFromConfigurationContributorTest : SourceSetDependenciesResolution() {
+    private val contributor = KotlinDependencyFromConfigurationContributor
+
+    private fun Project.defaultTargets() {
+        setMultiplatformAndroidSourceSetLayoutVersion(2)
+        applyMultiplatformPlugin()
+        plugins.apply("com.android.library")
+        androidExtension.configureDefaults()
+
+        kotlin {
+            jvm()
+            linuxX64()
+            js()
+            wasmJs()
+            wasmWasi()
+            androidTarget {
+                publishLibraryVariants("release")
+            }
+
+            applyDefaultHierarchyTemplate {
+                common {
+                    group("jvmAndAndroid") {
+                        withAndroidTarget()
+                        withJvm()
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun `resolves dependencies for jvm target`() {
+        val expected = mutableMapOf(
+            "x" to "x"
+        )
+        testKotlinSourceSetDependenciesContributor(contributor, expected) { project ->
+            project.defaultTargets()
+
+//            api("commonMain", "test:lib-commonMain:1.0")
+//            api("commonTest", "test:lib-commonTest:1.0")
+//            api("jvmAndAndroidMain", "test:lib-jvmAndAndroidMain:1.0")
+//            api("jvmAndAndroidTest", "test:lib-jvmAndAndroidTest:1.0")
+            api("jvmMain", "test:lib:1.0")
+//            api("jvmTest", "test:lib-test:1.0")
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/uklibs/PrettyPrintTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/uklibs/PrettyPrintTest.kt
index 3132233..70f25b7 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/uklibs/PrettyPrintTest.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/uklibs/PrettyPrintTest.kt
@@ -6,6 +6,8 @@
 package org.jetbrains.kotlin.gradle.unitTests.uklibs
 
 import org.jetbrains.kotlin.gradle.testing.prettyPrinted
+import org.jetbrains.kotlin.gradle.testing.prettyPrintedFileCollectionOf
+import org.jetbrains.kotlin.gradle.util.buildProject
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
@@ -84,6 +86,7 @@
             val a: Int,
             val b: String,
         )
+
         data class B(val m: Map<String, A>)
 
         assertEquals(
@@ -109,6 +112,35 @@
     }
 
     @Test
+    fun testFileCollection() {
+        val project = buildProject {}
+        val fc = project.files("file1.txt", "dir/file2.txt")
+        assertEquals(
+            """
+                prettyPrintedFileCollectionOf(
+                  "${project.projectDir}/file1.txt",
+                  "${project.projectDir}/dir/file2.txt",
+                )
+            """.trimIndent(),
+            fc.prettyPrinted.toString(),
+        )
+    }
+
+    @Test
+    fun testPrettyPrintedFileCollectionOf() {
+        val project = buildProject {}
+        val fc = project.files("file1.txt", "dir/file2.txt")
+
+        assertEquals(
+            prettyPrintedFileCollectionOf(
+                "${project.projectDir}/file1.txt",
+                "${project.projectDir}/dir/file2.txt",
+            ).toString(),
+            fc.prettyPrinted.toString(),
+        )
+    }
+
+    @Test
     fun equalityComparisonOfPrettyPrintedTypes() {
         data class C(
             val value: String
diff --git a/libraries/tools/kotlin-gradle-plugin/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/testing/PrettyPrint.kt b/libraries/tools/kotlin-gradle-plugin/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/testing/PrettyPrint.kt
index 59f1618..de91d7f 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/testing/PrettyPrint.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/testFixtures/kotlin/org/jetbrains/kotlin/gradle/testing/PrettyPrint.kt
@@ -5,6 +5,7 @@
 
 package org.jetbrains.kotlin.gradle.testing
 
+import org.gradle.api.file.FileCollection
 import kotlin.reflect.full.memberProperties
 
 /** Pretty print diffable by text and copypastable collection-like hierarchies */
@@ -17,6 +18,18 @@
         val indentationSpace = " ".repeat(indentation)
         val nextIndentationDepth = indentation + 2
         val elements: Array<String> = when (value) {
+            is FileCollection -> {
+                val files = value.files.map { it.absolutePath }
+                arrayOf(
+                    PrettyPrintedFileCollection(files).prettyPrinted(indentation).toString()
+                )
+            }
+            is PrettyPrintedFileCollection -> arrayOf(
+                "prettyPrintedFileCollectionOf(",
+                *value.map { twoSpaces + it.prettyPrinted(nextIndentationDepth) + "," }.toTypedArray(),
+                ")"
+            )
+
             is Map<*, *> -> arrayOf(
                 "mutableMapOf(",
                 *value.map { it }.sortedBy { it.key.toString() }.map {
@@ -78,4 +91,7 @@
     private fun Any.prettyPrinted(indentation: Int = 0): PrettyPrint<Any> = PrettyPrint(this, indentation)
 }
 
-val <T : Any> T.prettyPrinted: PrettyPrint<T> get() = PrettyPrint(this, 0)
\ No newline at end of file
+val <T : Any> T.prettyPrinted: PrettyPrint<T> get() = PrettyPrint(this, 0)
+
+private class PrettyPrintedFileCollection(files: List<String>) : List<String> by files
+fun prettyPrintedFileCollectionOf(vararg files: String): List<String> = PrettyPrintedFileCollection(files.toList())
\ No newline at end of file