org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerConfigurations.kt Maven / Gradle / Ivy
package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.identityString
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.categoryByName
import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.targets.metadata.awaitMetadataCompilationsCreated
import org.jetbrains.kotlin.gradle.targets.metadata.findMetadataCompilation
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropKlibLibraryElements.cinteropKlibLibraryElements
import org.jetbrains.kotlin.gradle.utils.markConsumable
import org.jetbrains.kotlin.gradle.utils.markResolvable
import org.jetbrains.kotlin.tooling.core.UnsafeApi
/* Elements configuration */
internal suspend fun Project.setupCInteropCommonizedCInteropApiElementsConfigurations() {
val extension = multiplatformExtensionOrNull ?: return
val cinteropCommonizerTask = commonizeCInteropTask() ?: return
/*
Expose api dependencies from Source Sets to the elements configuration
*/
extension.awaitSourceSets().forEach { sourceSet ->
val commonizerTarget = sourceSet.commonizerTarget.await() as? SharedCommonizerTarget ?: return@forEach
val configuration = locateOrCreateCommonizedCInteropApiElementsConfiguration(commonizerTarget)
val metadataCompilation = findMetadataCompilation(sourceSet) ?: return@forEach
configuration.extendsFrom(metadataCompilation.internal.configurations.apiConfiguration)
}
/*
Expose artifacts from cinterop commonizer
*/
for (commonizerGroup in kotlinCInteropGroups.await()) {
for (target in commonizerGroup.targets) {
val configuration = locateOrCreateCommonizedCInteropApiElementsConfiguration(target)
val commonizerTargetOutputDir = cinteropCommonizerTask.map { task ->
CommonizerOutputFileLayout.resolveCommonizedDirectory(task.outputDirectory(commonizerGroup), target)
}
project.artifacts.add(configuration.name, commonizerTargetOutputDir) { artifact ->
artifact.extension = CInteropCommonizerArtifactTypeAttribute.KLIB_COLLECTION_DIR
artifact.type = CInteropCommonizerArtifactTypeAttribute.KLIB_COLLECTION_DIR
artifact.builtBy(cinteropCommonizerTask)
}
}
}
}
internal fun Project.locateOrCreateCommonizedCInteropApiElementsConfiguration(commonizerTarget: SharedCommonizerTarget): Configuration {
val configurationName = commonizerTarget.identityString + "CInteropApiElements"
configurations.findByName(configurationName)?.let { return it }
return configurations.create(configurationName) { configuration ->
configuration.markConsumable()
setupBasicCommonizedCInteropConfigurationAttributes(configuration, commonizerTarget)
launch {
val metadataTarget = multiplatformExtension.metadata() as KotlinMetadataTarget
metadataTarget.awaitMetadataCompilationsCreated()
.filter { compilation -> compilation.commonizerTarget.await() == commonizerTarget }
.forEach { compilation -> configuration.extendsFrom(compilation.internal.configurations.apiConfiguration) }
}
}
}
/* Dependency configuration */
/**
* Gives access the 'commonized cinterop dependency configuration' of the given [sourceSet].
* The access is forced through this 'view' because the provided 'artifact view' is forced to be lenient as protective measure.
*
* If dependencies do not provide corresponding commonized cinterop element configurations then we should not fail the build!
*/
internal suspend fun Project.createCommonizedCInteropDependencyConfigurationView(sourceSet: KotlinSourceSet): FileCollection {
@OptIn(UnsafeApi::class)
val configuration = locateOrCreateCommonizedCInteropDependencyConfiguration(sourceSet) ?: return files()
return configuration.incoming.artifactView { view -> view.isLenient = true }.files
}
@UnsafeApi("Use createCommonizedCInteropDependencyConfigurationView instead")
internal suspend fun Project.locateOrCreateCommonizedCInteropDependencyConfiguration(
sourceSet: KotlinSourceSet,
): Configuration? {
val commonizerTarget = sourceSet.commonizerTarget.await() ?: return null
if (commonizerTarget !is SharedCommonizerTarget) return null
val configurationName = commonizerTarget.identityString + "CInterop"
configurations.findByName(configurationName)?.let { return it }
val configuration = configurations.create(configurationName) { configuration ->
configuration.isVisible = false
configuration.markResolvable()
// Extends from Metadata Configuration associated with given source set to ensure matching
configuration.extendsFrom(sourceSet.internal.resolvableMetadataConfiguration)
setupBasicCommonizedCInteropConfigurationAttributes(configuration, commonizerTarget)
/**
* Dependencies require the [CInteropCommonizerArtifactTypeAttribute.KLIB].
* If artifacts are added using [CInteropCommonizerArtifactTypeAttribute.KLIB_COLLECTION_DIR] then a transformation
* has to happen that will resolve the exact list of klibs.
*/
configuration.attributes.attribute(CInteropCommonizerArtifactTypeAttribute.attribute, CInteropCommonizerArtifactTypeAttribute.KLIB)
description = "Commonized CInterop dependencies for targets: '$commonizerTarget'."
}
return configuration
}
private fun Project.setupBasicCommonizedCInteropConfigurationAttributes(
configuration: Configuration,
commonizerTarget: SharedCommonizerTarget,
) {
configuration.attributes.attribute(CommonizerTargetAttribute.attribute, commonizerTarget.identityString)
configuration.attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, KotlinUsages.KOTLIN_COMMONIZED_CINTEROP))
configuration.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
}