[Gradle] Replace usage of ResolvedConfiguration to ResolvedDependencyResult
ResolvedConfiguration is a legacy API that doesn't work with Gradle Configuration Cache. ResolvedDependencyResult is cacheable but lightweight.
This commit is contained in:
+28
-14
@@ -637,7 +637,7 @@ constructor(
|
|||||||
@get:Internal
|
@get:Internal
|
||||||
internal abstract val konanPropertiesService: Property<KonanPropertiesBuildService>
|
internal abstract val konanPropertiesService: Property<KonanPropertiesBuildService>
|
||||||
|
|
||||||
private val compileDependencyFiles = FilesWithResolvedDependencyGraph(
|
private val resolvedDependencyGraph = ResolvedDependencyGraph(
|
||||||
project,
|
project,
|
||||||
project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
project.configurations.getByName(compilation.compileDependencyConfigurationName)
|
||||||
)
|
)
|
||||||
@@ -659,7 +659,7 @@ constructor(
|
|||||||
executionContext = executionContext,
|
executionContext = executionContext,
|
||||||
settings = cacheBuilderSettings,
|
settings = cacheBuilderSettings,
|
||||||
konanPropertiesService = konanPropertiesService.get()
|
konanPropertiesService = konanPropertiesService.get()
|
||||||
).buildCompilerArgs(compileDependencyFiles)
|
).buildCompilerArgs(resolvedDependencyGraph)
|
||||||
|
|
||||||
val buildArgs = buildKotlinNativeBinaryLinkerArgs(
|
val buildArgs = buildKotlinNativeBinaryLinkerArgs(
|
||||||
output,
|
output,
|
||||||
@@ -939,33 +939,47 @@ internal class CacheBuilder(
|
|||||||
private val partialLinkage: Boolean
|
private val partialLinkage: Boolean
|
||||||
get() = PARTIAL_LINKAGE in settings.kotlinOptions.freeCompilerArgs
|
get() = PARTIAL_LINKAGE in settings.kotlinOptions.freeCompilerArgs
|
||||||
|
|
||||||
private fun getCacheDirectory(dependency: ResolvedDependency): File = getCacheDirectory(
|
private fun getCacheDirectory(
|
||||||
|
resolvedDependencyGraph: ResolvedDependencyGraph,
|
||||||
|
dependency: ResolvedDependencyResult
|
||||||
|
): File = getCacheDirectory(
|
||||||
rootCacheDirectory = rootCacheDirectory,
|
rootCacheDirectory = rootCacheDirectory,
|
||||||
dependency = dependency,
|
dependency = dependency,
|
||||||
artifact = null,
|
artifact = null,
|
||||||
|
resolvedDependencyGraph = resolvedDependencyGraph,
|
||||||
partialLinkage = partialLinkage
|
partialLinkage = partialLinkage
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun needCache(libraryPath: String) =
|
private fun needCache(libraryPath: String) =
|
||||||
libraryPath.startsWith(settings.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib")
|
libraryPath.startsWith(settings.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib")
|
||||||
|
|
||||||
private fun ensureDependencyPrecached(dependency: ResolvedDependency, visitedDependencies: MutableSet<ResolvedDependency>) {
|
private fun ResolvedDependencyGraph.ensureDependencyPrecached(
|
||||||
|
dependency: ResolvedDependencyResult,
|
||||||
|
visitedDependencies: MutableSet<ResolvedDependencyResult>
|
||||||
|
) {
|
||||||
if (dependency in visitedDependencies)
|
if (dependency in visitedDependencies)
|
||||||
return
|
return
|
||||||
visitedDependencies += dependency
|
|
||||||
dependency.children.forEach { ensureDependencyPrecached(it, visitedDependencies) }
|
|
||||||
|
|
||||||
val artifactsToAddToCache = dependency.moduleArtifacts.filter { needCache(it.file.absolutePath) }
|
visitedDependencies += dependency
|
||||||
|
dependency
|
||||||
|
.selected
|
||||||
|
.dependencies
|
||||||
|
.filterIsInstance<ResolvedDependencyResult>()
|
||||||
|
.forEach { ensureDependencyPrecached(it, visitedDependencies) }
|
||||||
|
|
||||||
|
val artifactsToAddToCache = dependencyArtifacts(dependency).filter { needCache(it.file.absolutePath) }
|
||||||
|
|
||||||
if (artifactsToAddToCache.isEmpty()) return
|
if (artifactsToAddToCache.isEmpty()) return
|
||||||
|
|
||||||
val dependenciesCacheDirectories = getDependenciesCacheDirectories(
|
val dependenciesCacheDirectories = getDependenciesCacheDirectories(
|
||||||
rootCacheDirectory = rootCacheDirectory,
|
rootCacheDirectory = rootCacheDirectory,
|
||||||
dependency = dependency,
|
dependency = dependency,
|
||||||
considerArtifact = false,
|
considerArtifact = false,
|
||||||
|
resolvedDependencyGraph = this,
|
||||||
partialLinkage = partialLinkage
|
partialLinkage = partialLinkage
|
||||||
) ?: return
|
) ?: return
|
||||||
|
|
||||||
val cacheDirectory = getCacheDirectory(dependency)
|
val cacheDirectory = getCacheDirectory(this, dependency)
|
||||||
cacheDirectory.mkdirs()
|
cacheDirectory.mkdirs()
|
||||||
|
|
||||||
val artifactsLibraries = artifactsToAddToCache
|
val artifactsLibraries = artifactsToAddToCache
|
||||||
@@ -1017,7 +1031,7 @@ internal class CacheBuilder(
|
|||||||
args += "-Xcache-directory=${it.absolutePath}"
|
args += "-Xcache-directory=${it.absolutePath}"
|
||||||
}
|
}
|
||||||
getAllDependencies(dependency)
|
getAllDependencies(dependency)
|
||||||
.flatMap { it.moduleArtifacts }
|
.flatMap { dependencyArtifacts(it) }
|
||||||
.map { it.file }
|
.map { it.file }
|
||||||
.filterKlibsPassedToCompiler()
|
.filterKlibsPassedToCompiler()
|
||||||
.forEach {
|
.forEach {
|
||||||
@@ -1085,17 +1099,17 @@ internal class CacheBuilder(
|
|||||||
ensureCompilerProvidedLibPrecached(platformLibName, platformLibs, visitedLibs)
|
ensureCompilerProvidedLibPrecached(platformLibName, platformLibs, visitedLibs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildCompilerArgs(compileDependencyFiles: FilesWithResolvedDependencyGraph): List<String> = mutableListOf<String>().apply {
|
fun buildCompilerArgs(resolvedDependencyGraph: ResolvedDependencyGraph): List<String> = mutableListOf<String>().apply {
|
||||||
if (konanCacheKind != NativeCacheKind.NONE && !optimized && konanPropertiesService.cacheWorksFor(konanTarget)) {
|
if (konanCacheKind != NativeCacheKind.NONE && !optimized && konanPropertiesService.cacheWorksFor(konanTarget)) {
|
||||||
rootCacheDirectory.mkdirs()
|
rootCacheDirectory.mkdirs()
|
||||||
ensureCompilerProvidedLibsPrecached()
|
ensureCompilerProvidedLibsPrecached()
|
||||||
add("-Xcache-directory=${rootCacheDirectory.absolutePath}")
|
add("-Xcache-directory=${rootCacheDirectory.absolutePath}")
|
||||||
val visitedDependencies = mutableSetOf<ResolvedDependency>()
|
val visitedDependencies = mutableSetOf<ResolvedDependencyResult>()
|
||||||
val allCacheDirectories = mutableSetOf<String>()
|
val allCacheDirectories = mutableSetOf<String>()
|
||||||
for (root in compileDependencyFiles.graphRoot.firstLevelModuleDependencies) {
|
for (root in resolvedDependencyGraph.root.dependencies.filterIsInstance<ResolvedDependencyResult>()) {
|
||||||
ensureDependencyPrecached(root, visitedDependencies)
|
resolvedDependencyGraph.ensureDependencyPrecached(root, visitedDependencies)
|
||||||
for (dependency in listOf(root) + getAllDependencies(root)) {
|
for (dependency in listOf(root) + getAllDependencies(root)) {
|
||||||
val cacheDirectory = getCacheDirectory(dependency)
|
val cacheDirectory = getCacheDirectory(resolvedDependencyGraph, dependency)
|
||||||
if (cacheDirectory.exists())
|
if (cacheDirectory.exists())
|
||||||
allCacheDirectories += cacheDirectory.absolutePath
|
allCacheDirectories += cacheDirectory.absolutePath
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-19
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.utils
|
package org.jetbrains.kotlin.gradle.utils
|
||||||
|
|
||||||
import org.gradle.api.artifacts.ResolvedArtifact
|
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||||
import org.gradle.api.artifacts.ResolvedDependency
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
||||||
import org.jetbrains.kotlin.library.uniqueName
|
import org.jetbrains.kotlin.library.uniqueName
|
||||||
@@ -14,14 +14,15 @@ import java.io.File
|
|||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
fun getCacheDirectory(
|
internal fun getCacheDirectory(
|
||||||
rootCacheDirectory: File,
|
rootCacheDirectory: File,
|
||||||
dependency: ResolvedDependency,
|
dependency: ResolvedDependencyResult,
|
||||||
artifact: ResolvedArtifact?,
|
artifact: ResolvedArtifactResult?,
|
||||||
|
resolvedDependencyGraph: ResolvedDependencyGraph,
|
||||||
partialLinkage: Boolean
|
partialLinkage: Boolean
|
||||||
): File {
|
): File {
|
||||||
val moduleCacheDirectory = File(rootCacheDirectory, dependency.moduleName)
|
val moduleCacheDirectory = File(rootCacheDirectory, dependency.selected.moduleVersion?.name ?: "undefined")
|
||||||
val versionCacheDirectory = File(moduleCacheDirectory, dependency.moduleVersion)
|
val versionCacheDirectory = File(moduleCacheDirectory, dependency.selected.moduleVersion?.version ?: "undefined")
|
||||||
val uniqueName = artifact
|
val uniqueName = artifact
|
||||||
?.let {
|
?.let {
|
||||||
if (libraryFilter(it))
|
if (libraryFilter(it))
|
||||||
@@ -40,16 +41,17 @@ fun getCacheDirectory(
|
|||||||
versionCacheDirectory.resolve(hash)
|
versionCacheDirectory.resolve(hash)
|
||||||
} else versionCacheDirectory
|
} else versionCacheDirectory
|
||||||
|
|
||||||
return File(cacheDirectory, computeDependenciesHash(dependency, partialLinkage))
|
return File(cacheDirectory, computeDependenciesHash(dependency, resolvedDependencyGraph, partialLinkage))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun ByteArray.toHexString() = joinToString("") { (0xFF and it.toInt()).toString(16).padStart(2, '0') }
|
internal fun ByteArray.toHexString() = joinToString("") { (0xFF and it.toInt()).toString(16).padStart(2, '0') }
|
||||||
|
|
||||||
private fun computeDependenciesHash(dependency: ResolvedDependency, partialLinkage: Boolean): String {
|
private fun computeDependenciesHash(dependency: ResolvedDependencyResult, resolvedDependencyGraph: ResolvedDependencyGraph, partialLinkage: Boolean): String {
|
||||||
val hashedValue = buildString {
|
val hashedValue = buildString {
|
||||||
if (partialLinkage) append("#__PL__#")
|
if (partialLinkage) append("#__PL__#")
|
||||||
|
|
||||||
(dependency.moduleArtifacts + getAllDependencies(dependency).flatMap { it.moduleArtifacts })
|
(listOf(dependency) + getAllDependencies(dependency))
|
||||||
|
.flatMap { resolvedDependencyGraph.dependencyArtifacts(it) }
|
||||||
.map { it.file.absolutePath }
|
.map { it.file.absolutePath }
|
||||||
.distinct()
|
.distinct()
|
||||||
.sortedBy { it }
|
.sortedBy { it }
|
||||||
@@ -61,20 +63,22 @@ private fun computeDependenciesHash(dependency: ResolvedDependency, partialLinka
|
|||||||
return hash.toHexString()
|
return hash.toHexString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDependenciesCacheDirectories(
|
internal fun getDependenciesCacheDirectories(
|
||||||
rootCacheDirectory: File,
|
rootCacheDirectory: File,
|
||||||
dependency: ResolvedDependency,
|
dependency: ResolvedDependencyResult,
|
||||||
|
resolvedDependencyGraph: ResolvedDependencyGraph,
|
||||||
considerArtifact: Boolean,
|
considerArtifact: Boolean,
|
||||||
partialLinkage: Boolean
|
partialLinkage: Boolean
|
||||||
): List<File>? {
|
): List<File>? {
|
||||||
return getAllDependencies(dependency)
|
return getAllDependencies(dependency)
|
||||||
.flatMap { childDependency ->
|
.flatMap { childDependency ->
|
||||||
childDependency.moduleArtifacts.map {
|
resolvedDependencyGraph.dependencyArtifacts(childDependency).map {
|
||||||
if (libraryFilter(it)) {
|
if (libraryFilter(it)) {
|
||||||
val cacheDirectory = getCacheDirectory(
|
val cacheDirectory = getCacheDirectory(
|
||||||
rootCacheDirectory = rootCacheDirectory,
|
rootCacheDirectory = rootCacheDirectory,
|
||||||
dependency = childDependency,
|
dependency = childDependency,
|
||||||
artifact = if (considerArtifact) it else null,
|
artifact = if (considerArtifact) it else null,
|
||||||
|
resolvedDependencyGraph = resolvedDependencyGraph,
|
||||||
partialLinkage = partialLinkage
|
partialLinkage = partialLinkage
|
||||||
)
|
)
|
||||||
if (!cacheDirectory.exists()) return null
|
if (!cacheDirectory.exists()) return null
|
||||||
@@ -88,17 +92,17 @@ fun getDependenciesCacheDirectories(
|
|||||||
.filter { it.exists() }
|
.filter { it.exists() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllDependencies(dependency: ResolvedDependency): Set<ResolvedDependency> {
|
internal fun getAllDependencies(dependency: ResolvedDependencyResult): Set<ResolvedDependencyResult> {
|
||||||
val allDependencies = mutableSetOf<ResolvedDependency>()
|
val allDependencies = mutableSetOf<ResolvedDependencyResult>()
|
||||||
|
|
||||||
fun traverseAllDependencies(dependency: ResolvedDependency) {
|
fun traverseAllDependencies(dependency: ResolvedDependencyResult) {
|
||||||
if (dependency in allDependencies)
|
if (dependency in allDependencies)
|
||||||
return
|
return
|
||||||
allDependencies.add(dependency)
|
allDependencies.add(dependency)
|
||||||
dependency.children.forEach { traverseAllDependencies(it) }
|
dependency.selected.dependencies.filterIsInstance<ResolvedDependencyResult>().forEach { traverseAllDependencies(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependency.children.forEach { traverseAllDependencies(it) }
|
dependency.selected.dependencies.filterIsInstance<ResolvedDependencyResult>().forEach { traverseAllDependencies(it) }
|
||||||
return allDependencies
|
return allDependencies
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,4 +113,4 @@ internal class GradleLoggerAdapter(private val gradleLogger: Logger) : org.jetbr
|
|||||||
override fun fatal(message: String): Nothing = kotlin.error(message)
|
override fun fatal(message: String): Nothing = kotlin.error(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun libraryFilter(artifact: ResolvedArtifact): Boolean = artifact.file.absolutePath.endsWith(".klib")
|
private fun libraryFilter(artifact: ResolvedArtifactResult): Boolean = artifact.file.absolutePath.endsWith(".klib")
|
||||||
|
|||||||
+18
-14
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.utils
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
import org.gradle.api.artifacts.ResolvedConfiguration
|
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||||
import org.gradle.api.artifacts.ResolvedDependency
|
|
||||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
|
|
||||||
@@ -22,25 +22,29 @@ const val RUNTIME = "runtime"
|
|||||||
internal const val INTRANSITIVE = "intransitive"
|
internal const val INTRANSITIVE = "intransitive"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gradle Configuration Cache-friendly holder of resolved Configuration
|
* Gradle Configuration Cache-friendly representation of resolved Configuration
|
||||||
*/
|
*/
|
||||||
class FilesWithResolvedDependencyGraph
|
internal class ResolvedDependencyGraph
|
||||||
private constructor (
|
private constructor (
|
||||||
val files: FileCollection,
|
val files: FileCollection,
|
||||||
val graphRootProvider: Provider<ResolvedComponentResult>
|
private val graphRootProvider: Provider<ResolvedComponentResult>,
|
||||||
|
private val artifactsProvider: Provider<Set<ResolvedArtifactResult>>
|
||||||
) {
|
) {
|
||||||
val graphRoot get() = graphRootProvider.get()
|
val root get() = graphRootProvider.get()
|
||||||
|
val artifacts get() = artifactsProvider.get()
|
||||||
|
|
||||||
|
val artifactsByComponentId by lazy { artifacts.groupBy { it.id.componentIdentifier } }
|
||||||
|
|
||||||
|
fun dependencyArtifacts(dependency: ResolvedDependencyResult): List<ResolvedArtifactResult> {
|
||||||
|
val componentId = dependency.selected.id
|
||||||
|
return artifactsByComponentId[componentId] ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
operator fun invoke(project: Project, configuration: Configuration) = FilesWithResolvedDependencyGraph(
|
operator fun invoke(project: Project, configuration: Configuration) = ResolvedDependencyGraph(
|
||||||
files = project.files(configuration),
|
files = project.files(configuration),
|
||||||
graphRootProvider = configuration.incoming.resolutionResult.let { rr -> project.provider { rr.root } }
|
graphRootProvider = configuration.incoming.resolutionResult.let { rr -> project.provider { rr.root } },
|
||||||
|
artifactsProvider = configuration.incoming.artifacts.let { collection -> project.provider { collection.artifacts } }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration Cache-friendly alternative of [ResolvedConfiguration.getFirstLevelModuleDependencies]
|
|
||||||
*/
|
|
||||||
internal val ResolvedComponentResult.firstLevelModuleDependencies: Set<ResolvedDependency> get() =
|
|
||||||
dependencies.filterIsInstance<ResolvedDependency>().toSet()
|
|
||||||
Reference in New Issue
Block a user