From 6e29075c3c7c0a34bce40f180d993edb73def80f Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Wed, 15 Jun 2022 21:41:07 +0200 Subject: [PATCH] [Gradle] Introduce TransientLazy for ResolvedDependencyGraph Gradle Configuration Cache writer serialises objects that implement java.lang.Serializable interface. SynchronizedLazyImpl does implement it by initialising value before serialization. This can cause issues for GCC because after initialisation value can contain unsupported entities that Gradle can't save as Configuration Cache. Gradle can serialise lambdas so UnserializableLazy implementation benefits from it. --- .../targets/native/tasks/KotlinNativeTasks.kt | 2 +- .../kotlin/gradle/utils/Delegates.kt | 31 ++++++++++++++++++- .../kotlin/gradle/utils/configurations.kt | 12 +++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt index 960b427c451..04980ace821 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTasks.kt @@ -885,7 +885,7 @@ internal class CacheBuilder( val kotlinOptions: KotlinCommonToolOptions, val externalDependenciesArgs: List ) { - val rootCacheDirectory by lazy(rootCacheDirectoryProvider) + val rootCacheDirectory by UnserializableLazy(rootCacheDirectoryProvider) companion object { operator fun invoke( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/Delegates.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/Delegates.kt index 1a504afd3b5..37b4f371fd8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/Delegates.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/Delegates.kt @@ -35,4 +35,33 @@ fun provider( fun property( defaultValueProvider: () -> T -): PropertyDelegate = PropertyDelegate(defaultValueProvider) \ No newline at end of file +): PropertyDelegate = PropertyDelegate(defaultValueProvider) + +/** + * Similar to [SynchronizedLazyImpl] but doesn't implement [Serializable] in the way + * that value gets initialised upon serialisation. + * It is intended that [initializer] gets serialised. + * Reason: Sometimes Gradle Configuration Cache can't serialise some entities that + * are produced by [initializer] but is okay serialising [initializer] + */ +internal class TransientLazy( + private val initializer: () -> T +) : Lazy { + @Volatile + @Transient + private var _value: T? = null + override fun isInitialized(): Boolean = _value != null + override val value get(): T { + val v1 = _value + if (v1 != null) return v1 + + return synchronized(this) { + val v2 = _value + if (v2 == null) { + initializer().also { _value = it } + } else { + v2 + } + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/configurations.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/configurations.kt index e7e2475da44..09a1e48d475 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/configurations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/configurations.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.gradle.utils import org.gradle.api.Project +import org.gradle.api.artifacts.ArtifactCollection import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.result.DependencyResult import org.gradle.api.artifacts.result.ResolvedArtifactResult @@ -27,14 +28,14 @@ internal const val INTRANSITIVE = "intransitive" */ internal class ResolvedDependencyGraph private constructor ( - val files: FileCollection, private val graphRootProvider: Provider, - private val artifactsProvider: Provider> + private val artifactCollection: ArtifactCollection ) { val root get() = graphRootProvider.get() - val artifacts get() = artifactsProvider.get() + val files: FileCollection get() = artifactCollection.artifactFiles + val artifacts get() = artifactCollection.artifacts - val artifactsByComponentId by lazy { artifacts.groupBy { it.id.componentIdentifier } } + private val artifactsByComponentId by TransientLazy { artifacts.groupBy { it.id.componentIdentifier } } val allDependencies: List get() { fun DependencyResult.allDependenciesRecursive(): List = @@ -54,9 +55,8 @@ private constructor ( companion object { operator fun invoke(project: Project, configuration: Configuration) = ResolvedDependencyGraph( - files = project.files(configuration), graphRootProvider = configuration.incoming.resolutionResult.let { rr -> project.provider { rr.root } }, - artifactsProvider = configuration.incoming.artifacts.let { collection -> project.provider { collection.artifacts } } + artifactCollection = configuration.incoming.artifacts ) } } \ No newline at end of file