[Gradle][MPP] Show (potential) warning on disabled cinterop commonization

^KT-51176 Verification Pending
This commit is contained in:
sebastian.sellmair
2022-02-07 17:09:49 +01:00
parent 42010282d5
commit 56de13fe2f
5 changed files with 166 additions and 3 deletions
@@ -0,0 +1,122 @@
/*
* Copyright 2010-2022 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
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.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck
import kotlin.test.Test
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
class DisabledCInteropCommonizationWarningTest {
private val project by lazy { ProjectBuilder.builder().build() as ProjectInternal }
@Test
fun `test warning shows affected source sets and compilations`() {
project.enableCInteropCommonization(false)
project.setupNativeTargetsWithCInterops()
project.evaluate()
val warningMessage = project.runHealthCheckAndGetWarning()
assertNotNull(warningMessage, "Expected a warning message to be logged")
assertTrue(
"[commonMain, nativeMain]" in warningMessage,
"Expected source sets being mentioned in the warning message. Found\n\n$warningMessage"
)
assertTrue(
"[metadata/commonMain, metadata/nativeMain]" in warningMessage,
"Expected compilations being mentioned in the warning message. Found\n\n$warningMessage"
)
}
@Test
fun `test warning is not shown when explicitly ignored`() {
project.enableCInteropCommonization(false)
project.setupNativeTargetsWithCInterops()
project.propertiesExtension.set("$KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION.nowarn", "true")
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
"Expected no warning message shown when explictily ignored"
)
}
@Test
fun `test warning is not shown when cinterop commonization is enabled`() {
project.enableCInteropCommonization(true)
project.setupNativeTargetsWithCInterops()
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
"Expected no error message shown when cinterop commonization is enabled"
)
}
@Test
fun `test warning is not shown when hierarchical structure is disabled`() {
project.enableCInteropCommonization(false)
project.enableHierarchicalStructureByDefault(false)
project.setupNativeTargetsWithCInterops()
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
"Expected no error message shown when hmpp is disabled"
)
}
@Test
fun `test warning is not shown when no cinterops are defined`() {
project.enableCInteropCommonization(false)
project.setupNativeTargets()
project.evaluate()
assertNull(
project.runHealthCheckAndGetWarning(),
"Expected no error message shown when no cinterops are defined"
)
}
}
private fun Project.setupNativeTargets(): List<KotlinNativeTarget> {
val kotlin = applyMultiplatformPlugin()
val linuxX64 = kotlin.linuxX64()
val linuxArm64 = kotlin.linuxArm64()
val commonMain = kotlin.sourceSets.getByName("commonMain")
val nativeMain = kotlin.sourceSets.create("nativeMain")
val linuxX64Main = kotlin.sourceSets.getByName("linuxX64Main")
val linuxArm64Main = kotlin.sourceSets.getByName("linuxArm64Main")
nativeMain.dependsOn(commonMain)
linuxX64Main.dependsOn(nativeMain)
linuxArm64Main.dependsOn(nativeMain)
return listOf(linuxX64, linuxArm64)
}
private fun Project.setupNativeTargetsWithCInterops(): List<KotlinNativeTarget> {
return setupNativeTargets().onEach { target ->
target.compilations.getByName("main").cinterops.create("dummy1")
target.compilations.getByName("main").cinterops.create("dummy2")
}
}
private fun Project.runHealthCheckAndGetWarning(): String? {
var message: String? = null
runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck { message = it }
return message
}
@@ -98,6 +98,6 @@ fun Project.enableCInteropCommonization(enabled: Boolean = true) {
propertiesExtension.set(KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION, enabled.toString())
}
fun Project.enableHierarchicalStructureByDefault() {
propertiesExtension.set(KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT, "true")
fun Project.enableHierarchicalStructureByDefault(enabled: Boolean = true) {
propertiesExtension.set(KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT, enabled.toString())
}
@@ -8,9 +8,14 @@ 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.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.androidPluginIds
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheck
@@ -62,3 +67,35 @@ internal fun Project.runMissingAndroidTargetProjectConfigurationHealthCheck(
""".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 affectedCompilations = multiplatformExtension.targets.flatMap { it.compilations }
.filterIsInstance<KotlinSharedNativeCompilation>()
.filter { compilation -> CInteropCommonizerDependent.from(compilation)?.interops.orEmpty().isNotEmpty() }
/* CInterop commonizer would not affect the project: No compilation that would actually benefit */
if (affectedCompilations.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
The following source sets are affected:
${affectedCompilations.map { it.defaultSourceSetName }.sorted().joinToString(", ", "[", "]")}
The following compilations are affected:
${affectedCompilations.map { "${it.target.name}/${it.compilationName}" }.sorted().joinToString(", ", "[", "]")}
""".trimIndent()
)
}
}
@@ -250,6 +250,7 @@ open class KotlinMultiplatformPluginWrapper : KotlinBasePluginWrapper() {
override fun whenBuildEvaluated(project: Project) {
project.runMissingAndroidTargetProjectConfigurationHealthCheck()
project.runMissingKotlinTargetsProjectConfigurationHealthCheck()
project.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck()
}
}
@@ -15,9 +15,9 @@ import org.jetbrains.kotlin.gradle.plugin.Kotlin2JsPlugin.Companion.NOWARN_2JS_F
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
@@ -226,6 +226,9 @@ internal class PropertiesProvider private constructor(private val project: Proje
val ignoreAbsentAndroidMultiplatformTarget: Boolean
get() = booleanProperty("kotlin.mpp.absentAndroidTarget.nowarn") ?: false
val ignoreDisabledCInteropCommonization: Boolean
get() = booleanProperty("$KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION.nowarn") ?: false
val ignoreIncorrectNativeDependencies: Boolean?
get() = booleanProperty(KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES)