diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 6ef8691ec1c..37ebd100254 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -41,16 +41,13 @@ interface KotlinTargetConfigurator { ) { target.runKotlinTargetSideEffects() target.runKotlinCompilationSideEffects() - defineConfigurationsForTarget(target) configureArchivesAndComponent(target) configureBuild(target) configurePlatformSpecificModel(target) } - fun defineConfigurationsForTarget(target: KotlinTargetType) fun configureArchivesAndComponent(target: KotlinTargetType) fun configureBuild(target: KotlinTargetType) - fun configurePlatformSpecificModel(target: KotlinTargetType) = Unit } @@ -60,96 +57,6 @@ abstract class AbstractKotlinTargetConfigurator protected open val runtimeIncludesCompilationOutputs = true - override fun defineConfigurationsForTarget(target: KotlinTargetType) { - val project = target.project - - val configurations = project.configurations - - val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME) - - val compileConfiguration = mainCompilation.internal.configurations.deprecatedCompileConfiguration - val implementationConfiguration = configurations.maybeCreate(mainCompilation.implementationConfigurationName) - - val runtimeOnlyConfiguration = when (mainCompilation) { - is KotlinCompilationToRunnableFiles<*> -> configurations.maybeCreate(mainCompilation.runtimeOnlyConfigurationName) - else -> null - } - - configurations.maybeCreate(target.apiElementsConfigurationName).apply { - description = "API elements for main." - isVisible = false - isCanBeResolved = false - isCanBeConsumed = true - attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target)) - attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) - extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName)) - if (mainCompilation is KotlinCompilationToRunnableFiles) { - val runtimeConfiguration = mainCompilation.internal.configurations.deprecatedRuntimeConfiguration - runtimeConfiguration?.let { extendsFrom(it) } - } - usesPlatformOf(target) - } - - if (mainCompilation is KotlinCompilationToRunnableFiles<*>) { - configurations.maybeCreate(target.runtimeElementsConfigurationName).apply { - description = "Elements of runtime for main." - isVisible = false - isCanBeConsumed = true - isCanBeResolved = false - attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target)) - attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) - val runtimeConfiguration = mainCompilation.internal.configurations.deprecatedRuntimeConfiguration - extendsFrom(implementationConfiguration) - if (runtimeOnlyConfiguration != null) - extendsFrom(runtimeOnlyConfiguration) - runtimeConfiguration?.let { extendsFrom(it) } - usesPlatformOf(target) - } - } - - configurations.maybeCreate(target.sourcesElementsConfigurationName).apply { - description = "Source files of main compilation of ${target.name}." - isVisible = false - isCanBeResolved = false - isCanBeConsumed = true - configureSourcesPublicationAttributes(target) - project.launch { isCanBeConsumed = target.internal.isSourcesPublishableFuture.await() } - } - - if (createTestCompilation) { - val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME) - val compileTestsConfiguration = testCompilation.internal.configurations.deprecatedCompileConfiguration - val testImplementationConfiguration = configurations.maybeCreate(testCompilation.implementationConfigurationName) - val testRuntimeOnlyConfiguration = when (testCompilation) { - is KotlinCompilationToRunnableFiles<*> -> configurations.maybeCreate(testCompilation.runtimeOnlyConfigurationName) - else -> null - } - - compileConfiguration?.let { compileTestsConfiguration?.extendsFrom(it) } - testImplementationConfiguration.extendsFrom(implementationConfiguration) - testRuntimeOnlyConfiguration?.extendsFrom(runtimeOnlyConfiguration) - - if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) { - val runtimeConfiguration = mainCompilation.internal.configurations.deprecatedRuntimeConfiguration - val testRuntimeConfiguration = testCompilation.internal.configurations.deprecatedRuntimeConfiguration - runtimeConfiguration?.let { testRuntimeConfiguration?.extendsFrom(it) } - } - } - } - - @Deprecated("Remove when IR compiler to klib will not need transitive implementation dependencies") - protected fun implementationToApiElements(target: KotlinTargetType) { - val configurations = target.project.configurations - - // The configuration and the main compilation are created by the base class. - val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME) - configurations.getByName(target.apiElementsConfigurationName).apply { - // K/N and K/JS IR compiler doesn't divide libraries into implementation and api ones. So we need to add implementation - // dependencies into the outgoing configuration. - extendsFrom(configurations.getByName(mainCompilation.implementationConfigurationName)) - } - } - override fun configureBuild(target: KotlinTargetType) { val project = target.project diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt index 8e6bab9682d..de24697898c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt @@ -50,6 +50,8 @@ import org.jetbrains.kotlin.gradle.plugin.sources.LanguageSettingsSetupAction import org.jetbrains.kotlin.gradle.plugin.statistics.MultiplatformBuildStatsReportSetupAction import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubpluginSetupAction import org.jetbrains.kotlin.gradle.targets.CreateDefaultCompilationsSideEffect +import org.jetbrains.kotlin.gradle.targets.CreateTargetConfigurationsSideEffect +import org.jetbrains.kotlin.gradle.targets.NativeForwardImplementationToApiElementsSideEffect import org.jetbrains.kotlin.gradle.targets.KotlinTargetSideEffect import org.jetbrains.kotlin.gradle.targets.js.npm.AddNpmDependencyExtensionProjectSetupAction import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetSetupAction @@ -96,6 +98,8 @@ internal fun Project.registerKotlinPluginExtensions() { KotlinTargetSideEffect.extensionPoint.apply { register(project, CreateDefaultCompilationsSideEffect) + register(project, CreateTargetConfigurationsSideEffect) + register(project, NativeForwardImplementationToApiElementsSideEffect) } KotlinCompilationSideEffect.extensionPoint.apply { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt new file mode 100644 index 00000000000..436c90f3dc1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/CreateTargetConfigurationsSideEffect.kt @@ -0,0 +1,107 @@ +/* + * 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.targets + +import org.gradle.api.attributes.Category +import org.gradle.api.attributes.Usage +import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.categoryByName +import org.jetbrains.kotlin.gradle.plugin.launch +import org.jetbrains.kotlin.gradle.plugin.mpp.* +import org.jetbrains.kotlin.gradle.plugin.mpp.configureSourcesPublicationAttributes +import org.jetbrains.kotlin.gradle.plugin.mpp.internal +import org.jetbrains.kotlin.gradle.plugin.mpp.isSourcesPublishableFuture +import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget + +internal val CreateTargetConfigurationsSideEffect = KotlinTargetSideEffect { target -> + val project = target.project + + val configurations = project.configurations + + val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME) + + val compileConfiguration = mainCompilation.internal.configurations.deprecatedCompileConfiguration + val implementationConfiguration = configurations.maybeCreate(mainCompilation.implementationConfigurationName) + + val runtimeOnlyConfiguration = when (mainCompilation) { + is KotlinCompilationToRunnableFiles<*> -> configurations.maybeCreate(mainCompilation.runtimeOnlyConfigurationName) + else -> null + } + + configurations.maybeCreate(target.apiElementsConfigurationName).apply { + description = "API elements for main." + isVisible = false + isCanBeResolved = false + isCanBeConsumed = true + attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) + extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName)) + if (mainCompilation is KotlinCompilationToRunnableFiles) { + val runtimeConfiguration = mainCompilation.internal.configurations.deprecatedRuntimeConfiguration + runtimeConfiguration?.let { extendsFrom(it) } + } + usesPlatformOf(target) + } + + if (mainCompilation is KotlinCompilationToRunnableFiles<*>) { + configurations.maybeCreate(target.runtimeElementsConfigurationName).apply { + description = "Elements of runtime for main." + isVisible = false + isCanBeConsumed = true + isCanBeResolved = false + attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY)) + val runtimeConfiguration = mainCompilation.internal.configurations.deprecatedRuntimeConfiguration + extendsFrom(implementationConfiguration) + if (runtimeOnlyConfiguration != null) + extendsFrom(runtimeOnlyConfiguration) + runtimeConfiguration?.let { extendsFrom(it) } + usesPlatformOf(target) + } + } + + configurations.maybeCreate(target.sourcesElementsConfigurationName).apply { + description = "Source files of main compilation of ${target.name}." + isVisible = false + isCanBeResolved = false + isCanBeConsumed = true + configureSourcesPublicationAttributes(target) + project.launch { isCanBeConsumed = target.internal.isSourcesPublishableFuture.await() } + } + + if (target !is KotlinMetadataTarget) { + val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME) + val compileTestsConfiguration = testCompilation.internal.configurations.deprecatedCompileConfiguration + val testImplementationConfiguration = configurations.maybeCreate(testCompilation.implementationConfigurationName) + val testRuntimeOnlyConfiguration = when (testCompilation) { + is KotlinCompilationToRunnableFiles<*> -> configurations.maybeCreate(testCompilation.runtimeOnlyConfigurationName) + else -> null + } + + compileConfiguration?.let { compileTestsConfiguration?.extendsFrom(it) } + testImplementationConfiguration.extendsFrom(implementationConfiguration) + testRuntimeOnlyConfiguration?.extendsFrom(runtimeOnlyConfiguration) + + if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) { + val runtimeConfiguration = mainCompilation.internal.configurations.deprecatedRuntimeConfiguration + val testRuntimeConfiguration = testCompilation.internal.configurations.deprecatedRuntimeConfiguration + runtimeConfiguration?.let { testRuntimeConfiguration?.extendsFrom(it) } + } + } + + if (target is KotlinJsIrTarget && !target.isMpp!!) { + target.project.configurations.maybeCreate( + target.commonFakeApiElementsConfigurationName + ).apply { + description = "Common Fake API elements for main." + isVisible = false + isCanBeResolved = false + isCanBeConsumed = true + attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target)) + attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/NativeForwardImplementationToApiElementsSideEffect.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/NativeForwardImplementationToApiElementsSideEffect.kt new file mode 100644 index 00000000000..e6020cde156 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/NativeForwardImplementationToApiElementsSideEffect.kt @@ -0,0 +1,26 @@ +/* + * 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.targets + +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + +/** + * Kotlin/Multiplatform requires all dependencies to be available at compile time. + * We therefore forward all dependencies with the 'implementation' scope to 'apiElements' to ensure + * them being available transitively. + */ +internal val NativeForwardImplementationToApiElementsSideEffect = KotlinTargetSideEffect { target -> + val configurations = target.project.configurations + + // The configuration and the main compilation are created by the base class. + val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME) + configurations.getByName(target.apiElementsConfigurationName).apply { + // K/N and K/JS IR compiler doesn't divide libraries into implementation and api ones. So we need to add implementation + // dependencies into the outgoing configuration. + extendsFrom(configurations.getByName(mainCompilation.implementationConfigurationName)) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTargetConfigurator.kt index 0b36a32e90c..fba7b8f7cdc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTargetConfigurator.kt @@ -5,17 +5,16 @@ package org.jetbrains.kotlin.gradle.targets.js.ir -import org.gradle.api.attributes.Usage import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.bundling.Zip import org.jetbrains.kotlin.gradle.dsl.JsModuleKind import org.jetbrains.kotlin.gradle.dsl.JsSourceMapEmbedMode import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompilerOptions -import org.jetbrains.kotlin.gradle.plugin.* -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages +import org.jetbrains.kotlin.gradle.plugin.KotlinOnlyTargetConfigurator +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.KotlinTargetWithTestsConfigurator import org.jetbrains.kotlin.gradle.targets.js.KotlinJsReportAggregatingTestRun -import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.testing.testTaskName import org.jetbrains.kotlin.gradle.utils.decamelize @@ -80,22 +79,6 @@ open class KotlinJsIrTargetConfigurator : } } - override fun defineConfigurationsForTarget(target: KotlinJsIrTarget) { - super.defineConfigurationsForTarget(target) - - if (target.isMpp!!) return - - target.project.configurations.maybeCreate( - target.commonFakeApiElementsConfigurationName - ).apply { - description = "Common Fake API elements for main." - isVisible = false - isCanBeResolved = false - isCanBeConsumed = true - attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target)) - attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) - } - } internal companion object { internal fun KotlinJsCompilerOptions.configureJsDefaultOptions( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index 37806d1543f..f44e404c0e0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -303,11 +303,6 @@ open class KotlinNativeTargetConfigurator : AbstractKotl } } - override fun defineConfigurationsForTarget(target: T) { - super.defineConfigurationsForTarget(target) - implementationToApiElements(target) - } - private fun warnAboutIncorrectDependencies(target: KotlinNativeTarget) = target.project.launchInStage(ReadyForExecution) { val compileOnlyDependencies = target.compilations.mapNotNull {