[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.
This commit is contained in:
sebastian.sellmair
2022-06-09 09:57:39 +02:00
committed by Space
parent d8b4a88400
commit 9c67276201
6 changed files with 26 additions and 21 deletions
@@ -126,7 +126,7 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
project.pluginManager.apply(ScriptingGradleSubplugin::class.java) project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
exportProjectStructureMetadataForOtherBuilds(project) exportProjectStructureMetadataForOtherBuilds(kotlinMultiplatformExtension)
SingleActionPerBuild.run(project.rootProject, "cleanup-processed-metadata") { SingleActionPerBuild.run(project.rootProject, "cleanup-processed-metadata") {
if (isConfigurationCacheAvailable(project.gradle)) { if (isConfigurationCacheAvailable(project.gradle)) {
@@ -148,10 +148,10 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
} }
private fun exportProjectStructureMetadataForOtherBuilds( private fun exportProjectStructureMetadataForOtherBuilds(
project: Project extension: KotlinMultiplatformExtension
) { ) {
GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(project) { GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(extension.project) {
checkNotNull(buildKotlinProjectStructureMetadata(project)) extension.kotlinProjectStructureMetadata
} }
} }
@@ -13,7 +13,7 @@ import org.gradle.api.Project
import org.gradle.api.tasks.Input import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested 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.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope 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.getPublishedPlatformCompilations
import org.jetbrains.kotlin.gradle.targets.metadata.isSharedNativeSourceSet import org.jetbrains.kotlin.gradle.targets.metadata.isSharedNativeSourceSet
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerCompositeMetadataJarBundling.cinteropMetadataDirectoryPath 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.Document
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.Node import org.w3c.dom.Node
@@ -138,13 +139,19 @@ data class KotlinProjectStructureMetadata(
} }
} }
internal fun buildKotlinProjectStructureMetadata(project: Project): KotlinProjectStructureMetadata? { internal val KotlinMultiplatformExtension.kotlinProjectStructureMetadata: KotlinProjectStructureMetadata
require(!project.hasKpmModel) { "this function only works with the stable plugin" } get() = project.extensions.extraProperties.getOrPut("org.jetbrains.kotlin.gradle.plugin.mpp.kotlinProjectStructureMetadata") {
buildKotlinProjectStructureMetadata(this)
}
val sourceSetsWithMetadataCompilations = private fun buildKotlinProjectStructureMetadata(extension: KotlinMultiplatformExtension): KotlinProjectStructureMetadata {
project.multiplatformExtensionOrNull?.targets?.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)?.compilations?.associate { val project = extension.project
it.defaultSourceSet to it require(!project.hasKpmModel) { "this function only works with the stable plugin" }
} ?: return null 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 } val publishedVariantsNamesWithCompilation = getPublishedPlatformCompilations(project).mapKeys { it.key.name }
@@ -8,8 +8,8 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedComponentResult 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.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.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
@@ -35,7 +35,8 @@ internal class ProjectMppDependencyProjectStructureMetadataExtractor(
dependencyProject.hasKpmModel -> buildProjectStructureMetadata( dependencyProject.hasKpmModel -> buildProjectStructureMetadata(
dependencyProject.kpmModules.single { it.moduleIdentifier == moduleIdentifier } dependencyProject.kpmModules.single { it.moduleIdentifier == moduleIdentifier }
) )
else -> buildKotlinProjectStructureMetadata(dependencyProject)
else -> dependencyProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata
} }
} }
} }
@@ -496,7 +496,7 @@ internal fun Project.createGenerateProjectStructureMetadataTask(module: GradleKp
internal fun Project.createGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> = internal fun Project.createGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> =
project.registerTask(lowerCamelCaseName("generateProjectStructureMetadata")) { task -> project.registerTask(lowerCamelCaseName("generateProjectStructureMetadata")) { task ->
task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) } task.lazyKotlinProjectStructureMetadata = lazy { project.multiplatformExtension.kotlinProjectStructureMetadata }
} }
internal interface ResolvedMetadataFilesProvider { internal interface ResolvedMetadataFilesProvider {
@@ -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. * 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("FunctionName")
@file:Suppress("invisible_reference", "invisible_member", "FunctionName", "DuplicatedCode")
package org.jetbrains.kotlin.gradle 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.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataCompilation 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.* import kotlin.test.*
class JvmAndAndroidIntermediateSourceSetTest { class JvmAndAndroidIntermediateSourceSetTest {
@@ -81,7 +80,7 @@ class JvmAndAndroidIntermediateSourceSetTest {
@Test @Test
fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in jvm variants`() { fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in jvm variants`() {
project.evaluate() project.evaluate()
val metadata = assertNotNull(buildKotlinProjectStructureMetadata(project)) val metadata = kotlin.kotlinProjectStructureMetadata
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmApiElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmApiElements"].orEmpty())
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmRuntimeElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["jvmRuntimeElements"].orEmpty())
} }
@@ -89,7 +88,7 @@ class JvmAndAndroidIntermediateSourceSetTest {
@Test @Test
fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in android variants`() { fun `KotlinProjectStructureMetadata jvmAndAndroidMain exists in android variants`() {
project.evaluate() project.evaluate()
val metadata = assertNotNull(buildKotlinProjectStructureMetadata(project)) val metadata = kotlin.kotlinProjectStructureMetadata
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugApiElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugApiElements"].orEmpty())
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugRuntimeElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["debugRuntimeElements"].orEmpty())
assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["releaseApiElements"].orEmpty()) assertTrue("jvmAndAndroidMain" in metadata.sourceSetNamesByVariantName["releaseApiElements"].orEmpty())
@@ -72,5 +72,3 @@ data class KotlinToolingMetadata(
const val currentSchemaVersion: String = "1.1.0" const val currentSchemaVersion: String = "1.1.0"
} }
} }