[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.
This commit is contained in:
Anton Lakotka
2022-06-15 21:41:07 +02:00
committed by Space
parent 2f5ae70cef
commit 6e29075c3c
3 changed files with 37 additions and 8 deletions
@@ -885,7 +885,7 @@ internal class CacheBuilder(
val kotlinOptions: KotlinCommonToolOptions,
val externalDependenciesArgs: List<String>
) {
val rootCacheDirectory by lazy(rootCacheDirectoryProvider)
val rootCacheDirectory by UnserializableLazy(rootCacheDirectoryProvider)
companion object {
operator fun invoke(
@@ -35,4 +35,33 @@ fun <T : Any> provider(
fun <T : Any> property(
defaultValueProvider: () -> T
): PropertyDelegate<T> = PropertyDelegate(defaultValueProvider)
): PropertyDelegate<T> = 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<T: Any>(
private val initializer: () -> T
) : Lazy<T> {
@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
}
}
}
}
@@ -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<ResolvedComponentResult>,
private val artifactsProvider: Provider<Set<ResolvedArtifactResult>>
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<DependencyResult> get() {
fun DependencyResult.allDependenciesRecursive(): List<DependencyResult> =
@@ -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
)
}
}