[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)
exportProjectStructureMetadataForOtherBuilds(project)
exportProjectStructureMetadataForOtherBuilds(kotlinMultiplatformExtension)
SingleActionPerBuild.run(project.rootProject, "cleanup-processed-metadata") {
if (isConfigurationCacheAvailable(project.gradle)) {
@@ -148,10 +148,10 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
}
private fun exportProjectStructureMetadataForOtherBuilds(
project: Project
extension: KotlinMultiplatformExtension
) {
GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(project) {
checkNotNull(buildKotlinProjectStructureMetadata(project))
GlobalProjectStructureMetadataStorage.registerProjectStructureMetadata(extension.project) {
extension.kotlinProjectStructureMetadata
}
}
@@ -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 }
@@ -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
}
}
}
@@ -496,7 +496,7 @@ internal fun Project.createGenerateProjectStructureMetadataTask(module: GradleKp
internal fun Project.createGenerateProjectStructureMetadataTask(): TaskProvider<GenerateProjectStructureMetadata> =
project.registerTask(lowerCamelCaseName("generateProjectStructureMetadata")) { task ->
task.lazyKotlinProjectStructureMetadata = lazy { checkNotNull(buildKotlinProjectStructureMetadata(project)) }
task.lazyKotlinProjectStructureMetadata = lazy { project.multiplatformExtension.kotlinProjectStructureMetadata }
}
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.
*/
/* 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())
@@ -72,5 +72,3 @@ data class KotlinToolingMetadata(
const val currentSchemaVersion: String = "1.1.0"
}
}