From b2bef4ad412368a5d5b5e384c88ee53d4a4a1fa0 Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Mon, 14 Aug 2023 17:02:34 +0200 Subject: [PATCH] [Gradle] Extract allInteropGroups from CInteropCommonizerTask This information is needed to create consumable configurations for Commonized Cinterop outputs. This way CInteropCommonizerTask is not required to be created eagerly. ^KT-59596 Verification Pending --- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 6 +- .../native/internal/CInteropCommonizerTask.kt | 47 ++-------- .../native/internal/CInteropConfigurations.kt | 22 +---- .../internal/configureCInteropCommonizer.kt | 85 +++++++++++++++++++ 4 files changed, 93 insertions(+), 67 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/configureCInteropCommonizer.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 2a23e56bf2a..6c3007de1b0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.* @@ -28,8 +27,7 @@ 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.internal.configureCInteropCommonizer import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.registerKotlinArtifactsExtension import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility @@ -75,7 +73,7 @@ class KotlinMultiplatformPlugin : Plugin { // Ensure that the instance is created and configured during apply project.kotlinIdeMultiplatformImport project.locateOrRegisterIdeResolveDependenciesTask() - project.launch { project.createCommonizedCInteropApiElementsKlibArtifact() } + project.launch { project.configureCInteropCommonizer() } project.addBuildListenerForXcode() project.whenEvaluated { kotlinMultiplatformExtension.createFatFrameworks() } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt index 7eb97426bb4..59d26a0dd9c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropCommonizerTask.kt @@ -20,13 +20,9 @@ import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime import org.jetbrains.kotlin.commonizer.* import org.jetbrains.kotlin.compilerRunner.* -import org.jetbrains.kotlin.compilerRunner.GradleCliCommonizer -import org.jetbrains.kotlin.compilerRunner.KotlinNativeCommonizerToolRunner -import org.jetbrains.kotlin.compilerRunner.konanHome import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure import org.jetbrains.kotlin.gradle.report.GradleBuildMetricsReporter @@ -95,6 +91,10 @@ internal abstract class CInteropCommonizerTask override val outputDirectory: File get() = projectLayout.buildDirectory.get().asFile.resolve("classes/kotlin/commonizer") + internal fun outputDirectoriesOfCommonizerGroup(group: CInteropCommonizerGroup): Map = group + .targets + .associateWith { target -> CommonizerOutputFileLayout.resolveCommonizedDirectory(outputDirectory, target) } + @get:Internal internal val kotlinPluginVersion: Property = objectFactory .property() @@ -256,24 +256,7 @@ internal abstract class CInteropCommonizerTask } @get:Internal - internal val allInteropGroups: Future> = project.lazyFuture { - val dependents = allDependents.await() - val allScopeSets = dependents.map { it.scopes }.toSet() - val rootScopeSets = allScopeSets.filter { scopeSet -> - allScopeSets.none { otherScopeSet -> otherScopeSet != scopeSet && otherScopeSet.containsAll(scopeSet) } - } - - rootScopeSets.map { scopeSet -> - val dependentsForScopes = dependents.filter { dependent -> - scopeSet.containsAll(dependent.scopes) - } - - CInteropCommonizerGroup( - targets = dependentsForScopes.map { it.target }.toSet(), - interops = dependentsForScopes.flatMap { it.interops }.toSet() - ) - }.toSet() - } + internal val allInteropGroups: CompletableFuture> = CompletableFuture() @get:Nested @Suppress("unused") // UP-TO-DATE check @@ -290,26 +273,6 @@ internal abstract class CInteropCommonizerTask return suitableGroups.firstOrNull() } - - private val allDependents: Future> = project.lazyFuture { - val multiplatformExtension = project.multiplatformExtensionOrNull ?: return@lazyFuture emptySet() - - val fromSharedNativeCompilations = multiplatformExtension - .targets.flatMap { target -> target.compilations } - .filterIsInstance() - .mapNotNull { compilation -> CInteropCommonizerDependent.from(compilation) } - .toSet() - - val fromSourceSets = multiplatformExtension.awaitSourceSets() - .mapNotNull { sourceSet -> CInteropCommonizerDependent.from(sourceSet) } - .toSet() - - val fromSourceSetsAssociateCompilations = multiplatformExtension.awaitSourceSets() - .mapNotNull { sourceSet -> CInteropCommonizerDependent.fromAssociateCompilations(sourceSet) } - .toSet() - - (fromSharedNativeCompilations + fromSourceSets + fromSourceSetsAssociateCompilations) - } } private fun CInteropProcess.toGist(): CInteropGist { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt index f477e46fe12..9debe525057 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CInteropConfigurations.kt @@ -9,14 +9,11 @@ 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.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.sources.internal @@ -41,23 +38,6 @@ internal fun createCInteropApiElementsKlibArtifact( } } -internal suspend fun Project.createCommonizedCInteropApiElementsKlibArtifact() { - // TODO: Find a way to not materialize task. i.e. initialize only outputDirectory and allInteropGroups - val interopTask = project.commonizeCInteropTask()?.get() ?: return - 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 { @@ -162,7 +142,7 @@ private fun cInteropApiElementsConfigurationName(target: KotlinTarget): String { /** * Same as [org.jetbrains.kotlin.commonizer.identityString] but target segments separated with dash */ -private fun SharedCommonizerTarget.dashedIdentityString() = targets.map { it.name }.sorted().joinToString("-") +internal fun SharedCommonizerTarget.dashedIdentityString() = targets.map { it.name }.sorted().joinToString("-") private fun commonizedCInteropApiElementsConfigurationName(commonizerTarget: SharedCommonizerTarget): String { return commonizerTarget.dashedIdentityString() + "CInteropApiElements" } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/configureCInteropCommonizer.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/configureCInteropCommonizer.kt new file mode 100644 index 00000000000..e50409d2ad3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/configureCInteropCommonizer.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2023 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.targets.native.internal + +import org.gradle.api.Project +import org.gradle.api.tasks.TaskProvider +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation + +internal suspend fun Project.configureCInteropCommonizer() { + val interopTask = commonizeCInteropTask() ?: return + + val cinteropGroups = getCInteropGroups() + configureCInteropCommonizerConsumableConfigurations(cinteropGroups, interopTask) + + interopTask.configure { + it.allInteropGroups.complete(cinteropGroups) + } +} + +private fun Project.configureCInteropCommonizerConsumableConfigurations( + cinteropGroups: Set, + interopTask: TaskProvider, +) { + for (commonizerGroup in cinteropGroups) { + for (sharedCommonizerTargets in commonizerGroup.targets) { + val configuration = locateOrCreateCommonizedCInteropApiElementsConfiguration(sharedCommonizerTargets) + val commonizerTargetOutputDir = interopTask.map { task -> + task.outputDirectoriesOfCommonizerGroup(commonizerGroup)[sharedCommonizerTargets] + ?: error("Can't find output of Shared Commonizer Target $sharedCommonizerTargets") + } + project.artifacts.add(configuration.name, commonizerTargetOutputDir) { artifact -> + artifact.extension = "klib" + artifact.type = "klib" + artifact.classifier = "cinterop-" + sharedCommonizerTargets.dashedIdentityString() + artifact.builtBy(interopTask) + } + } + } +} + +private suspend fun Project.allCinteropCommonizerDependents(): Set { + val multiplatformExtension = project.multiplatformExtensionOrNull ?: return emptySet() + + val fromSharedNativeCompilations = multiplatformExtension + .targets.flatMap { target -> target.compilations } + .filterIsInstance() + .mapNotNull { compilation -> CInteropCommonizerDependent.from(compilation) } + .toSet() + + val fromSourceSets = multiplatformExtension.awaitSourceSets() + .mapNotNull { sourceSet -> CInteropCommonizerDependent.from(sourceSet) } + .toSet() + + val fromSourceSetsAssociateCompilations = multiplatformExtension.awaitSourceSets() + .mapNotNull { sourceSet -> CInteropCommonizerDependent.fromAssociateCompilations(sourceSet) } + .toSet() + + return (fromSharedNativeCompilations + fromSourceSets + fromSourceSetsAssociateCompilations) +} + +private suspend fun Project.getCInteropGroups(): Set { + val dependents = allCinteropCommonizerDependents() + + val allScopeSets = dependents.map { it.scopes }.toSet() + val rootScopeSets = allScopeSets.filter { scopeSet -> + allScopeSets.none { otherScopeSet -> otherScopeSet != scopeSet && otherScopeSet.containsAll(scopeSet) } + } + + val result = rootScopeSets.map { scopeSet -> + val dependentsForScopes = dependents.filter { dependent -> + scopeSet.containsAll(dependent.scopes) + } + + CInteropCommonizerGroup( + targets = dependentsForScopes.map { it.target }.toSet(), + interops = dependentsForScopes.flatMap { it.interops }.toSet() + ) + }.toSet() + + return result +}