[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
This commit is contained in:
Anton Lakotka
2023-01-12 12:15:37 +01:00
committed by Space Team
parent 72f8c8399d
commit 4941e8b7de
4 changed files with 77 additions and 107 deletions
@@ -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<Iterable<File>> = project.provider {
metadataDependencyResolutions.flatMap { resolution ->
val files: Iterable<File> = 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.
@@ -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<T : Kot
get() = compileAllTask.name
override var compileDependencyFiles: FileCollection by project.newProperty {
createMetadataDependencyTransformationClasspath(
project = project,
fromFiles = resolvableMetadataConfiguration(fragment.containingModule),
parentCompiledMetadataFiles = lazy {
fragment.refinesClosure.map {
val compilation = metadataCompilationRegistry.getForFragmentOrNull(it)
?: return@map project.files()
compilation.output.classesDirs
}
},
metadataResolutionProviders = resolvedMetadataFiles
)
TODO("""Provide Compile Dependency Files.
| See KotlinMetadataTargetConfigurator::configureMetadataDependenciesForCompilation for reference""".trimMargin())
}
override val output: KotlinCompilationOutput = DefaultKotlinCompilationOutput(
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.gradle.targets.metadata
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.component.ComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedArtifactResult
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE
import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE
@@ -25,6 +27,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.*
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.targets.native.internal.*
import org.jetbrains.kotlin.gradle.tasks.*
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
import java.util.concurrent.Callable
@@ -105,7 +108,7 @@ class KotlinMetadataTargetConfigurator :
override fun setupCompilationDependencyFiles(compilation: KotlinCompilation<KotlinCommonOptions>) {
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<MetadataDependencyTransformationTask>(
val transformationTask = project.registerTask<MetadataDependencyTransformationTask>(
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<MetadataDependencyTransformationTask>(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<out MetadataDependencyResolution, FileCollection>
}
internal fun createMetadataDependencyTransformationClasspath(
project: Project,
fromFiles: Configuration,
parentCompiledMetadataFiles: Lazy<Iterable<FileCollection>>,
metadataResolutionProviders: Lazy<Iterable<ResolvedMetadataFilesProvider>>,
): FileCollection {
return project.files(
Callable {
val allResolutionsByComponentId: Map<ComponentIdentifier, List<MetadataDependencyResolution>> =
mutableMapOf<ComponentIdentifier, MutableList<MetadataDependencyResolution>>().apply {
metadataResolutionProviders.value.forEach {
it.metadataResolutions.forEach { resolution ->
getOrPut(resolution.dependency.id) { mutableListOf() }.add(resolution)
}
}
}
val transformedFilesByResolution: Map<MetadataDependencyResolution, FileCollection> =
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<Any /* File | FileCollection */>().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<MetadataDependencyResolution.ChooseVisibleSourceSets>()
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 }
@@ -64,17 +64,22 @@ private constructor(
* If you need to avoid such behavior see [moduleArtifacts]
*/
fun dependencyArtifacts(dependency: ResolvedDependencyResult): List<ResolvedArtifactResult> {
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<ResolvedArtifactResult> {
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].