From 380ca95661f7a2e5fc2c5c859dda58da3ed28262 Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Tue, 7 Feb 2023 11:01:13 +0100 Subject: [PATCH] [Gradle] resolvableMetadataConfiguration: Ensure consistent resolution across all compile dependencies ^KT-56461 Verification Pending ^KT-56431 Verification Pending --- .../mpp/resolvableMetadataConfiguration.kt | 29 +++++--- .../KotlinMetadataTargetConfigurator.kt | 14 ---- .../ResolvableMetadataConfigurationTest.kt | 68 +++++++++++++++++++ 3 files changed, 87 insertions(+), 24 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/ResolvableMetadataConfigurationTest.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resolvableMetadataConfiguration.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resolvableMetadataConfiguration.kt index ed4af8d8bd9..f9146c7e9c9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resolvableMetadataConfiguration.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resolvableMetadataConfiguration.kt @@ -10,14 +10,14 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.categoryByName import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes -import org.jetbrains.kotlin.gradle.utils.markResolvable +import org.jetbrains.kotlin.gradle.plugin.sources.* import org.jetbrains.kotlin.gradle.plugin.sources.InternalKotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.sources.METADATA_CONFIGURATION_NAME_SUFFIX import org.jetbrains.kotlin.gradle.plugin.sources.disambiguateName -import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations +import org.jetbrains.kotlin.gradle.utils.markResolvable import org.jetbrains.kotlin.gradle.plugin.usageByName import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf import org.jetbrains.kotlin.gradle.utils.getOrCreate @@ -71,14 +71,23 @@ internal val InternalKotlinSourceSet.resolvableMetadataConfiguration: Configurat configuration } -internal val Project.allCompileMetadataConfiguration get(): Configuration = - configurations.getOrCreate("allSourceSetsCompileDependenciesMetadata", invokeWhenCreated = { - it.markResolvable() +/** + * Configuration containing all compile dependencies from *all* source sets. + * This configuration is used to provide a dependency 'consistency scope' for + * the [InternalKotlinSourceSet.resolvableMetadataConfiguration] + */ +private val Project.allCompileMetadataConfiguration + get(): Configuration = configurations.getOrCreate("allSourceSetsCompileDependenciesMetadata", invokeWhenCreated = { configuration -> + configuration.markResolvable() + configuration.usesPlatformOf(multiplatformExtension.metadata()) + configuration.attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA)) + configuration.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) - val metadataTarget = multiplatformExtension.metadata() - it.usesPlatformOf(metadataTarget) - it.attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA)) - it.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) + kotlinExtension.sourceSets.all { sourceSet -> + configuration.extendsFrom(configurations.getByName(sourceSet.apiConfigurationName)) + configuration.extendsFrom(configurations.getByName(sourceSet.implementationConfigurationName)) + configuration.extendsFrom(configurations.getByName(sourceSet.compileOnlyConfigurationName)) + } }) private inline fun Project.listProvider(noinline provider: () -> List): Provider> { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt index fc6233c6f29..06708c0094c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt @@ -30,7 +30,6 @@ import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadataElements" -internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompileDependenciesMetadata" internal val Project.isKotlinGranularMetadataEnabled: Boolean get() = project.pm20ExtensionOrNull != null || with(PropertiesProvider(this)) { @@ -81,7 +80,6 @@ class KotlinMetadataTargetConfigurator : compileKotlinTaskProvider.configure { it.onlyIf { isCompatibilityMetadataVariantEnabled } } } - createAllCompileMetadataConfiguration(target) val allMetadataJar = target.project.tasks.withType().named(ALL_METADATA_JAR_NAME) createMetadataCompilationsForCommonSourceSets(target, allMetadataJar) @@ -272,18 +270,6 @@ class KotlinMetadataTargetConfigurator : } } - private fun createAllCompileMetadataConfiguration(target: KotlinMetadataTarget) { - val project = target.project - project.configurations.create(ALL_COMPILE_METADATA_CONFIGURATION_NAME).apply { - isCanBeConsumed = false - isCanBeResolved = true - - usesPlatformOf(target) - attributes.attribute(USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA)) - attributes.attribute(CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) - } - } - private fun createMetadataCompilation( target: KotlinMetadataTarget, sourceSet: KotlinSourceSet, diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/ResolvableMetadataConfigurationTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/ResolvableMetadataConfigurationTest.kt new file mode 100644 index 00000000000..7c0ce1f5c35 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/ResolvableMetadataConfigurationTest.kt @@ -0,0 +1,68 @@ +/* + * 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. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.gradle.dependencyResolutionTests + +import org.gradle.api.artifacts.component.ModuleComponentIdentifier +import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.mpp.resolvableMetadataConfiguration +import org.jetbrains.kotlin.gradle.plugin.sources.internal +import org.jetbrains.kotlin.gradle.util.applyMultiplatformPlugin +import org.jetbrains.kotlin.gradle.util.buildProject +import org.jetbrains.kotlin.gradle.util.enableDefaultStdlibDependency +import org.jetbrains.kotlin.gradle.util.enableDependencyVerification +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.fail + +class ResolvableMetadataConfigurationTest { + + @Test + fun `test - resolves consistent in project`() { + val project = buildProject { + enableDefaultStdlibDependency(false) + enableDependencyVerification(false) + applyMultiplatformPlugin() + repositories.mavenCentralCacheRedirector() + } + + val kotlin = project.multiplatformExtension + + /* Define simple targets */ + kotlin.jvm() + kotlin.linuxArm64() + kotlin.linuxX64() + kotlin.targetHierarchy.default() + + val commonMain = kotlin.sourceSets.getByName("commonMain") + val nativeMain = kotlin.sourceSets.getByName("nativeMain") + + commonMain.dependencies { + implementation("com.squareup.okio:okio:3.2.0") + } + + /* nativeMain explicitly using 3.3.0 (higher than 3.2.0 in commonMain) */ + nativeMain.dependencies { + implementation("com.squareup.okio:okio:3.3.0") + } + + kotlin.sourceSets.forEach { sourceSet -> + sourceSet.internal.resolvableMetadataConfiguration.incoming.resolutionResult.allDependencies + .mapNotNull { result -> if (result is ResolvedDependencyResult) result.selected.id else null } + .filterIsInstance() + .filter { id -> id.group == "com.squareup.okio" } + .ifEmpty { fail("Expected at least one okio dependency resolved") } + .forEach { resolvedId -> + assertEquals( + "3.3.0", resolvedId.version, + "SourceSet: ${sourceSet.name} resolved $resolvedId, but expected consistent version 3.3.0" + ) + } + } + } +}