From ca79860a718b647ea24ee1f86cc9df386162e426 Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Mon, 16 Oct 2023 15:31:08 +0200 Subject: [PATCH] [Gradle] Move 'whenEvaluated' util function into 'utils' package --- .../gradle/android/KotlinAndroidMppIT.kt | 65 ------------------- .../kapt/Kapt3KotlinGradleSubplugin.kt | 1 + .../gradle/plugin/AbstractKotlinPlugin.kt | 1 + .../plugin/Kotlin2JsSourceSetProcessor.kt | 1 + .../gradle/plugin/KotlinAndroidPlugin.kt | 1 + .../plugin/KotlinJsIrSourceSetProcessor.kt | 1 + .../plugin/KotlinLegacyMultiplatformPlugin.kt | 46 +------------ .../plugin/KotlinPluginLifecycleImpl.kt | 1 + .../gradle/plugin/RunOnceAfterEvaluated.kt | 1 + .../mpp/GranularMetadataTransformation.kt | 1 + .../plugin/mpp/KotlinMultiplatformPlugin.kt | 1 + .../kotlin/gradle/plugin/mpp/Publishing.kt | 1 + .../targets/android/AndroidProjectHandler.kt | 1 + .../gradle/targets/js/d8/D8RootPlugin.kt | 1 - .../targets/js/ir/KotlinJsIrSubTarget.kt | 2 +- .../targets/js/npm/NpmResolverPlugin.kt | 2 +- .../jvm/KotlinJvmTargetConfigurator.kt | 1 + .../KotlinMetadataTargetConfigurator.kt | 1 + .../native/KotlinNativeTargetConfigurator.kt | 2 +- .../native/KotlinNativeTargetPreset.kt | 1 + .../native/cocoapods/KotlinCocoapodsPlugin.kt | 2 +- .../native/internal/CommonizerTasks.kt | 2 +- .../runProjectConfigurationHealthCheck.kt | 1 - .../kotlin/gradle/utils/whenEvaluated.kt | 51 +++++++++++++++ .../WhenEvaluatedAndroidOrderingTest.kt | 2 +- .../gradle/unitTests/WhenEvaluatedTest.kt | 42 ++++++++++++ 26 files changed, 114 insertions(+), 118 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/whenEvaluated.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedTest.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt index eddfddd3a34..33ae4ebf252 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/android/KotlinAndroidMppIT.kt @@ -31,71 +31,6 @@ import kotlin.test.* @GradleTestVersions(minVersion = G_7_1) @AndroidTestVersions(minVersion = AGP_70) class KotlinAndroidMppIT : KGPBaseTest() { - @DisplayName("KT-50736: whenEvaluated waits for AGP being applied later") - @GradleAndroidTest - fun testAfterEvaluateOrdering( - gradleVersion: GradleVersion, - agpVersion: String, - jdkVersion: JdkVersions.ProvidedJdk, - ) { - project( - "AndroidProject", - gradleVersion, - buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion), - buildJdk = jdkVersion.location - ) { - subProject("Lib").buildGradle.writeText( - //language=Gradle - """ - buildscript { - repositories { - mavenLocal() - google() - gradlePluginPortal() - } - dependencies { - classpath "com.android.tools.build:gradle:${'$'}android_tools_version" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${'$'}kotlin_version" - } - } - - plugins { - id 'org.jetbrains.kotlin.multiplatform' - } - - class MyAction implements kotlin.jvm.functions.Function1 { - Void invoke (Project p) { - println("compilations: " + p.kotlin.targets.getByName("android").compilations.names) - } - } - - org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginKt.whenEvaluated(project, new MyAction ()) - - apply plugin : "android-library" - - android { - compileSdkVersion 22 - namespace 'org.jetbrains.kotlin.gradle.test.android.libalfa' - } - - kotlin { android("android") { } } - """.trimIndent() - ) - - build("help") { - val reportedCompilations = output.lines() - .single { it.contains("compilations: ") } - .substringAfter("compilations: ") - .removeSurrounding("[", "]") - .split(", ") - .toSet() - assertEquals( - setOf("debug", "debugAndroidTest", "debugUnitTest", "release", "releaseUnitTest"), - reportedCompilations - ) - } - } - } @DisplayName("KotlinToolingMetadataArtifact is bundled into apk") @GradleAndroidTest diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index ac34dc7c160..bd2fcbf7afd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.tasks.configuration.* +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly import java.io.ByteArrayOutputStream import java.io.File diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt index 5b759b540e2..87f6bdf833a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/AbstractKotlinPlugin.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.gradle.tasks.InspectClassesForMultiModuleIC import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.archivePathCompatible const val PLUGIN_CLASSPATH_CONFIGURATION_NAME = "kotlinCompilerPluginClasspath" diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/Kotlin2JsSourceSetProcessor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/Kotlin2JsSourceSetProcessor.kt index 38f48e09de3..4c8e8b4f64e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/Kotlin2JsSourceSetProcessor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/Kotlin2JsSourceSetProcessor.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.configuration.Kotlin2JsCompileConfig +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import java.io.File internal class Kotlin2JsSourceSetProcessor( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinAndroidPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinAndroidPlugin.kt index dee2af0d70b..07a66b6eb6b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinAndroidPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinAndroidPlugin.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinJvmPlugin.Companion.configureCom import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.applyUserDefinedAttributes import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.androidPluginIds import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsIrSourceSetProcessor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsIrSourceSetProcessor.kt index 20eb85440ce..6d60e43499e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsIrSourceSetProcessor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsIrSourceSetProcessor.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.configuration.Kotlin2JsCompileConfig import org.jetbrains.kotlin.gradle.tasks.configuration.KotlinJsIrLinkConfig +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.filesProvider internal class KotlinJsIrSourceSetProcessor( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinLegacyMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinLegacyMultiplatformPlugin.kt index 72a1ac43c19..d07fe5043f7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinLegacyMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinLegacyMultiplatformPlugin.kt @@ -27,9 +27,7 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnosticOncePerBuild import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile -import org.jetbrains.kotlin.gradle.utils.androidPluginIds -import org.jetbrains.kotlin.gradle.utils.getOrPut -import java.util.concurrent.atomic.AtomicBoolean +import org.jetbrains.kotlin.gradle.utils.whenEvaluated abstract class KotlinPlatformPluginBase(protected val platformName: String) : Plugin { companion object { @@ -200,48 +198,6 @@ open class KotlinPlatformImplementationPluginBase(platformName: String) : Kotlin } } -internal fun Project.whenEvaluated(fn: Project.() -> T) { - if (state.executed) { - fn() - return - } - - /** If there's already an Android plugin applied, just dispatch the action to `afterEvaluate`, it gets executed after AGP's actions */ - if (androidPluginIds.any { pluginManager.hasPlugin(it) }) { - afterEvaluate { fn() } - return - } - - val isDispatchedAfterAndroid = AtomicBoolean(false) - - /** - * This queue holds all actions submitted to `whenEvaluated` in this project, waiting for one of the Android plugins to be applied. - * After (and if) an Android plugin gets applied, we dispatch all the actions in the queue to `afterEvaluate`, so that they are - * executed after what AGP scheduled to `afterEvaluate`. There are different Android plugins, so actions in the queue also need to check - * if it's the first Android plugin, using `isDispatched` (each has its own instance). - */ - val afterAndroidDispatchQueue = project.extensions.extraProperties.getOrPut("org.jetbrains.kotlin.whenEvaluated") { - val queue = mutableListOf<() -> Unit>() - // Trigger the actions on any plugin applied; the actions themselves ensure that they only dispatch the fn once. - androidPluginIds.forEach { id -> - pluginManager.withPlugin(id) { queue.forEach { it() } } - } - queue - } - afterAndroidDispatchQueue.add { - if (!isDispatchedAfterAndroid.getAndSet(true)) { - afterEvaluate { fn() } - } - } - - afterEvaluate { - /** If no Android plugin was loaded, then the action was not dispatched, and we can freely execute it now */ - if (!isDispatchedAfterAndroid.getAndSet(true)) { - fn() - } - } -} - private const val KOTLIN_12X_MPP_DEPRECATION_SUPPRESS_FLAG = "kotlin.internal.mpp12x.deprecation.suppress" internal fun warnAboutKotlin12xMppDeprecation(project: Project) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginLifecycleImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginLifecycleImpl.kt index d0de393a0b4..2956ecc3b41 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginLifecycleImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginLifecycleImpl.kt @@ -9,6 +9,7 @@ import org.gradle.api.Project import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.CoroutineStart.Default import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.CoroutineStart.Undispatched import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.ProjectConfigurationResult +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.CompletableFuture import org.jetbrains.kotlin.gradle.utils.failures import java.util.concurrent.atomic.AtomicBoolean diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/RunOnceAfterEvaluated.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/RunOnceAfterEvaluated.kt index c76bc8d817e..7f46a84e15e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/RunOnceAfterEvaluated.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/RunOnceAfterEvaluated.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.Project import org.gradle.api.logging.Logging +import org.jetbrains.kotlin.gradle.utils.whenEvaluated /** * This class encapsulated logic which should be invoked during not before the script evaluation is ready and diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt index d6de3d57018..15358ec1b8c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GranularMetadataTransformation.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ArtifactMetadataProvider import org.jetbrains.kotlin.gradle.plugin.sources.internal +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.* import java.util.* 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 4fecf7a418f..89bc94b1341 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 @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.gradle.targets.native.createFatFrameworks import org.jetbrains.kotlin.gradle.targets.native.internal.setupCInteropCommonizedCInteropApiElementsConfigurations import org.jetbrains.kotlin.gradle.targets.native.tasks.artifact.registerKotlinArtifactsExtension import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget.* diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt index 1d190f5586e..2984b6aa10f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/Publishing.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled import org.jetbrains.kotlin.gradle.tooling.buildKotlinToolingMetadataTask +import org.jetbrains.kotlin.gradle.utils.whenEvaluated internal fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") { if (project.kotlinPropertiesProvider.createDefaultMultiplatformPublications) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt index 809ab73bcab..8c91671f554 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/android/AndroidProjectHandler.kt @@ -45,6 +45,7 @@ import org.jetbrains.kotlin.gradle.tasks.configuration.KotlinCompileConfig import org.jetbrains.kotlin.gradle.tasks.thisTaskProvider import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.tooling.includeKotlinToolingMetadataInApk +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.* import java.io.File import java.io.ObjectInputStream diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt index b35a2b945f3..168613d45ac 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt @@ -9,7 +9,6 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.BasePlugin import org.gradle.api.tasks.Copy -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootExtension.Companion.EXTENSION_NAME import org.jetbrains.kotlin.gradle.tasks.CleanDataTask diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrSubTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrSubTarget.kt index 335644230c6..5268b0a287f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrSubTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrSubTarget.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinTargetWithTests import org.jetbrains.kotlin.gradle.plugin.mpp.isMain -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlatformTestRun import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt index f505a34bb80..d701f2ebe12 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import org.gradle.api.Plugin import org.gradle.api.Project -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.implementing diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTargetConfigurator.kt index 0cbc0e98221..f908ea24731 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTargetConfigurator.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.testing.testTaskName +import org.jetbrains.kotlin.gradle.utils.whenEvaluated open class KotlinJvmTargetConfigurator : KotlinOnlyTargetConfigurator(true), diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt index 1230da86f84..3c354a967f4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.gradle.targets.native.internal.sharedCommonizerTarge import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.registerTask +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics import org.jetbrains.kotlin.tooling.core.extrasLazyProperty 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 bcc36149238..37806d1543f 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 @@ -42,9 +42,9 @@ import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.testing.internal.configureConventions import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.testing.testTaskName +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.XcodeUtils import org.jetbrains.kotlin.gradle.utils.copyAttributes -import org.jetbrains.kotlin.gradle.utils.named import org.jetbrains.kotlin.gradle.utils.newInstance import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt index 2341a4100db..2d1421e95b5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetPreset.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.targets.android.internal.InternalKotlinTargetPreset import org.jetbrains.kotlin.gradle.targets.native.internal.* +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject import org.jetbrains.kotlin.gradle.utils.setupNativeCompiler import org.jetbrains.kotlin.konan.target.HostManager diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt index 31248076b60..8e0995cf49f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/cocoapods/KotlinCocoapodsPlugin.kt @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.apple.* import org.jetbrains.kotlin.gradle.plugin.mpp.apple.AppleSdk import org.jetbrains.kotlin.gradle.plugin.mpp.apple.AppleTarget import org.jetbrains.kotlin.gradle.plugin.mpp.apple.FrameworkCopy.Companion.dsymFile -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.targets.native.cocoapods.CocoapodsPluginDiagnostics import org.jetbrains.kotlin.gradle.targets.native.cocoapods.KotlinArtifactsPodspecExtension import org.jetbrains.kotlin.gradle.targets.native.cocoapods.kotlinArtifactsPodspecExtension diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt index 9317770c0af..86f46a68756 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPro import org.jetbrains.kotlin.gradle.plugin.await import org.jetbrains.kotlin.gradle.plugin.ide.Idea222Api import org.jetbrains.kotlin.gradle.plugin.ide.ideaImportDependsOn -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.tasks.dependsOn import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask import java.io.File diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/runProjectConfigurationHealthCheck.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/runProjectConfigurationHealthCheck.kt index 36639201919..66b78d74b01 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/runProjectConfigurationHealthCheck.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/runProjectConfigurationHealthCheck.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.utils import org.gradle.api.Project import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated import org.jetbrains.kotlin.gradle.plugin.launchInStage /** diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/whenEvaluated.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/whenEvaluated.kt new file mode 100644 index 00000000000..61ce5eda072 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/whenEvaluated.kt @@ -0,0 +1,51 @@ +/* + * 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.utils + +import org.gradle.api.Project +import java.util.concurrent.atomic.AtomicBoolean + +internal fun Project.whenEvaluated(fn: Project.() -> T) { + if (state.executed) { + fn() + return + } + + /** If there's already an Android plugin applied, just dispatch the action to `afterEvaluate`, it gets executed after AGP's actions */ + if (androidPluginIds.any { pluginManager.hasPlugin(it) }) { + afterEvaluate { fn() } + return + } + + val isDispatchedAfterAndroid = AtomicBoolean(false) + + /** + * This queue holds all actions submitted to `whenEvaluated` in this project, waiting for one of the Android plugins to be applied. + * After (and if) an Android plugin gets applied, we dispatch all the actions in the queue to `afterEvaluate`, so that they are + * executed after what AGP scheduled to `afterEvaluate`. There are different Android plugins, so actions in the queue also need to check + * if it's the first Android plugin, using `isDispatched` (each has its own instance). + */ + val afterAndroidDispatchQueue = project.extensions.extraProperties.getOrPut("org.jetbrains.kotlin.whenEvaluated") { + val queue = mutableListOf<() -> Unit>() + // Trigger the actions on any plugin applied; the actions themselves ensure that they only dispatch the fn once. + androidPluginIds.forEach { id -> + pluginManager.withPlugin(id) { queue.forEach { it() } } + } + queue + } + afterAndroidDispatchQueue.add { + if (!isDispatchedAfterAndroid.getAndSet(true)) { + afterEvaluate { fn() } + } + } + + afterEvaluate { + /** If no Android plugin was loaded, then the action was not dispatched, and we can freely execute it now */ + if (!isDispatchedAfterAndroid.getAndSet(true)) { + fn() + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedAndroidOrderingTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedAndroidOrderingTest.kt index c8c939304a5..de90f3d5c2a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedAndroidOrderingTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedAndroidOrderingTest.kt @@ -11,7 +11,7 @@ import com.android.build.gradle.LibraryExtension import org.gradle.api.Project import org.gradle.api.internal.project.ProjectInternal import org.gradle.testfixtures.ProjectBuilder -import org.jetbrains.kotlin.gradle.plugin.whenEvaluated +import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.util.applyMultiplatformPlugin import org.junit.Test import kotlin.test.BeforeTest diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedTest.kt new file mode 100644 index 00000000000..25c4bbef827 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/WhenEvaluatedTest.kt @@ -0,0 +1,42 @@ +/* + * 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. + */ + +@file:Suppress("FunctionName") + +package org.jetbrains.kotlin.gradle.unitTests + +import com.android.build.api.variant.AndroidComponentsExtension +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.util.androidLibrary +import org.jetbrains.kotlin.gradle.util.applyMultiplatformPlugin +import org.jetbrains.kotlin.gradle.util.buildProject +import org.jetbrains.kotlin.gradle.utils.getByType +import org.jetbrains.kotlin.gradle.utils.whenEvaluated +import java.util.concurrent.atomic.AtomicBoolean +import kotlin.test.Test +import kotlin.test.assertFalse + +class WhenEvaluatedTest { + @Test + fun `test - whenEvaluated - waits for Android plugins afterEvaluate`() { + val project = buildProject() + project.androidLibrary { compileSdk = 33 } + project.applyMultiplatformPlugin() + project.multiplatformExtension.androidTarget() + + val onVariantsCalled = AtomicBoolean(false) + val onWhenEvaluatedCalled = AtomicBoolean(false) + + project.extensions.getByType>().onVariants { + assertFalse(onVariantsCalled.getAndSet(true)) + assertFalse(onWhenEvaluatedCalled.get(), "whenEvaluated was called before 'onVariants'") + } + + project.whenEvaluated { + assertFalse(onVariantsCalled.get(), "whenEvaluated was called after 'onVariants'") + assertFalse(onWhenEvaluatedCalled.getAndSet(true)) + } + } +} \ No newline at end of file