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 0ee7e85c486..fefad6cc77c 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 @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.gradle.plugin +import org.gradle.api.GradleException import org.gradle.api.NamedDomainObjectFactory import org.gradle.api.Plugin import org.gradle.api.Project @@ -26,6 +27,7 @@ import org.gradle.api.logging.Logging import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.logging.kotlinDebug +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory @@ -36,6 +38,7 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension import org.jetbrains.kotlin.gradle.tasks.KOTLIN_COMPILER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_KLIB_COMMONIZER_EMBEDDABLE import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP +import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError import org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.gradle.utils.loadPropertyFromResources @@ -60,6 +63,10 @@ abstract class KotlinBasePluginWrapper( checkGradleCompatibility() + project.gradle.projectsEvaluated { + whenBuildEvaluated(project) + } + project.configurations.maybeCreate(COMPILER_CLASSPATH_CONFIGURATION_NAME).defaultDependencies { it.add(project.dependencies.create("$KOTLIN_MODULE_GROUP:$KOTLIN_COMPILER_EMBEDDABLE:$kotlinPluginVersion")) } @@ -97,6 +104,9 @@ abstract class KotlinBasePluginWrapper( project.addNpmDependencyExtension() } + open fun whenBuildEvaluated(project: Project) { + } + internal open fun createTestRegistry(project: Project) = KotlinTestsRegistry(project) private fun setupAttributeMatchingStrategy(project: Project) = with(project.dependencies.attributesSchema) { @@ -165,6 +175,27 @@ open class KotlinJsPluginWrapper @Inject constructor( override val projectExtensionClass: KClass get() = KotlinJsProjectExtension::class + override fun whenBuildEvaluated(project: Project) { + val isJsTargetUninitialized = (project.kotlinExtension as KotlinJsProjectExtension) + ._target == null + + if (isJsTargetUninitialized) { + throw GradleException( + """ + Please initialize the Kotlin/JS target in '${project.name} (${project.path})'. Use: + kotlin { + js { + // To build distributions and run tests for browser or Node.js use one or both of: + browser() + nodejs() + } + } + Read more https://kotlinlang.org/docs/reference/js-project-setup.html + """.trimIndent() + ) + } + } + override fun createTestRegistry(project: Project) = KotlinTestsRegistry(project, "test") } @@ -180,6 +211,21 @@ open class KotlinMultiplatformPluginWrapper @Inject constructor( override val projectExtensionClass: KClass get() = KotlinMultiplatformExtension::class + + override fun whenBuildEvaluated(project: Project) { + 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() + ) + } + } } fun Project.getKotlinPluginVersion(): String? =