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 6c8ee02ab3b..2d5e20e9bda 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 @@ -78,7 +78,7 @@ internal sealed class MetadataDependencyResolution( enum class MetadataConsumer { Ide, Cli } abstract fun getSourceSetCompiledMetadata(sourceSetName: String): FileCollection - abstract fun getSourceSetCInteropMetadata(sourceSetName: String, consumer: MetadataConsumer): FileCollection + abstract fun getSourceSetCInteropMetadata(sourceSetName: String, consumer: MetadataConsumer): FileCollection? } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ProjectMetadataProviderImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ProjectMetadataProviderImpl.kt index 4eb04930c7d..aae7fa19624 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ProjectMetadataProviderImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ProjectMetadataProviderImpl.kt @@ -8,11 +8,15 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.jetbrains.kotlin.gradle.dsl.* +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ProjectMetadataProvider import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.metadataCompilationRegistryByModuleId import org.jetbrains.kotlin.gradle.targets.native.internal.* +import org.jetbrains.kotlin.gradle.utils.withType import org.jetbrains.kotlin.project.model.KpmModuleIdentifier +private typealias SourceSetName = String + internal fun ProjectMetadataProvider( dependencyProject: Project, moduleIdentifier: KpmModuleIdentifier @@ -56,3 +60,81 @@ private class ProjectMetadataProviderImpl( return commonizeCInteropTask.get().commonizedOutputLibraries(dependent) } } + +internal class SourceSetMetadataOutputs( + val metadata: FileCollection, + val cinterop: CInterop? +) { + class CInterop( + val forCli: FileCollection, + val forIde: FileCollection + ) +} + +internal class PreExtractedProjectMetadataProvider( + private val sourceSetMetadataOutputs: Map +): ProjectMetadataProvider() { + + constructor(project: Project): this(project.collectSourceSetMetadataOutputs()) + + override fun getSourceSetCompiledMetadata(sourceSetName: String): FileCollection = + sourceSetMetadataOutputs[sourceSetName]?.metadata ?: error("Unexpected source set '$sourceSetName'") + + override fun getSourceSetCInteropMetadata(sourceSetName: String, consumer: MetadataConsumer): FileCollection? { + val metadataOutputs = sourceSetMetadataOutputs[sourceSetName] ?: error("Unexpected source set '$sourceSetName'") + val cinteropMetadata = metadataOutputs.cinterop ?: return null + return when (consumer) { + MetadataConsumer.Ide -> cinteropMetadata.forIde + MetadataConsumer.Cli -> cinteropMetadata.forCli + } + } +} + +internal fun Project.collectSourceSetMetadataOutputs(): Map { + val multiplatformExtension = multiplatformExtensionOrNull ?: return emptyMap() + + val sourceSetMetadata = multiplatformExtension.sourceSetsMetadataOutputs() + val sourceSetCInteropMetadata = multiplatformExtension.cInteropMetadataOfSourceSets(sourceSetMetadata.keys) + + return sourceSetMetadata.mapValues { (sourceSet, metadata) -> + val cinteropMetadataOutput = sourceSetCInteropMetadata[sourceSet] + SourceSetMetadataOutputs( + metadata = metadata, + cinterop = cinteropMetadataOutput + ) + }.mapKeys { it.key.name } +} + +private fun KotlinMultiplatformExtension.sourceSetsMetadataOutputs(): Map { + val commonTarget = targets.withType().singleOrNull() ?: return emptyMap() + + val compilations = commonTarget.compilations + + return sourceSets.mapNotNull { sourceSet -> + val compilation = compilations.findByName(sourceSet.name) + ?: return@mapNotNull null // given source set is not shared + + val destination = when (compilation) { + is KotlinCommonCompilation -> compilation.output.classesDirs + is KotlinSharedNativeCompilation -> compilation.output.classesDirs + else -> error("Unexpected compilation type: $compilation") + } + + Pair(sourceSet, destination) + }.toMap() +} + +private fun KotlinMultiplatformExtension.cInteropMetadataOfSourceSets( + sourceSets: Iterable +): Map { + val taskForCLI = project.commonizeCInteropTask ?: return emptyMap() + val taskForIde = project.copyCommonizeCInteropForIdeTask ?: return emptyMap() + + return sourceSets.associateWith { sourceSet -> + val dependent = CInteropCommonizerDependent.from(sourceSet) ?: return@associateWith null + SourceSetMetadataOutputs.CInterop( + forCli = taskForCLI.get().commonizedOutputLibraries(dependent), + forIde = taskForIde.get().commonizedOutputLibraries(dependent) + ) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt index 4b4d7f8d42c..0cd2de1a4dd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropMetadataDependencyClasspath.kt @@ -61,7 +61,7 @@ private fun Project.createCInteropMetadataDependencyClasspathFromProjectDependen is ArtifactMetadataProvider -> return@flatMap emptyList() } - chooseVisibleSourceSets.visibleSourceSetsProvidingCInterops.map { visibleSourceSetName -> + chooseVisibleSourceSets.visibleSourceSetsProvidingCInterops.mapNotNull { visibleSourceSetName -> projectMetadataProvider.getSourceSetCInteropMetadata(visibleSourceSetName, if (forIde) Ide else Cli) } }