[Gradle] Migrate disabled cinterops commonization warning

This commit is contained in:
Dmitry Savvinov
2023-04-19 17:36:28 +02:00
parent 63f61685c0
commit 5a9aa43aa5
6 changed files with 94 additions and 104 deletions
@@ -1,84 +0,0 @@
/*
* Copyright 2010-2021 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.plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerDependent
import org.jetbrains.kotlin.gradle.targets.native.internal.from
import org.jetbrains.kotlin.gradle.targets.native.internal.isAllowCommonizer
import org.jetbrains.kotlin.gradle.utils.findAppliedAndroidPluginIdOrNull
import org.jetbrains.kotlin.gradle.utils.future
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheck
private class KotlinMultiplatformProjectConfigurationException(message: String) : Exception(message)
internal fun Project.runMissingKotlinTargetsProjectConfigurationHealthCheck() = project.runProjectConfigurationHealthCheck {
val isNoTargetsInitialized = (project.kotlinExtension as KotlinMultiplatformExtension)
.targets
.none { it !is KotlinMetadataTarget }
if (isNoTargetsInitialized) {
throw KotlinMultiplatformProjectConfigurationException(
"""
Please initialize at least one Kotlin target in '${project.name} (${project.path})'.
Read more https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets
""".trimIndent()
)
}
}
internal fun Project.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck(
warningLogger: (warningMessage: String) -> Unit = project.logger::warn
) {
if (kotlinPropertiesProvider.ignoreDisabledCInteropCommonization) return
if (isAllowCommonizer() && !kotlinPropertiesProvider.enableCInteropCommonization) {
val multiplatformExtension = multiplatformExtensionOrNull ?: return
val sharedCompilationsWithInterops = multiplatformExtension.targets.flatMap { it.compilations }
.filterIsInstance<KotlinSharedNativeCompilation>()
.mapNotNull { compilation ->
val cinteropDependent = future { CInteropCommonizerDependent.from(compilation) }.getOrThrow() ?: return@mapNotNull null
compilation to cinteropDependent
}
.toMap()
val affectedCompilations = sharedCompilationsWithInterops.keys
val affectedCInterops = sharedCompilationsWithInterops.values.flatMap { it.interops }.toSet()
/* CInterop commonizer would not affect the project: No compilation that would actually benefit */
if (affectedCompilations.isEmpty()) return
if (affectedCInterops.isEmpty()) return
warningLogger(
"""
[WARNING] The project is using Kotlin Multiplatform with hierarchical structure and disabled 'cinterop commonization'
See: https://kotlinlang.org/docs/mpp-share-on-platforms.html#use-native-libraries-in-the-hierarchical-structure
'cinterop commonization' can be enabled in your 'gradle.properties'
kotlin.mpp.enableCInteropCommonization=true
To hide this message, add to your 'gradle.properties'
$KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION.nowarn=true
The following source sets are affected:
${affectedCompilations.map { it.defaultSourceSetName }.sorted().joinToString(", ", "[", "]")}
The following cinterops are affected:
${affectedCInterops.map { it.toString() }.sorted().joinToString(", ", "[", "]")}
""".trimIndent()
)
}
}
@@ -385,10 +385,6 @@ abstract class AbstractKotlinMultiplatformPluginWrapper : KotlinBasePluginWrappe
override val projectExtensionClass: KClass<out KotlinMultiplatformExtension>
get() = KotlinMultiplatformExtension::class
override fun whenBuildEvaluated(project: Project) {
project.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck()
}
}
abstract class AbstractKotlinPm20PluginWrapper(
@@ -101,7 +101,8 @@ internal interface KotlinGradleProjectChecker {
AndroidSourceSetLayoutV1SourceSetsNotFoundChecker,
TargetsWithAmbiguousConsumableConfigurationsChecker,
AndroidPluginWithoutAndroidTargetChecker,
NoKotlinTargetsDeclaredChecker
NoKotlinTargetsDeclaredChecker,
DisabledCinteropCommonizationInHmppProjectChecker
)
}
}
@@ -213,7 +213,7 @@ object KotlinToolingDiagnostics {
object Kotlin12XMppDeprecation : ToolingDiagnosticFactory(WARNING) {
operator fun invoke() = build(
"""
The 'org.jetbrains.kotlin.platform.*' plugins are deprecated and will no longer be available in Kotlin 1.4.
The 'org.jetbrains.kotlin.platform.*' plugins are deprecated and are no longer available since Kotlin 1.4.
Please migrate the project to the 'org.jetbrains.kotlin.multiplatform' plugin.
See: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html
""".trimIndent()
@@ -248,4 +248,25 @@ object KotlinToolingDiagnostics {
""".trimIndent()
)
}
object DisabledCinteropsCommonizationInHmppProject : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(affectedSourceSetsString: String, affectedCinteropsString: String) = build(
"""
The project is using Kotlin Multiplatform with hierarchical structure and disabled 'cinterop commonization'
See: https://kotlinlang.org/docs/mpp-share-on-platforms.html#use-native-libraries-in-the-hierarchical-structure
'cinterop commonization' can be enabled in your 'gradle.properties'
kotlin.mpp.enableCInteropCommonization=true
To hide this message, add to your 'gradle.properties'
${PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION}.nowarn=true
The following source sets are affected:
$affectedSourceSetsString
The following cinterops are affected:
$affectedCinteropsString
""".trimIndent()
)
}
}
@@ -0,0 +1,54 @@
/*
* 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.plugin.diagnostics.checkers
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.await
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerDependent
import org.jetbrains.kotlin.gradle.targets.native.internal.from
import org.jetbrains.kotlin.gradle.targets.native.internal.isAllowCommonizer
internal object DisabledCinteropCommonizationInHmppProjectChecker : KotlinGradleProjectChecker {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
// `isAllowCommonizer` is not lifecycle-aware, but requires afterEvaluate-phase, so have to await manually
KotlinPluginLifecycle.Stage.ReadyForExecution.await()
if (multiplatformExtension == null
|| !project.isAllowCommonizer()
|| kotlinPropertiesProvider.enableCInteropCommonization
|| kotlinPropertiesProvider.ignoreDisabledCInteropCommonization
) return
val sharedCompilationsWithInterops = multiplatformExtension.awaitTargets()
.flatMap { it.compilations }
.filterIsInstance<KotlinSharedNativeCompilation>()
.mapNotNull { compilation ->
val cinteropDependent = CInteropCommonizerDependent.from(compilation) ?: return@mapNotNull null
compilation to cinteropDependent
}
.toMap()
val affectedCompilations = sharedCompilationsWithInterops.keys
val affectedCInterops = sharedCompilationsWithInterops.values.flatMap { it.interops }.toSet()
/* CInterop commonizer would not affect the project: No compilation that would actually benefit */
if (affectedCompilations.isEmpty()) return
if (affectedCInterops.isEmpty()) return
val affectedSourceSetsString = affectedCompilations.map { it.defaultSourceSet.name }.sorted().joinToString(", ", "[", "]")
val affectedCinteropsString = affectedCInterops.map { it.toString() }.sorted().joinToString(", ", "[", "]")
collector.reportOncePerGradleProject(
project,
KotlinToolingDiagnostics.DisabledCinteropsCommonizationInHmppProject(affectedSourceSetsString, affectedCinteropsString)
)
}
}
@@ -11,16 +11,14 @@ import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck
import org.jetbrains.kotlin.gradle.util.applyMultiplatformPlugin
import org.jetbrains.kotlin.gradle.util.enableCInteropCommonization
import org.jetbrains.kotlin.gradle.util.enableHierarchicalStructureByDefault
import org.jetbrains.kotlin.gradle.util.propertiesExtension
import kotlin.test.Test
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
import kotlin.test.*
class DisabledCInteropCommonizationWarningTest {
@@ -32,7 +30,7 @@ class DisabledCInteropCommonizationWarningTest {
project.setupNativeTargetsWithCInterops()
project.evaluate()
val warningMessage = project.runHealthCheckAndGetWarning()
val warningMessage = project.getWarningMessage()
assertNotNull(warningMessage, "Expected a warning message to be logged")
@@ -65,7 +63,7 @@ class DisabledCInteropCommonizationWarningTest {
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
project.getWarningMessage(),
"Expected no warning message shown when explicitly ignored"
)
}
@@ -76,7 +74,7 @@ class DisabledCInteropCommonizationWarningTest {
project.setupNativeTargetsWithCInterops()
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
project.getWarningMessage(),
"Expected no error message shown when cinterop commonization is enabled"
)
}
@@ -88,7 +86,7 @@ class DisabledCInteropCommonizationWarningTest {
project.setupNativeTargetsWithCInterops()
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
project.getWarningMessage(),
"Expected no error message shown when hmpp is disabled"
)
}
@@ -99,7 +97,7 @@ class DisabledCInteropCommonizationWarningTest {
project.setupNativeTargets()
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
project.getWarningMessage(),
"Expected no error message shown when no cinterops are defined"
)
}
@@ -129,8 +127,12 @@ private fun Project.setupNativeTargetsWithCInterops(): List<KotlinNativeTarget>
}
}
private fun Project.runHealthCheckAndGetWarning(): String? {
var message: String? = null
runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck { message = it }
return message
private fun Project.getWarningMessage(): String? {
val diagnostics = project.kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(this).filter {
it.id == KotlinToolingDiagnostics.DisabledCinteropsCommonizationInHmppProject.id
}
if (diagnostics.size > 1) fail("Unexpected multiple diagnostics reported:\n\n" + diagnostics.joinToString(separator = "\n\n"))
return diagnostics.singleOrNull()?.message
}