From 7630afd37d955e817404b0b99625571163125e31 Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Tue, 21 Jun 2022 22:35:52 +0200 Subject: [PATCH] Replace MPP 'fromPreset' convention with normal extension methods ^KT-47047 In Progress --- .../native-binaries/groovy-dsl/build.gradle | 2 +- .../testProject/native-libraries/build.gradle | 2 +- .../testProject/native-tests/build.gradle | 26 ++-- .../sample-app/build.gradle | 2 +- .../dsl/KotlinMultiplatformExtension.kt | 119 +++++++++++++++++- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 31 +---- 6 files changed, 128 insertions(+), 54 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/groovy-dsl/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/groovy-dsl/build.gradle index 8bcaa903317..a9708cfbf6f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/groovy-dsl/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-binaries/groovy-dsl/build.gradle @@ -41,7 +41,7 @@ kotlin { linuxX64("linux64") mingwX64("mingw64") - configure([macos64, linux64, mingw64]) { + configure([findByName('macos64'), findByName('linux64'), findByName('mingw64')]) { compilations.all { kotlinOptions.verbose = true } compilations.test.kotlinOptions.freeCompilerArgs += "-nowarn" binaries { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-libraries/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-libraries/build.gradle index 139c0bf795e..9bf61294e1e 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-libraries/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-libraries/build.gradle @@ -27,7 +27,7 @@ kotlin { fromPreset(presets.linuxX64, 'linux64') fromPreset(presets.mingwX64, 'mingw64') - configure([linux64, mingw64, macos64]) { + configure([findByName('linux64'), findByName('mingw64'), findByName('macos64')]) { binaries { sharedLib("main", [DEBUG]) staticLib("main", [DEBUG]) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-tests/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-tests/build.gradle index 4c0380a8b88..17713ec9d21 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-tests/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/native-tests/build.gradle @@ -25,7 +25,7 @@ kotlin { fromPreset(presets.iosX64, 'ios') fromPreset(presets.iosSimulatorArm64, 'iosArm64') - configure([host]) { + configure([findByName('host')]) { compilations.create("anotherTest") binaries { test("another", [DEBUG]) { @@ -53,10 +53,8 @@ configure([hostTest, iosTest, iosArm64Test]){ // Check that getting a test binary in an old way fails showing the corresponding warning task checkOldGet { doLast { - kotlin.targets { - configure([host]) { - println("Get test: ${binaries.getExecutable("test", DEBUG)}") - } + configure([kotlin.targets.host]) { + println("Get test: ${binaries.getExecutable("test", DEBUG)}") } } } @@ -64,23 +62,19 @@ task checkOldGet { // Check that finding a test binary in an old way returns null showing the corresponding warning. task checkOldFind { doLast { - kotlin.targets { - configure([host]) { - println("Find test: ${binaries.findExecutable("test", DEBUG)}") - } + configure([kotlin.targets.host]) { + println("Find test: ${binaries.findExecutable("test", DEBUG)}") } } } task checkNewGetters { doLast { - kotlin.targets { - configure([host]) { - println("Get test: ${binaries.getTest(DEBUG).outputFile.name}") - println("Find test: ${binaries.findTest(DEBUG).outputFile.name}") - println("Get test: ${binaries.getTest("another", DEBUG).outputFile.name}") - println("Find test: ${binaries.findTest("another", DEBUG).outputFile.name}") - } + configure([kotlin.targets.host]) { + println("Get test: ${binaries.getTest(DEBUG).outputFile.name}") + println("Find test: ${binaries.findTest(DEBUG).outputFile.name}") + println("Get test: ${binaries.getTest("another", DEBUG).outputFile.name}") + println("Find test: ${binaries.findTest("another", DEBUG).outputFile.name}") } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-app/build.gradle index 88f74c3d5ba..be4b8f25a20 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-app/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-app/build.gradle @@ -68,7 +68,7 @@ kotlin { fromPreset(presets.linuxX64, 'linux64') - configure([linux64]) { + configure([findByName('linux64')]) { binaries.executable("main", [DEBUG]) { entryPoint = "com.example.app.native.main" } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt index 2452e4d7afa..ce719564fc0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt @@ -6,12 +6,17 @@ package org.jetbrains.kotlin.gradle.dsl import groovy.lang.Closure +import org.gradle.api.Action import org.gradle.api.InvalidUserCodeException import org.gradle.api.NamedDomainObjectCollection import org.gradle.api.Project +import org.gradle.api.internal.plugins.DslObject +import org.gradle.api.logging.Logger import org.gradle.util.ConfigureUtil import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.* +import javax.inject.Inject open class KotlinMultiplatformExtension(project: Project) : KotlinProjectExtension(project), @@ -19,14 +24,36 @@ open class KotlinMultiplatformExtension(project: Project) : KotlinTargetContainerWithJsPresetFunctions, KotlinTargetContainerWithWasmPresetFunctions, KotlinTargetContainerWithNativeShortcuts { - override lateinit var presets: NamedDomainObjectCollection> - internal set + override val presets: NamedDomainObjectCollection> = project.container(KotlinTargetPreset::class.java) - override lateinit var targets: NamedDomainObjectCollection - internal set + final override val targets: NamedDomainObjectCollection = project.container(KotlinTarget::class.java) - override lateinit var defaultJsCompilerType: KotlinJsCompilerType - internal set + override val defaultJsCompilerType: KotlinJsCompilerType = project.kotlinPropertiesProvider.jsCompiler + + private val presetExtension = project.objects.newInstance( + DefaultTargetsFromPresetExtension::class.java, + { this }, + targets + ) + + init { + val presetExtensionWithDeprecation = project.objects.newInstance( + TargetsFromPresetExtensionWithDeprecation::class.java, + project.logger, + project.path, + presetExtension + ) + @Suppress("DEPRECATION") + DslObject(targets).addConvention("fromPreset", presetExtensionWithDeprecation) + } + + fun targets(configure: Action) { + configure.execute(presetExtension) + } + + fun targets(configure: TargetsFromPresetExtension.() -> Unit) { + configure(presetExtension) + } @Suppress("unused") // DSL val testableTargets: NamedDomainObjectCollection> @@ -56,6 +83,86 @@ open class KotlinMultiplatformExtension(project: Project) : } } +interface TargetsFromPresetExtension : NamedDomainObjectCollection { + + fun fromPreset( + preset: KotlinTargetPreset, + name: String, + configureAction: T.() -> Unit = {} + ): T + + fun fromPreset( + preset: KotlinTargetPreset, + name: String + ): T = fromPreset(preset, name, {}) + + fun fromPreset( + preset: KotlinTargetPreset, + name: String, + configureAction: Action + ): T +} + +internal abstract class DefaultTargetsFromPresetExtension @Inject constructor( + private val targetsContainer: () -> KotlinTargetsContainerWithPresets, + val targets: NamedDomainObjectCollection +) : TargetsFromPresetExtension, + NamedDomainObjectCollection by targets { + + override fun fromPreset( + preset: KotlinTargetPreset, + name: String, + configureAction: T.() -> Unit + ): T = targetsContainer().configureOrCreate(name, preset, configureAction) + + override fun fromPreset( + preset: KotlinTargetPreset, + name: String, + configureAction: Action + ) = fromPreset(preset, name) { + configureAction.execute(this) + } +} + +internal abstract class TargetsFromPresetExtensionWithDeprecation @Inject constructor( + private val logger: Logger, + private val projectPath: String, + private val parentExtension: DefaultTargetsFromPresetExtension +) : TargetsFromPresetExtension, + NamedDomainObjectCollection by parentExtension.targets { + + override fun fromPreset( + preset: KotlinTargetPreset, + name: String, + configureAction: T.() -> Unit + ): T { + printDeprecationMessage(preset, name) + return parentExtension.fromPreset(preset, name, configureAction) + } + + override fun fromPreset( + preset: KotlinTargetPreset, + name: String, + configureAction: Action + ): T { + printDeprecationMessage(preset, name) + return parentExtension.fromPreset(preset, name, configureAction) + } + + private fun printDeprecationMessage( + preset: KotlinTargetPreset, + targetName: String + ) { + logger.warn( + """ + Creating Kotlin target ${preset.name}:${targetName} via convention 'target.fromPreset()' in $projectPath project is deprecated!" + + Check https://kotlinlang.org/docs/multiplatform-set-up-targets.html documentation how to create MPP target. + """.trimIndent() + ) + } +} + internal fun KotlinTarget.isProducedFromPreset(kotlinTargetPreset: KotlinTargetPreset<*>): Boolean = preset == kotlinTargetPreset diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index f1d549f6a5a..8550c3ab0e3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -5,19 +5,15 @@ package org.jetbrains.kotlin.gradle.plugin.mpp -import groovy.lang.Closure import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.attributes.AttributeContainer import org.gradle.api.file.DuplicatesStrategy -import org.gradle.api.internal.plugins.DslObject import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.tasks.TaskProvider import org.gradle.jvm.tasks.Jar -import org.gradle.util.ConfigureUtil import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.dsl.configureOrCreate import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies @@ -51,15 +47,6 @@ import java.io.File class KotlinMultiplatformPlugin : Plugin { - private class TargetFromPresetExtension(val targetsContainer: KotlinTargetsContainerWithPresets) { - fun fromPreset(preset: KotlinTargetPreset, name: String, configureClosure: Closure<*>): T = - fromPreset(preset, name) { ConfigureUtil.configure(configureClosure, this) } - - @JvmOverloads - fun fromPreset(preset: KotlinTargetPreset, name: String, configureAction: T.() -> Unit = { }): T = - targetsContainer.configureOrCreate(name, preset, configureAction) - } - override fun apply(project: Project) { checkGradleCompatibility("the Kotlin Multiplatform plugin", GradleVersion.version("6.0")) @@ -88,28 +75,14 @@ class KotlinMultiplatformPlugin : Plugin { } } - val targetsContainer = project.container(KotlinTarget::class.java) val kotlinMultiplatformExtension = project.extensions.getByType(KotlinMultiplatformExtension::class.java) - val targetsFromPreset = TargetFromPresetExtension(kotlinMultiplatformExtension) - - kotlinMultiplatformExtension.apply { - DslObject(targetsContainer).addConvention("fromPreset", targetsFromPreset) - - targets = targetsContainer - addExtension("targets", targets) - - presets = project.container(KotlinTargetPreset::class.java) - addExtension("presets", presets) - - defaultJsCompilerType = PropertiesProvider(project).jsCompiler - } setupDefaultPresets(project) customizeKotlinDependencies(project) configureSourceSets(project) // set up metadata publishing - targetsFromPreset.fromPreset( + kotlinMultiplatformExtension.targetFromPreset( KotlinMetadataTargetPreset(project), METADATA_TARGET_NAME ) @@ -118,7 +91,7 @@ class KotlinMultiplatformPlugin : Plugin { if (!project.hasKpmModel) { configurePublishingWithMavenPublish(project) } - targetsContainer.withType(AbstractKotlinTarget::class.java).all { applyUserDefinedAttributes(it) } + kotlinMultiplatformExtension.targets.withType(AbstractKotlinTarget::class.java).all { applyUserDefinedAttributes(it) } // propagate compiler plugin options to the source set language settings setupAdditionalCompilerArguments(project)