From 9c67276201643e17a85620dfcc2205898e3aad94 Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Thu, 9 Jun 2022 09:57:39 +0200 Subject: [PATCH] [Gradle][MPP] Cache kotlinProjectStructureMetadata for multiplatform projects GranularMetadataTransformation requires the metadata for dependency projects, for every given source set multiple times. This lead to the metadata being built extremely often, causing a significant bottleneck during import. --- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 8 +++---- .../mpp/KotlinProjectStructureMetadata.kt | 21 ++++++++++++------- ...ndencyProjectStructureMetadataExtractor.kt | 5 +++-- .../KotlinMetadataTargetConfigurator.kt | 2 +- .../JvmAndAndroidIntermediateSourceSetTest.kt | 9 ++++---- .../kotlin/tooling/KotlinToolingMetadata.kt | 2 -- 6 files changed, 26 insertions(+), 21 deletions(-) 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 9badcb76c5f..f1d549f6a5a 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 @@ -126,7 +126,7 @@ class KotlinMultiplatformPlugin : Plugin { project.pluginManager.apply(ScriptingGradleSubplugin::class.java) - exportProjectStructureMetadataForOtherBuilds(project) + exportProjectStructureMetadataForOtherBuilds(kotlinMultiplatformExtension) SingleActionPerBuild.run(project.rootProject, "cleanup-processed-metadata") { if (isConfigurationCacheAvailable(project.gradle)) { @@ -148,10 +148,10 @@ class KotlinMultiplatformPlugin : Plugin { } private fun exportProjectStructureMetadataForOtherBuilds( - project: Project + extension: KotlinMultiplatformExtension ) { - GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(project) { - checkNotNull(buildKotlinProjectStructureMetadata(project)) + GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(extension.project) { + extension.kotlinProjectStructureMetadata } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt index e28ce62a53a..ce03e5331e0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt @@ -13,7 +13,7 @@ import org.gradle.api.Project import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Nested -import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCom import org.jetbrains.kotlin.gradle.targets.metadata.getPublishedPlatformCompilations import org.jetbrains.kotlin.gradle.targets.metadata.isSharedNativeSourceSet import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerCompositeMetadataJarBundling.cinteropMetadataDirectoryPath +import org.jetbrains.kotlin.gradle.utils.getOrPut import org.w3c.dom.Document import org.w3c.dom.Element import org.w3c.dom.Node @@ -138,13 +139,19 @@ data class KotlinProjectStructureMetadata( } } -internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjectStructureMetadata? { - require(!project.hasKpmModel) { "this function only works with the stable plugin" } +internal val KotlinMultiplatformExtension.kotlinProjectStructureMetadata: KotlinProjectStructureMetadata + get() = project.extensions.extraProperties.getOrPut("org.jetbrains.kotlin.gradle.plugin.mpp.kotlinProjectStructureMetadata") { + buildKotlinProjectStructureMetadata(this) + } - val sourceSetsWithMetadataCompilations = - project.multiplatformExtensionOrNull?.targets?.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)?.compilations?.associate { - it.defaultSourceSet to it - } ?: return null +private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformExtension): KotlinProjectStructureMetadata { + val project = extension.project + require(!project.hasKpmModel) { "this function only works with the stable plugin" } + require(project.state.executed) { "Cannot build 'KotlinProjectStructureMetadata' during project configuration phase" } + + val sourceSetsWithMetadataCompilations = extension.targets + .getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME) + .compilations.associateBy { it.defaultSourceSet } val publishedVariantsNamesWithCompilation = getPublishedPlatformCompilations(project).mapKeys { it.key.name } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt index c6e18b34425..99ce93102a6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt @@ -8,8 +8,8 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.artifacts.result.ResolvedComponentResult +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules import org.jetbrains.kotlin.project.model.KpmModuleIdentifier @@ -35,7 +35,8 @@ internal class ProjectMppDependencyProjectStructureMetadataExtractor( dependencyProject.hasKpmModel -> buildProjectStructureMetadata( dependencyProject.kpmModules.single { it.moduleIdentifier == moduleIdentifier } ) - else -> buildKotlinProjectStructureMetadata(dependencyProject) + + else -> dependencyProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata } } } 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 9a95a06d59c..a87366e4520 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 @@ -496,7 +496,7 @@ internal fun Project.createGenerateProjectStructureMetadataTask(module: GradleKp internal fun Project.createGenerateProjectStructureMetadataTask(): TaskProvider = project.registerTask(lowerCamelCaseName("generateProjectStructureMetadata")) { task -> - task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) } + task.lazyKotlinProjectStructureMetadata = lazy { project.multiplatformExtension.kotlinProjectStructureMetadata } } internal interface ResolvedMetadataFilesProvider { diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/JvmAndAndroidIntermediateSourceSetTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/JvmAndAndroidIntermediateSourceSetTest.kt index a5958122533..d840ca3cc1a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/JvmAndAndroidIntermediateSourceSetTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/JvmAndAndroidIntermediateSourceSetTest.kt @@ -3,8 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -/* Associate compilations are not yet supported by the IDE. KT-34102 */ -@file:Suppress("invisible_reference", "invisible_member", "FunctionName", "DuplicatedCode") +@file:Suppress("FunctionName") package org.jetbrains.kotlin.gradle @@ -17,7 +16,7 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation -import org.jetbrains.kotlin.gradle.plugin.mpp.buildKotlinProjectStructureMetadata +import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinProjectStructureMetadata import kotlin.test.* class JvmAndAndroidIntermediateSourceSetTest { @@ -81,7 +80,7 @@ class JvmAndAndroidIntermediateSourceSetTest { @Test fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in jvm variants`() { project.evaluate() - val metadata = assertNotNull(buildKotlinProjectStructureMetadata(project)) + val metadata = kotlin.kotlinProjectStructureMetadata assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmApiElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmRuntimeElements"].orEmpty()) } @@ -89,7 +88,7 @@ class JvmAndAndroidIntermediateSourceSetTest { @Test fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in android variants`() { project.evaluate() - val metadata = assertNotNull(buildKotlinProjectStructureMetadata(project)) + val metadata = kotlin.kotlinProjectStructureMetadata assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugApiElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugRuntimeElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["releaseApiElements"].orEmpty()) diff --git a/libraries/tools/kotlin-tooling-metadata/src/main/kotlin/org/jetbrains/kotlin/tooling/KotlinToolingMetadata.kt b/libraries/tools/kotlin-tooling-metadata/src/main/kotlin/org/jetbrains/kotlin/tooling/KotlinToolingMetadata.kt index 48a3e4eeba9..f9e46c5911c 100644 --- a/libraries/tools/kotlin-tooling-metadata/src/main/kotlin/org/jetbrains/kotlin/tooling/KotlinToolingMetadata.kt +++ b/libraries/tools/kotlin-tooling-metadata/src/main/kotlin/org/jetbrains/kotlin/tooling/KotlinToolingMetadata.kt @@ -72,5 +72,3 @@ data class KotlinToolingMetadata( const val currentSchemaVersion: String = "1.1.0" } } - -