From 4941e8b7dede5b13d08ef18adf7b64e98576f5b6 Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Thu, 12 Jan 2023 12:15:37 +0100 Subject: [PATCH] [Gradle] Provide transformed libraries from transformation task itself Remove `createMetadataDependencyTransformationClasspath` that were using `ResolvedMetadataFilesProvider` which is no longer used by GranularMetadataTransformation. The transformed files can be requested directly from resolution results. ^KT-49933 --- .../MetadataDependencyTransformationTask.kt | 33 +++++ .../pm20/GradleKpmMetadataCompilationData.kt | 15 +-- .../KotlinMetadataTargetConfigurator.kt | 117 +++++------------- .../gradle/utils/LazyResolvedConfiguration.kt | 19 +-- 4 files changed, 77 insertions(+), 107 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt index d8a973b4758..8313bb7d9c3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MetadataDependencyTransformationTask.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.DefaultTask import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.work.NormalizeLineEndings import org.jetbrains.kotlin.gradle.dsl.kotlinExtension @@ -19,6 +20,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGU import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies +import org.jetbrains.kotlin.gradle.utils.filesProvider import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.gradle.utils.notCompatibleWithConfigurationCacheCompat import org.jetbrains.kotlin.gradle.utils.outputFilesProvider @@ -101,6 +103,37 @@ open class MetadataDependencyTransformationTask transformation.metadataDependencyResolutions } + @get:Internal + internal val transformedLibraries: Provider> = project.provider { + metadataDependencyResolutions.flatMap { resolution -> + val files: Iterable = when (resolution) { + is MetadataDependencyResolution.ChooseVisibleSourceSets -> when (val metadataProvider = resolution.metadataProvider) { + is MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ArtifactMetadataProvider -> metadataProvider.read { content -> + resolution.allVisibleSourceSetNames.mapNotNull { sourceSet -> + val metadataBinary = content.getSourceSet(sourceSet).metadataBinary ?: return@mapNotNull null + val outputBinaryFile = outputsDir.resolve(metadataBinary.relativeFile) + metadataBinary.copyTo(outputBinaryFile) + outputBinaryFile + } + } + is MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ProjectMetadataProvider -> { + resolution.allVisibleSourceSetNames.flatMap { sourceSet -> + metadataProvider.getSourceSetCompiledMetadata(sourceSet).files + } + } + } + is MetadataDependencyResolution.Exclude -> emptySet() + is MetadataDependencyResolution.KeepOriginalDependency -> transformation + .params + .resolvedMetadataConfiguration + .componentArtifacts(resolution.dependency) + .map { it.file } + } + + files + } + } + /** * Contains "actually transformed" metadata libraries (extracted from any [CompositeMetadataArtifact]) as well as * [FileCollection]s pointing to project dependency klibs. diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt index 06b47962f9a..3f77608fba6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmMetadataCompilationData.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider -import org.jetbrains.kotlin.gradle.targets.metadata.createMetadataDependencyTransformationClasspath import org.jetbrains.kotlin.gradle.targets.native.NativeCompilerOptions import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName @@ -59,18 +58,8 @@ internal abstract class GradleKpmAbstractFragmentMetadataCompilationData) { val project = compilation.target.project - /** See [createMetadataDependencyTransformationClasspath] and its usage. */ + /** See [configureMetadataDependenciesForCompilation] */ if (project.isKotlinGranularMetadataEnabled && compilation.name != KotlinCompilation.MAIN_COMPILATION_NAME) compilation.compileDependencyFiles = project.files() else @@ -333,7 +336,7 @@ class KotlinMetadataTargetConfigurator : val project = compilation.target.project val sourceSet = compilation.defaultSourceSet - project.registerTask( + val transformationTask = project.registerTask( transformGranularMetadataTaskName(compilation.name), listOf(sourceSet) ) { @@ -341,16 +344,37 @@ class KotlinMetadataTargetConfigurator : "Generates serialized dependencies metadata for compilation '${compilation.name}' of target '${compilation.target.name}' (for tooling)" } - compilation.compileDependencyFiles += createMetadataDependencyTransformationClasspath( - sourceSet.internal.resolvableMetadataConfiguration, - compilation - ) + val artifacts = sourceSet.internal.resolvableMetadataConfiguration.incoming.artifacts + + // Metadata from visible source sets within dependsOn closure + compilation.compileDependencyFiles += sourceSet.dependsOnClassesDirs + + // Requested dependencies that are not Multiplatform Libraries. for example stdlib-common + compilation.compileDependencyFiles += project.filesProvider { artifacts.filterNot { it.isMpp }.map { it.file } } + + // Transformed Multiplatform Libraries based on source set visibility + compilation.compileDependencyFiles += project.files(transformationTask.flatMap { it.transformedLibraries }) if (compilation is KotlinSharedNativeCompilation && sourceSet is DefaultKotlinSourceSet) { compilation.compileDependencyFiles += project.createCInteropMetadataDependencyClasspath(sourceSet) } } + private val ResolvedArtifactResult.isMpp: Boolean get() = variant.attributes.containsMultiplatformAttributes + + private val AttributeContainer.containsMultiplatformAttributes: Boolean get() = + keySet().any { it.name == KotlinPlatformType.attribute.name } + + private val KotlinSourceSet.dependsOnClassesDirs: FileCollection get() = project.filesProvider { + internal.dependsOnClosure.mapNotNull { hierarchySourceSet -> + val compilation = + project.getMetadataCompilationForSourceSet( + hierarchySourceSet + ) ?: return@mapNotNull null + compilation.output.classesDirs + } + } + private fun setupDependencyTransformationForSourceSet( project: Project, sourceSet: KotlinSourceSet @@ -386,36 +410,6 @@ class KotlinMetadataTargetConfigurator : } } - private fun createMetadataDependencyTransformationClasspath( - fromFiles: Configuration, - compilation: KotlinCompilation<*> - ): FileCollection { - val project = compilation.target.project - - val sourceSet = compilation.defaultSourceSet - - val dependsOnCompilationOutputs = lazy { - sourceSet.internal.withDependsOnClosure.mapNotNull { hierarchySourceSet -> - val dependencyCompilation = project.getMetadataCompilationForSourceSet(hierarchySourceSet) - dependencyCompilation?.output?.classesDirs.takeIf { hierarchySourceSet != sourceSet } - } - } - - val resolvedMetadataFilesProviders = lazy { - val transformationTaskHolders = sourceSet.internal.withDependsOnClosure.mapNotNull { hierarchySourceSet -> - project.locateTask(transformGranularMetadataTaskName(hierarchySourceSet.name)) - } - transformationTaskHolders.map { SourceSetResolvedMetadataProvider(it) } - } - - return createMetadataDependencyTransformationClasspath( - project, - fromFiles, - dependsOnCompilationOutputs, - resolvedMetadataFilesProviders - ) - } - private fun createCommonMainElementsConfiguration(target: KotlinMetadataTarget) { val project = target.project project.configurations.create(COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME).apply { @@ -465,57 +459,6 @@ internal interface ResolvedMetadataFilesProvider { val metadataFilesByResolution: Map } -internal fun createMetadataDependencyTransformationClasspath( - project: Project, - fromFiles: Configuration, - parentCompiledMetadataFiles: Lazy>, - metadataResolutionProviders: Lazy>, -): FileCollection { - return project.files( - Callable { - val allResolutionsByComponentId: Map> = - mutableMapOf>().apply { - metadataResolutionProviders.value.forEach { - it.metadataResolutions.forEach { resolution -> - getOrPut(resolution.dependency.id) { mutableListOf() }.add(resolution) - } - } - } - - val transformedFilesByResolution: Map = - metadataResolutionProviders.value.flatMap { it.metadataFilesByResolution.toList() }.toMap() - - val artifactView = fromFiles.incoming.artifactView { view -> - view.componentFilter { id -> - allResolutionsByComponentId[id].let { resolutions -> - resolutions == null || resolutions.any { it !is MetadataDependencyResolution.Exclude } - } - } - } - - mutableSetOf().apply { - addAll(metadataResolutionProviders.value.map { project.files().builtBy(it.buildDependencies) }) - addAll(parentCompiledMetadataFiles.value) - artifactView.artifacts.forEach { artifact -> - val resolutions = allResolutionsByComponentId[artifact.id.componentIdentifier] - if (resolutions == null) { - add(artifact.file) - } else { - val chooseVisibleSourceSets = resolutions.filterIsInstance() - - if (chooseVisibleSourceSets.isNotEmpty()) { - // Wrap the list into a FileCollection, as some older Gradle version failed to resolve the classpath - add(project.files(chooseVisibleSourceSets.map { transformedFilesByResolution.getValue(it) })) - } else if (resolutions.any { it is MetadataDependencyResolution.KeepOriginalDependency }) { - add(artifact.file) - } // else: all dependency transformations exclude this dependency as unrequested; don't add any files - } - } - } - } - ) -} - internal fun isNativeSourceSet(sourceSet: KotlinSourceSet): Boolean { val compilations = sourceSet.internal.compilations.filterNot { it.platformType == KotlinPlatformType.common } return compilations.isNotEmpty() && compilations.all { it.platformType == KotlinPlatformType.native } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt index 5028c7eb1a5..de748b4f8cc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt @@ -64,17 +64,22 @@ private constructor( * If you need to avoid such behavior see [moduleArtifacts] */ fun dependencyArtifacts(dependency: ResolvedDependencyResult): List { - fun ResolvedVariantResult.findNonExternalVariant(): ResolvedVariantResult = - if (externalVariant.isPresent) { - externalVariant.get().findNonExternalVariant() - } else { - this - } - val componentId = dependency.resolvedVariant.findNonExternalVariant().owner return artifactsByComponentId[componentId] ?: emptyList() } + fun componentArtifacts(component: ResolvedComponentResult): List { + val componentIds = component.variants.map { it.findNonExternalVariant().owner } + return componentIds.flatMap { artifactsByComponentId[it].orEmpty() } + } + + private fun ResolvedVariantResult.findNonExternalVariant(): ResolvedVariantResult = + if (externalVariant.isPresent) { + externalVariant.get().findNonExternalVariant() + } else { + this + } + /** * Returns own artifacts of a given dependency. * Acts in the same way as [org.gradle.api.artifacts.ResolvedDependency.getModuleArtifacts].