[Gradle] Add PreExtractedProjectMetadataProvider

It is decoupled from Gradle Project and can be stored in
Gradle Configuration cache safely.

^KT-49933
This commit is contained in:
Anton Lakotka
2023-01-12 10:25:35 +01:00
committed by Space Team
parent 84d7139a12
commit 7290947fe8
3 changed files with 84 additions and 2 deletions
@@ -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?
}
}
@@ -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<SourceSetName, SourceSetMetadataOutputs>
): 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<SourceSetName, SourceSetMetadataOutputs> {
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<KotlinSourceSet, FileCollection> {
val commonTarget = targets.withType<KotlinMetadataTarget>().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<KotlinSourceSet>
): Map<KotlinSourceSet, SourceSetMetadataOutputs.CInterop?> {
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)
)
}
}
@@ -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)
}
}