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 5058c9731cf..c853f49b1ed 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 @@ -637,7 +637,7 @@ constructor( @get:Internal internal abstract val konanPropertiesService: Property - private val compileDependencyFiles = FilesWithResolvedDependencyGraph( + private val resolvedDependencyGraph = ResolvedDependencyGraph( project, project.configurations.getByName(compilation.compileDependencyConfigurationName) ) @@ -659,7 +659,7 @@ constructor( executionContext = executionContext, settings = cacheBuilderSettings, konanPropertiesService = konanPropertiesService.get() - ).buildCompilerArgs(compileDependencyFiles) + ).buildCompilerArgs(resolvedDependencyGraph) val buildArgs = buildKotlinNativeBinaryLinkerArgs( output, @@ -939,33 +939,47 @@ internal class CacheBuilder( private val partialLinkage: Boolean 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, dependency = dependency, artifact = null, + resolvedDependencyGraph = resolvedDependencyGraph, partialLinkage = partialLinkage ) private fun needCache(libraryPath: String) = libraryPath.startsWith(settings.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib") - private fun ensureDependencyPrecached(dependency: ResolvedDependency, visitedDependencies: MutableSet) { + private fun ResolvedDependencyGraph.ensureDependencyPrecached( + dependency: ResolvedDependencyResult, + visitedDependencies: MutableSet + ) { if (dependency in visitedDependencies) return - visitedDependencies += dependency - dependency.children.forEach { ensureDependencyPrecached(it, visitedDependencies) } - val artifactsToAddToCache = dependency.moduleArtifacts.filter { needCache(it.file.absolutePath) } + visitedDependencies += dependency + dependency + .selected + .dependencies + .filterIsInstance() + .forEach { ensureDependencyPrecached(it, visitedDependencies) } + + val artifactsToAddToCache = dependencyArtifacts(dependency).filter { needCache(it.file.absolutePath) } + if (artifactsToAddToCache.isEmpty()) return val dependenciesCacheDirectories = getDependenciesCacheDirectories( rootCacheDirectory = rootCacheDirectory, dependency = dependency, considerArtifact = false, + resolvedDependencyGraph = this, partialLinkage = partialLinkage ) ?: return - val cacheDirectory = getCacheDirectory(dependency) + val cacheDirectory = getCacheDirectory(this, dependency) cacheDirectory.mkdirs() val artifactsLibraries = artifactsToAddToCache @@ -1017,7 +1031,7 @@ internal class CacheBuilder( args += "-Xcache-directory=${it.absolutePath}" } getAllDependencies(dependency) - .flatMap { it.moduleArtifacts } + .flatMap { dependencyArtifacts(it) } .map { it.file } .filterKlibsPassedToCompiler() .forEach { @@ -1085,17 +1099,17 @@ internal class CacheBuilder( ensureCompilerProvidedLibPrecached(platformLibName, platformLibs, visitedLibs) } - fun buildCompilerArgs(compileDependencyFiles: FilesWithResolvedDependencyGraph): List = mutableListOf().apply { + fun buildCompilerArgs(resolvedDependencyGraph: ResolvedDependencyGraph): List = mutableListOf().apply { if (konanCacheKind != NativeCacheKind.NONE && !optimized && konanPropertiesService.cacheWorksFor(konanTarget)) { rootCacheDirectory.mkdirs() ensureCompilerProvidedLibsPrecached() add("-Xcache-directory=${rootCacheDirectory.absolutePath}") - val visitedDependencies = mutableSetOf() + val visitedDependencies = mutableSetOf() val allCacheDirectories = mutableSetOf() - for (root in compileDependencyFiles.graphRoot.firstLevelModuleDependencies) { - ensureDependencyPrecached(root, visitedDependencies) + for (root in resolvedDependencyGraph.root.dependencies.filterIsInstance()) { + resolvedDependencyGraph.ensureDependencyPrecached(root, visitedDependencies) for (dependency in listOf(root) + getAllDependencies(root)) { - val cacheDirectory = getCacheDirectory(dependency) + val cacheDirectory = getCacheDirectory(resolvedDependencyGraph, dependency) if (cacheDirectory.exists()) allCacheDirectories += cacheDirectory.absolutePath } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/cacheKlibUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/cacheKlibUtils.kt index 66181163ef4..64125593cfa 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/cacheKlibUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/cacheKlibUtils.kt @@ -5,8 +5,8 @@ package org.jetbrains.kotlin.gradle.utils -import org.gradle.api.artifacts.ResolvedArtifact -import org.gradle.api.artifacts.ResolvedDependency +import org.gradle.api.artifacts.result.ResolvedArtifactResult +import org.gradle.api.artifacts.result.ResolvedDependencyResult import org.gradle.api.logging.Logger import org.jetbrains.kotlin.library.resolveSingleFileKlib import org.jetbrains.kotlin.library.uniqueName @@ -14,14 +14,15 @@ import java.io.File import java.nio.charset.StandardCharsets import java.security.MessageDigest -fun getCacheDirectory( +internal fun getCacheDirectory( rootCacheDirectory: File, - dependency: ResolvedDependency, - artifact: ResolvedArtifact?, + dependency: ResolvedDependencyResult, + artifact: ResolvedArtifactResult?, + resolvedDependencyGraph: ResolvedDependencyGraph, partialLinkage: Boolean ): File { - val moduleCacheDirectory = File(rootCacheDirectory, dependency.moduleName) - val versionCacheDirectory = File(moduleCacheDirectory, dependency.moduleVersion) + val moduleCacheDirectory = File(rootCacheDirectory, dependency.selected.moduleVersion?.name ?: "undefined") + val versionCacheDirectory = File(moduleCacheDirectory, dependency.selected.moduleVersion?.version ?: "undefined") val uniqueName = artifact ?.let { if (libraryFilter(it)) @@ -40,16 +41,17 @@ fun getCacheDirectory( versionCacheDirectory.resolve(hash) } 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') } -private fun computeDependenciesHash(dependency: ResolvedDependency, partialLinkage: Boolean): String { +private fun computeDependenciesHash(dependency: ResolvedDependencyResult, resolvedDependencyGraph: ResolvedDependencyGraph, partialLinkage: Boolean): String { val hashedValue = buildString { if (partialLinkage) append("#__PL__#") - (dependency.moduleArtifacts + getAllDependencies(dependency).flatMap { it.moduleArtifacts }) + (listOf(dependency) + getAllDependencies(dependency)) + .flatMap { resolvedDependencyGraph.dependencyArtifacts(it) } .map { it.file.absolutePath } .distinct() .sortedBy { it } @@ -61,20 +63,22 @@ private fun computeDependenciesHash(dependency: ResolvedDependency, partialLinka return hash.toHexString() } -fun getDependenciesCacheDirectories( +internal fun getDependenciesCacheDirectories( rootCacheDirectory: File, - dependency: ResolvedDependency, + dependency: ResolvedDependencyResult, + resolvedDependencyGraph: ResolvedDependencyGraph, considerArtifact: Boolean, partialLinkage: Boolean ): List? { return getAllDependencies(dependency) .flatMap { childDependency -> - childDependency.moduleArtifacts.map { + resolvedDependencyGraph.dependencyArtifacts(childDependency).map { if (libraryFilter(it)) { val cacheDirectory = getCacheDirectory( rootCacheDirectory = rootCacheDirectory, dependency = childDependency, artifact = if (considerArtifact) it else null, + resolvedDependencyGraph = resolvedDependencyGraph, partialLinkage = partialLinkage ) if (!cacheDirectory.exists()) return null @@ -88,17 +92,17 @@ fun getDependenciesCacheDirectories( .filter { it.exists() } } -fun getAllDependencies(dependency: ResolvedDependency): Set { - val allDependencies = mutableSetOf() +internal fun getAllDependencies(dependency: ResolvedDependencyResult): Set { + val allDependencies = mutableSetOf() - fun traverseAllDependencies(dependency: ResolvedDependency) { + fun traverseAllDependencies(dependency: ResolvedDependencyResult) { if (dependency in allDependencies) return allDependencies.add(dependency) - dependency.children.forEach { traverseAllDependencies(it) } + dependency.selected.dependencies.filterIsInstance().forEach { traverseAllDependencies(it) } } - dependency.children.forEach { traverseAllDependencies(it) } + dependency.selected.dependencies.filterIsInstance().forEach { traverseAllDependencies(it) } return allDependencies } @@ -109,4 +113,4 @@ internal class GradleLoggerAdapter(private val gradleLogger: Logger) : org.jetbr 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") 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 6ad555bf5c9..19aea4b425a 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 @@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.utils import org.gradle.api.Project import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ResolvedConfiguration -import org.gradle.api.artifacts.ResolvedDependency +import org.gradle.api.artifacts.result.ResolvedArtifactResult import org.gradle.api.artifacts.result.ResolvedComponentResult +import org.gradle.api.artifacts.result.ResolvedDependencyResult import org.gradle.api.file.FileCollection import org.gradle.api.provider.Provider @@ -22,25 +22,29 @@ const val RUNTIME = "runtime" 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 ( val files: FileCollection, - val graphRootProvider: Provider + private val graphRootProvider: Provider, + private val artifactsProvider: Provider> ) { - 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 { + val componentId = dependency.selected.id + return artifactsByComponentId[componentId] ?: emptyList() + } companion object { - operator fun invoke(project: Project, configuration: Configuration) = FilesWithResolvedDependencyGraph( + operator fun invoke(project: Project, configuration: Configuration) = ResolvedDependencyGraph( 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 get() = - dependencies.filterIsInstance().toSet() \ No newline at end of file +} \ No newline at end of file