From bf04f821d6134fe2ecbd6109e3d3d209bd2cf236 Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Thu, 11 Nov 2021 15:48:41 +0100 Subject: [PATCH] [Gradle, MPP] Print warning on absent 'android' targets ^KT-41641 Verification Pending --- .../gradle/KT41641AbsentAndroidTarget.kt | 28 ++++++++- ...latformProjectConfigurationHealthChecks.kt | 59 +++++++++++++++++++ .../gradle/plugin/KotlinPluginWrapper.kt | 18 ++---- 3 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformProjectConfigurationHealthChecks.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt index 2d56955a434..2ba2d930fca 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/KT41641AbsentAndroidTarget.kt @@ -8,12 +8,13 @@ package org.jetbrains.kotlin.gradle import com.android.build.gradle.LibraryExtension +import org.jetbrains.kotlin.gradle.plugin.runMissingAndroidTargetProjectConfigurationHealthCheck import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget import org.junit.Test -import kotlin.test.assertNull -import kotlin.test.assertSame +import kotlin.test.* class KT41641AbsentAndroidTarget : MultiplatformExtensionTest() { + @Test fun `test android plugin without android target`() { project.plugins.apply("kotlin-multiplatform") @@ -29,4 +30,27 @@ class KT41641AbsentAndroidTarget : MultiplatformExtensionTest() { assertNull(project.findAndroidTarget()) assertSame(kotlin.android(), project.findAndroidTarget()) } + + @Test + fun `test runMissingAndroidTargetProjectConfigurationHealthCheck`() { + project.plugins.apply("kotlin-multiplatform") + project.plugins.apply("android-library") + + /* Arbitrary minimal Android setup */ + val android = project.extensions.getByName("android") as LibraryExtension + android.compileSdkVersion(30) + + kotlin.jvm() + + // Missing android target -> expect warning message + var warningMessage: String? = null + project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = { warningMessage = it }) + assertNotNull(warningMessage, "Expected warning message to be logged") + + // Present android target -> expect no warning message anymore + kotlin.android() + project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = { + fail("Expected no warning message to be logged. Received: $it") + }) + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformProjectConfigurationHealthChecks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformProjectConfigurationHealthChecks.kt new file mode 100644 index 00000000000..c88b8aedc8f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinMultiplatformProjectConfigurationHealthChecks.kt @@ -0,0 +1,59 @@ +/* + * 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.plugin.mpp.KotlinMetadataTarget +import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget +import org.jetbrains.kotlin.gradle.utils.androidPluginIds +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.runMissingAndroidTargetProjectConfigurationHealthCheck( + warningLogger: (warningMessage: String) -> Unit = project.logger::warn +) = project.runProjectConfigurationHealthCheck check@{ + val androidPluginId = androidPluginIds + .firstOrNull { androidPluginId -> plugins.findPlugin(androidPluginId) != null } ?: return@check + + if (findAndroidTarget() != null) return@check + + warningLogger( + """ + Missing 'android()' Kotlin target in ${project.name} (${project.path})'. + The Android Gradle plugin was applied without creating a corresponding 'android()' Kotlin Target: + + ``` + plugins { + id("$androidPluginId") + kotlin("multiplatform") + } + + kotlin { + android() // <-- please register this Android target + } + ``` + + """.trimIndent() + ) +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 701e0fa2c31..380f2df59e6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -50,7 +50,7 @@ import org.jetbrains.kotlin.statistics.metrics.StringMetrics import javax.inject.Inject import kotlin.reflect.KClass -abstract class KotlinBasePluginWrapper: Plugin { +abstract class KotlinBasePluginWrapper : Plugin { private val log = Logging.getLogger(this.javaClass) @@ -232,19 +232,9 @@ open class KotlinMultiplatformPluginWrapper : KotlinBasePluginWrapper() { override val projectExtensionClass: KClass get() = KotlinMultiplatformExtension::class - override fun whenBuildEvaluated(project: Project) = project.runProjectConfigurationHealthCheck { - val isNoTargetsInitialized = (project.kotlinExtension as KotlinMultiplatformExtension) - .targets - .none { it !is KotlinMetadataTarget } - - if (isNoTargetsInitialized) { - throw GradleException( - """ - 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() - ) - } + override fun whenBuildEvaluated(project: Project) { + project.runMissingAndroidTargetProjectConfigurationHealthCheck() + project.runMissingKotlinTargetsProjectConfigurationHealthCheck() } }