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) {
|
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 configurations = project.configurations
|
||||||
|
|
||||||
val defaultConfiguration = configurations.maybeCreate(target.defaultConfigurationName).apply {
|
|
||||||
setupAsLocalTargetSpecificConfigurationIfSupported(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME)
|
val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
val compileConfiguration = configurations.findByName(mainCompilation.deprecatedCompileConfigurationName)
|
val compileConfiguration = configurations.findByName(mainCompilation.deprecatedCompileConfigurationName)
|
||||||
val implementationConfiguration = configurations.maybeCreate(mainCompilation.implementationConfigurationName)
|
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."
|
description = "API elements for main."
|
||||||
isVisible = false
|
isVisible = false
|
||||||
isCanBeResolved = false
|
isCanBeResolved = false
|
||||||
isCanBeConsumed = true
|
isCanBeConsumed = true
|
||||||
attributes.attribute<Usage>(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||||
extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName))
|
extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName))
|
||||||
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
||||||
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
@@ -192,32 +191,34 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mainCompilation is KotlinCompilationToRunnableFiles<*>) {
|
if (mainCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
val runtimeElementsConfiguration = configurations.maybeCreate(target.runtimeElementsConfigurationName).apply {
|
configurations.maybeCreate(target.runtimeElementsConfigurationName).apply {
|
||||||
description = "Elements of runtime for main."
|
description = "Elements of runtime for main."
|
||||||
isVisible = false
|
isVisible = false
|
||||||
isCanBeConsumed = true
|
isCanBeConsumed = true
|
||||||
isCanBeResolved = false
|
isCanBeResolved = false
|
||||||
attributes.attribute<Usage>(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target))
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target))
|
||||||
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
extendsFrom(implementationConfiguration, runtimeOnlyConfiguration)
|
extendsFrom(implementationConfiguration)
|
||||||
|
if (runtimeOnlyConfiguration != null)
|
||||||
|
extendsFrom(runtimeOnlyConfiguration)
|
||||||
runtimeConfiguration?.let { extendsFrom(it) }
|
runtimeConfiguration?.let { extendsFrom(it) }
|
||||||
usesPlatformOf(target)
|
usesPlatformOf(target)
|
||||||
setupAsPublicConfigurationIfSupported(target)
|
setupAsPublicConfigurationIfSupported(target)
|
||||||
}
|
}
|
||||||
defaultConfiguration.extendsFrom(runtimeElementsConfiguration)
|
|
||||||
} else {
|
|
||||||
defaultConfiguration.extendsFrom(apiElementsConfiguration)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createTestCompilation) {
|
if (createTestCompilation) {
|
||||||
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
|
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||||
val compileTestsConfiguration = configurations.findByName(testCompilation.deprecatedCompileConfigurationName)
|
val compileTestsConfiguration = configurations.findByName(testCompilation.deprecatedCompileConfigurationName)
|
||||||
val testImplementationConfiguration = configurations.maybeCreate(testCompilation.implementationConfigurationName)
|
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) }
|
compileConfiguration?.let { compileTestsConfiguration?.extendsFrom(it) }
|
||||||
testImplementationConfiguration.extendsFrom(implementationConfiguration)
|
testImplementationConfiguration.extendsFrom(implementationConfiguration)
|
||||||
testRuntimeOnlyConfiguration.extendsFrom(runtimeOnlyConfiguration)
|
testRuntimeOnlyConfiguration?.extendsFrom(runtimeOnlyConfiguration)
|
||||||
|
|
||||||
if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) {
|
if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) {
|
||||||
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
val runtimeConfiguration = configurations.findByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
|||||||
+1
@@ -448,6 +448,7 @@ class KotlinMetadataTargetConfigurator :
|
|||||||
project.configurations.create(COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME).apply {
|
project.configurations.create(COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME).apply {
|
||||||
isCanBeConsumed = true
|
isCanBeConsumed = true
|
||||||
isCanBeResolved = false
|
isCanBeResolved = false
|
||||||
|
setupAsPublicConfigurationIfSupported(target)
|
||||||
usesPlatformOf(target)
|
usesPlatformOf(target)
|
||||||
|
|
||||||
attributes.attribute(
|
attributes.attribute(
|
||||||
|
|||||||
Reference in New Issue
Block a user