[Gradle] Report warning when targets are not distinguishable

^KT-55751 Verification Pending
This commit is contained in:
Anton Lakotka
2023-02-20 15:47:09 +01:00
committed by Space Team
parent 58959951d3
commit b9f0ad0e58
3 changed files with 94 additions and 0 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.mpp
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.replaceText
import kotlin.io.path.appendText
import kotlin.io.path.writeText
import kotlin.test.assertFalse
@@ -50,6 +51,45 @@ class MppDiagnosticsIt : KGPBaseTest() {
}
}
@GradleTest
fun testReportTargetsOfTheSamplePlatformAndWithTheSameAttributes(gradleVersion: GradleVersion) {
project("new-mpp-lib-and-app/sample-lib-gradle-kotlin-dsl", gradleVersion) {
// A hack to make project compatible with GradleTestKit infrastructure
buildGradleKts.replaceText(
"""id("org.jetbrains.kotlin.multiplatform").version("<pluginMarkerVersion>")""",
"""id("org.jetbrains.kotlin.multiplatform")""",
)
buildGradleKts.appendText("""
val distinguishAttribute = Attribute.of(String::class.java)
fun org.jetbrains.kotlin.gradle.plugin.KotlinTarget.applyDistinguishingAttributeIfSet(value: String) {
if (project.properties.containsKey("applyDistinguishingAttribute")) {
attributes {
attribute(distinguishAttribute, value)
}
}
}
kotlin {
jvm("jvm2") { applyDistinguishingAttributeIfSet("jvm2") }
linuxArm64("linuxArm_A") { applyDistinguishingAttributeIfSet("linuxArm_A") }
linuxArm64("linuxArm_B") { applyDistinguishingAttributeIfSet("linuxArm_B") }
}
""".trimIndent())
val warningMessage = """w: The following targets are not distinguishable:
| * 'jvm2', 'jvm6'
| * 'linuxArm_A', 'linuxArm_B'""".trimMargin()
build {
assertOutputContains(warningMessage)
}
build(buildOptions = defaultBuildOptions.copy(freeArgs = listOf("-PapplyDistinguishingAttribute"))) {
assertOutputDoesNotContain(warningMessage)
}
}
}
private fun TestProject.checkDeprecatedProperties(isDeprecationExpected: Boolean) {
build {
val assert: (Boolean, String) -> Unit = if (isDeprecationExpected) ::assertTrue else ::assertFalse
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet.Companion.COMMON_MAIN_SOURCE_SET_NAME
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheckWhenEvaluated
import org.jetbrains.kotlin.gradle.utils.toMap
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.tooling.core.UnsafeApi
@@ -28,6 +30,7 @@ internal fun runDeprecationDiagnostics(project: Project) {
checkAndReportDeprecatedSourceSetsLayouts(project)
project.runProjectConfigurationHealthCheckWhenEvaluated {
checkAndReportDeprecatedNativeTargets(project)
reportTargetsWithNonUniqueConsumableConfigurations(project)
}
}
@@ -41,6 +44,35 @@ private fun checkAndReportDeprecatedNativeTargets(project: Project) {
)
}
/**
* Report scenario when there are two targets of the same platform without distinguishing attribute
*/
private fun reportTargetsWithNonUniqueConsumableConfigurations(project: Project) {
// Wrap diagnostic check again to afterEvaluate to make sure that it gets executed the last
// Since Multiplatform plugin updates consumable configurations in afterEvaluate blocks
project.afterEvaluate {
val allTargets = project.multiplatformExtension.targets
val nonDistinguishableTargets = allTargets
.groupBy { target -> project.configurations.getByName(target.apiElementsConfigurationName).attributes.toMap() }
.values
.filter { targetGroup -> targetGroup.size > 1 }
if (nonDistinguishableTargets.isEmpty()) return@afterEvaluate
val nonUniqueTargetsString = nonDistinguishableTargets.joinToString(separator = "\n") { targets ->
val targetsListString = targets.joinToString { "'${it.name}'" }
" * $targetsListString"
}
SingleWarningPerBuild.show(
project,"w: The following targets are not distinguishable:\n$nonUniqueTargetsString" +
"\nUse distinguish attribute. " +
"See https://kotlinlang.org/docs/multiplatform-set-up-targets.html#distinguish-several-targets-for-one-platform for more details."
)
}
}
/**
* Declared properties have to be captured during plugin application phase before the HMPP migration util sets them.
* Warnings have to be reported only for successfully evaluated projects without errors.
@@ -0,0 +1,22 @@
/*
* 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.
*/
package org.jetbrains.kotlin.gradle.utils
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
/**
* KGP's internal analog of [org.gradle.api.internal.attributes.AttributeContainerInternal.asMap]
* Can be used to compare attributes
*/
internal fun AttributeContainer.toMap(): Map<Attribute<*>, Any?> {
val result = mutableMapOf<Attribute<*>, Any?>()
for (key in keySet()) {
result[key] = getAttribute(key)
}
return result
}