Cleanup configuration to fix corner cases in HMPP dependency resolution
* Set the local-to-project attribute on the compatibility metadata variant's "elements" configuration; not setting this attribute could lead to ambiguity because of diverging sets of non-matched attributes * Don't create the `runtimeOnly` configuration for the Kotlin/Native targets (or potentially other targets with no runtime dependencies), as the K/N target configurator is not aware of the configuration and would not set the configuration up properly * Don't create the legacy `*Default` configurations, as they basically duplicate the `*ApiElements` / `*RuntimeElements` configurations but don't have all the right attributes, so they are reckoned compatible with some consumers unnecessarily and pollute the dependency resolution error reports. Issue #KT-47506
This commit is contained in:
+34
@@ -346,6 +346,40 @@ class VariantAwareDependenciesIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResolveCompatibilityMetadataVariantWithNative() = with(Project("native-libraries")) {
|
||||
setupWorkingDir()
|
||||
val nestedProjectName = "nested"
|
||||
embedProject(Project("native-libraries"), nestedProjectName)
|
||||
|
||||
projectDir.resolve("gradle.properties").appendText(
|
||||
"\n" + """
|
||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||
kotlin.mpp.enableCompatibilityMetadataVariant=true
|
||||
"""
|
||||
)
|
||||
|
||||
val resolveConfigurationTaskName = "resolveConfiguration"
|
||||
val marker = "###=>"
|
||||
|
||||
gradleBuildScript().appendText(
|
||||
"\n" + """
|
||||
dependencies { "commonMainImplementation"(project(":$nestedProjectName")) }
|
||||
tasks.create("$resolveConfigurationTaskName") {
|
||||
doFirst {
|
||||
println("$marker" + configurations.getByName("metadataCompileClasspath").toList())
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
build(resolveConfigurationTaskName) {
|
||||
assertSuccessful()
|
||||
val output = output.lines().single { marker in it }.substringAfter(marker).removeSurrounding("[", "]").split(",")
|
||||
assertTrue { output.any { "$nestedProjectName-1.0.jar" in it } }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun BaseGradleIT.Project.embedProject(other: BaseGradleIT.Project, renameTo: String? = null) {
|
||||
|
||||
+16
-15
@@ -165,23 +165,22 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
||||
|
||||
val configurations = project.configurations
|
||||
|
||||
val defaultConfiguration = configurations.maybeCreate(target.defaultConfigurationName).apply {
|
||||
setupAsLocalTargetSpecificConfigurationIfSupported(target)
|
||||
}
|
||||
|
||||
val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
|
||||
val compileConfiguration = configurations.findByName(mainCompilation.deprecatedCompileConfigurationName)
|
||||
val implementationConfiguration = configurations.maybeCreate(mainCompilation.implementationConfigurationName)
|
||||
|
||||
val runtimeOnlyConfiguration = configurations.maybeCreate(mainCompilation.runtimeOnlyConfigurationName)
|
||||
val runtimeOnlyConfiguration = when (mainCompilation) {
|
||||
is KotlinCompilationToRunnableFiles<*> -> configurations.maybeCreate(mainCompilation.runtimeOnlyConfigurationName)
|
||||
else -> null
|
||||
}
|
||||
|
||||
val apiElementsConfiguration = configurations.maybeCreate(target.apiElementsConfigurationName).apply {
|
||||
configurations.maybeCreate(target.apiElementsConfigurationName).apply {
|
||||
description = "API elements for main."
|
||||
isVisible = false
|
||||
isCanBeResolved = false
|
||||
isCanBeConsumed = true
|
||||
attributes.attribute<Usage>(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||
extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName))
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
@@ -192,32 +191,34 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
||||
}
|
||||
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||
val runtimeElementsConfiguration = configurations.maybeCreate(target.runtimeElementsConfigurationName).apply {
|
||||
configurations.maybeCreate(target.runtimeElementsConfigurationName).apply {
|
||||
description = "Elements of runtime for main."
|
||||
isVisible = false
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
attributes.attribute<Usage>(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target))
|
||||
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target))
|
||||
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
extendsFrom(implementationConfiguration, runtimeOnlyConfiguration)
|
||||
extendsFrom(implementationConfiguration)
|
||||
if (runtimeOnlyConfiguration != null)
|
||||
extendsFrom(runtimeOnlyConfiguration)
|
||||
runtimeConfiguration?.let { extendsFrom(it) }
|
||||
usesPlatformOf(target)
|
||||
setupAsPublicConfigurationIfSupported(target)
|
||||
}
|
||||
defaultConfiguration.extendsFrom(runtimeElementsConfiguration)
|
||||
} else {
|
||||
defaultConfiguration.extendsFrom(apiElementsConfiguration)
|
||||
}
|
||||
|
||||
if (createTestCompilation) {
|
||||
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||
val compileTestsConfiguration = configurations.findByName(testCompilation.deprecatedCompileConfigurationName)
|
||||
val testImplementationConfiguration = configurations.maybeCreate(testCompilation.implementationConfigurationName)
|
||||
val testRuntimeOnlyConfiguration = configurations.maybeCreate(testCompilation.runtimeOnlyConfigurationName)
|
||||
val testRuntimeOnlyConfiguration = when (testCompilation) {
|
||||
is KotlinCompilationToRunnableFiles<*> -> configurations.maybeCreate(testCompilation.runtimeOnlyConfigurationName)
|
||||
else -> null
|
||||
}
|
||||
|
||||
compileConfiguration?.let { compileTestsConfiguration?.extendsFrom(it) }
|
||||
testImplementationConfiguration.extendsFrom(implementationConfiguration)
|
||||
testRuntimeOnlyConfiguration.extendsFrom(runtimeOnlyConfiguration)
|
||||
testRuntimeOnlyConfiguration?.extendsFrom(runtimeOnlyConfiguration)
|
||||
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) {
|
||||
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||
|
||||
+1
@@ -448,6 +448,7 @@ class KotlinMetadataTargetConfigurator :
|
||||
project.configurations.create(COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME).apply {
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
setupAsPublicConfigurationIfSupported(target)
|
||||
usesPlatformOf(target)
|
||||
|
||||
attributes.attribute(
|
||||
|
||||
Reference in New Issue
Block a user