[Gradle] Draft implementation of Configurations for Commonized CInterops
Introduce *CommonizedCInterop & *CommonizedCInteropElements configurations and fix CInteropCommonizerTask to consume dependencies / expose artifacts via these configurations.
This commit is contained in:
committed by
Space Team
parent
640d1e3fc8
commit
b37ebb47d9
+3
-3
@@ -479,10 +479,10 @@ open class CommonizerIT : KGPBaseTest() {
|
||||
@GradleTest
|
||||
fun testCommonizationWithTwoCInteropCommonizerGroups(gradleVersion: GradleVersion) {
|
||||
nativeProject("commonize-kt-57796-twoCInteropCommonizerGroups", gradleVersion) {
|
||||
build(":app:commonizeCIntero") {
|
||||
assertTasksExecuted(":lib:transformCommonMainCInteropDependenciesMetadata")
|
||||
build(":app:commonizeCInterop") {
|
||||
assertTasksNotExecuted(":lib:transformCommonMainCInteropDependenciesMetadata")
|
||||
assertTasksExecuted(":lib:commonizeCInterop")
|
||||
assertTasksExecuted(":app:transformCommonMainCInteropDependenciesMetadata")
|
||||
assertTasksNotExecuted(":app:transformCommonMainCInteropDependenciesMetadata")
|
||||
assertTasksExecuted(":app:commonizeCInterop")
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType
|
||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinWasmTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.targets.native.createFatFrameworks
|
||||
import org.jetbrains.kotlin.gradle.targets.native.internal.commonizeCInteropTask
|
||||
import org.jetbrains.kotlin.gradle.targets.native.internal.createCommonizedCInteropApiElementsKlibArtifact
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.registerKotlinArtifactsExtension
|
||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool
|
||||
import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility
|
||||
@@ -73,7 +75,13 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
|
||||
// Ensure that the instance is created and configured during apply
|
||||
project.kotlinIdeMultiplatformImport
|
||||
project.locateOrRegisterIdeResolveDependenciesTask()
|
||||
|
||||
// FIXME: This code creates consumable configurations for Commonized CInterops
|
||||
// FIXME: Unfortunately, it also creates [commonizeCInteropTask] eagerly
|
||||
// FIXME: Decouple [allInteropGroups] from task internals and then create configuration without task materialization.
|
||||
project.launch {
|
||||
val task = project.commonizeCInteropTask()?.get() ?: return@launch
|
||||
project.createCommonizedCInteropApiElementsKlibArtifact(task)
|
||||
}
|
||||
project.addBuildListenerForXcode()
|
||||
project.whenEvaluated { kotlinMultiplatformExtension.createFatFrameworks() }
|
||||
}
|
||||
|
||||
+22
-1
@@ -137,6 +137,7 @@ internal abstract class CInteropCommonizerTask
|
||||
val sourceSetsByGroup = multiplatformExtension.sourceSets.groupBy { sourceSet ->
|
||||
CInteropCommonizerDependent.from(sourceSet)?.let { findInteropsGroup(it) }
|
||||
}
|
||||
|
||||
allInteropGroups.await().associateWith { group ->
|
||||
(group.targets + group.targets.allLeaves()).map { target ->
|
||||
val externalDependencyFiles: List<FileCollection> = when (target) {
|
||||
@@ -157,7 +158,19 @@ internal abstract class CInteropCommonizerTask
|
||||
will provide the same dependencies (since cinterops are just based upon KonanTarget)
|
||||
*/
|
||||
.take(1)
|
||||
.map { sourceSet -> project.createCInteropMetadataDependencyClasspath(sourceSet) }
|
||||
.map { sourceSet ->
|
||||
val configuration = project.locateOrCreateCommonizedCInteropDependencyConfiguration(sourceSet)
|
||||
if (configuration != null) {
|
||||
configuration.incoming
|
||||
// Lenient is required since not every dependency exposes commonized CInterop KLibs
|
||||
// Only Projects with CInterops would expose their commonization results.
|
||||
// See: [createCommonizedCInteropApiElementsKlibArtifact]
|
||||
.artifactView { it.isLenient = true }
|
||||
.files
|
||||
} else {
|
||||
project.files()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +239,14 @@ internal abstract class CInteropCommonizerTask
|
||||
?.flatMap { (target, dependencies) ->
|
||||
dependencies.files
|
||||
.filter { file -> file.exists() && (file.isDirectory || file.extension == "klib") }
|
||||
.flatMap flatMap2@{ dir ->
|
||||
// FIXME: dir can be either a klib dir or parent dir of few klib dirs
|
||||
// FIXME: Find a way to expose exact klib-dirs in consumable configuration
|
||||
if (!dir.isDirectory) return@flatMap2 listOf(dir)
|
||||
val subDirs = dir.listFiles().orEmpty().toList()
|
||||
fun List<File>.isKlibDir() = any { it.isDirectory && it.name == "default" }
|
||||
if (subDirs.isKlibDir()) return@flatMap2 listOf(dir) else subDirs
|
||||
}
|
||||
.map { file -> TargetedCommonizerDependency(target, file) }
|
||||
}
|
||||
?.toSet()
|
||||
|
||||
+88
-4
@@ -9,17 +9,21 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.attributes.*
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout
|
||||
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinNativeTargetConfigurator.NativeArtifactFormat
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.categoryByName
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.artifactTypeAttribute
|
||||
import org.jetbrains.kotlin.gradle.plugin.launchInStage
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
|
||||
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.internal
|
||||
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropKlibLibraryElements.cinteropKlibLibraryElements
|
||||
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
|
||||
import org.jetbrains.kotlin.gradle.utils.markConsumable
|
||||
import org.jetbrains.kotlin.gradle.utils.markResolvable
|
||||
|
||||
internal fun createCInteropApiElementsKlibArtifact(
|
||||
target: KotlinNativeTarget,
|
||||
@@ -37,6 +41,23 @@ internal fun createCInteropApiElementsKlibArtifact(
|
||||
}
|
||||
}
|
||||
|
||||
internal suspend fun Project.createCommonizedCInteropApiElementsKlibArtifact(
|
||||
interopTask: CInteropCommonizerTask
|
||||
) {
|
||||
for (commonizerGroup in interopTask.allInteropGroups.await()) {
|
||||
for (sharedCommonizerTargets in commonizerGroup.targets) {
|
||||
val configuration = locateOrCreateCommonizedCInteropApiElementsConfiguration(sharedCommonizerTargets)
|
||||
val artifactPath = CommonizerOutputFileLayout.resolveCommonizedDirectory(interopTask.outputDirectory(commonizerGroup), sharedCommonizerTargets)
|
||||
project.artifacts.add(configuration.name, artifactPath) { artifact ->
|
||||
artifact.extension = "klib"
|
||||
artifact.type = "klib"
|
||||
artifact.classifier = "cinterop-" + sharedCommonizerTargets.dashedIdentityString()
|
||||
artifact.builtBy(interopTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Project.locateOrCreateCInteropDependencyConfiguration(
|
||||
compilation: KotlinNativeCompilation,
|
||||
): Configuration {
|
||||
@@ -48,8 +69,7 @@ internal fun Project.locateOrCreateCInteropDependencyConfiguration(
|
||||
return configurations.create(compilation.cInteropDependencyConfigurationName).apply {
|
||||
extendsFrom(compileOnlyConfiguration, implementationConfiguration)
|
||||
isVisible = false
|
||||
isCanBeResolved = true
|
||||
isCanBeConsumed = false
|
||||
markResolvable()
|
||||
|
||||
/* Deferring attributes to wait for compilation.attributes to be configured by user*/
|
||||
launchInStage(AfterFinaliseDsl) {
|
||||
@@ -63,9 +83,46 @@ internal fun Project.locateOrCreateCInteropDependencyConfiguration(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Configuration.applyAttributesForCommonizerTarget(commonizerTarget: SharedCommonizerTarget) {
|
||||
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.native)
|
||||
// TODO: [KotlinNativeTarget.konanTargetAttribute] is a public attribute. It should be better to introduce dedicated private attribute
|
||||
// TODO: for commonized target
|
||||
attributes.attribute(KotlinNativeTarget.konanTargetAttribute, commonizerTarget.dashedIdentityString())
|
||||
}
|
||||
|
||||
internal suspend fun Project.locateOrCreateCommonizedCInteropDependencyConfiguration(
|
||||
sourceSet: KotlinSourceSet,
|
||||
): Configuration? {
|
||||
val commonizerTarget = sourceSet.commonizerTarget.await() ?: return null
|
||||
if (commonizerTarget !is SharedCommonizerTarget) return null
|
||||
|
||||
configurations.findByName(commonizerTarget.commonizedCInteropDependencyConfigurationName)?.let { return it }
|
||||
|
||||
val configuration = configurations.create(commonizerTarget.commonizedCInteropDependencyConfigurationName).apply {
|
||||
isVisible = false
|
||||
markResolvable()
|
||||
|
||||
/* Deferring attributes to wait for compilation.attributes to be configured by user*/
|
||||
launchInStage(AfterFinaliseDsl) {
|
||||
// Extends from Metadata Configuration associated with given source set to ensure matching
|
||||
extendsFrom(sourceSet.internal.resolvableMetadataConfiguration)
|
||||
applyAttributesForCommonizerTarget(commonizerTarget)
|
||||
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, cinteropKlibLibraryElements())
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, KotlinUsages.KOTLIN_CINTEROP))
|
||||
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
|
||||
description = "Commonized CInterop dependencies for targets: '$commonizerTarget'."
|
||||
}
|
||||
}
|
||||
|
||||
return configuration
|
||||
}
|
||||
|
||||
internal val KotlinNativeCompilation.cInteropDependencyConfigurationName: String
|
||||
get() = compilation.disambiguateName("CInterop")
|
||||
|
||||
internal val SharedCommonizerTarget.commonizedCInteropDependencyConfigurationName: String
|
||||
get() = dashedIdentityString() + "CInterop"
|
||||
|
||||
internal fun Project.locateOrCreateCInteropApiElementsConfiguration(target: KotlinTarget): Configuration {
|
||||
val configurationName = cInteropApiElementsConfigurationName(target)
|
||||
configurations.findByName(configurationName)?.let { return it }
|
||||
@@ -86,10 +143,37 @@ internal fun Project.locateOrCreateCInteropApiElementsConfiguration(target: Kotl
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Project.locateOrCreateCommonizedCInteropApiElementsConfiguration(commonizerTarget: SharedCommonizerTarget): Configuration {
|
||||
val configurationName = commonizedCInteropApiElementsConfigurationName(commonizerTarget)
|
||||
configurations.findByName(configurationName)?.let { return it }
|
||||
|
||||
return configurations.create(configurationName).apply {
|
||||
markConsumable()
|
||||
|
||||
/* Deferring attributes to wait for target.attributes to be configured by user */
|
||||
launchInStage(AfterFinaliseDsl) {
|
||||
applyAttributesForCommonizerTarget(commonizerTarget)
|
||||
|
||||
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, cinteropKlibLibraryElements())
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, KotlinUsages.KOTLIN_CINTEROP))
|
||||
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
|
||||
attributes.attribute(artifactTypeAttribute, NativeArtifactFormat.KLIB)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun cInteropApiElementsConfigurationName(target: KotlinTarget): String {
|
||||
return target.name + "CInteropApiElements"
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as [org.jetbrains.kotlin.commonizer.identityString] but target segments separated with dash
|
||||
*/
|
||||
private fun SharedCommonizerTarget.dashedIdentityString() = targets.map { it.name }.sorted().joinToString("-")
|
||||
private fun commonizedCInteropApiElementsConfigurationName(commonizerTarget: SharedCommonizerTarget): String {
|
||||
return commonizerTarget.dashedIdentityString() + "CInteropApiElements"
|
||||
}
|
||||
|
||||
internal object CInteropKlibLibraryElements {
|
||||
const val CINTEROP_KLIB = "cinterop-klib"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user