[Gradle, JS] Fix case with multiple artifacts in module

This commit is contained in:
Ilya Goncharov
2022-01-18 13:41:18 +03:00
committed by Space
parent bea2bc3980
commit 443c0bf74f
3 changed files with 101 additions and 21 deletions
@@ -0,0 +1 @@
kotlin.incremental.js.ir=false
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.targets.js.ir
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ResolvedArtifact
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
@@ -42,6 +43,9 @@ import org.jetbrains.kotlin.gradle.utils.getAllDependencies
import org.jetbrains.kotlin.gradle.utils.getCacheDirectory
import org.jetbrains.kotlin.gradle.utils.getDependenciesCacheDirectories
import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.library.resolveSingleFileKlib
import org.jetbrains.kotlin.library.uniqueName
import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
import java.io.File
@@ -260,10 +264,12 @@ internal class CacheBuilder(
.filter { it !in visitedDependenciesForCache }
.forEach { dependencyForCache ->
visitedDependenciesForCache.add(dependencyForCache)
val cacheDirectory = getCacheDirectory(rootCacheDirectory, dependencyForCache)
if (cacheDirectory.exists()) {
allCacheDirectories.add(cacheDirectory)
}
dependencyForCache.moduleArtifacts
.map {
getCacheDirectory(rootCacheDirectory, dependencyForCache, it, { libraryFilter(it.file) })
}
.filter { it.exists() }
.forEach { allCacheDirectories.add(it) }
}
}
}
@@ -301,20 +307,65 @@ internal class CacheBuilder(
val dependenciesCacheDirectories = getDependenciesCacheDirectories(
rootCacheDirectory,
dependency
dependency,
libraryFilter = { libraryFilter(it.file) }
) ?: return
val cacheDirectory = getCacheDirectory(rootCacheDirectory, dependency)
cacheDirectory.mkdirs()
val nameMap: MutableMap<String, ResolvedArtifact> = mutableMapOf()
val depsMap: MutableMap<ResolvedArtifact, MutableList<ResolvedArtifact>> = mutableMapOf()
val cacheMap: MutableMap<ResolvedArtifact, File> = mutableMapOf()
var newOrderArtifactsToAddToCache = mutableListOf<ResolvedArtifact>()
for (library in artifactsToAddToCache) {
if (artifactsToAddToCache.size > 1) {
artifactsToAddToCache.forEach {
val klib = resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File(it.file.absolutePath))
nameMap[klib.uniqueName] = it
}
artifactsToAddToCache.forEach { artifact ->
val klib = resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File(artifact.file.absolutePath))
klib.unresolvedDependencies
.forEach { depLib ->
val depName = depLib.path.substringAfterLast("/")
nameMap[depName]?.let {
val depsSet = depsMap.getOrPut(artifact) {
mutableListOf()
}
depsSet.add(it)
}
}
}
fun traverseDependency(library: ResolvedArtifact) {
depsMap[library]?.let {
it.forEach {
traverseDependency(it)
}
}
if (library !in newOrderArtifactsToAddToCache) {
newOrderArtifactsToAddToCache.add(library)
}
}
depsMap.forEach { key, deps ->
traverseDependency(key)
}
} else {
newOrderArtifactsToAddToCache = artifactsToAddToCache.toMutableList()
}
for (library in newOrderArtifactsToAddToCache) {
val cacheDirectory = getCacheDirectory(rootCacheDirectory, dependency, library, { libraryFilter(it.file) })
cacheDirectory.mkdirs()
cacheMap[library] = cacheDirectory
val additionalDependencies = depsMap[library] ?: emptyList()
val additionalCacheDirectories = if (additionalDependencies.isNotEmpty()) {
additionalDependencies.map { cacheMap.getValue(it) }
} else emptyList()
runCompiler(
library.file,
getAllDependencies(dependency)
.flatMap { it.moduleArtifacts }
(getAllDependencies(dependency)
.flatMap { it.moduleArtifacts } + additionalDependencies)
.map { it.file },
cacheDirectory,
dependenciesCacheDirectories
dependenciesCacheDirectories + additionalCacheDirectories
)
}
}
@@ -5,19 +5,42 @@
package org.jetbrains.kotlin.gradle.utils
import org.gradle.api.artifacts.ResolvedArtifact
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.library.resolveSingleFileKlib
import org.jetbrains.kotlin.library.uniqueName
import java.io.File
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
fun getCacheDirectory(
rootCacheDirectory: File,
dependency: ResolvedDependency
dependency: ResolvedDependency,
artifact: ResolvedArtifact? = null,
libraryFilter: (ResolvedArtifact) -> Boolean = { it.file.absolutePath.endsWith(".klib") }
): File {
val moduleCacheDirectory = File(rootCacheDirectory, dependency.moduleName)
val versionCacheDirectory = File(moduleCacheDirectory, dependency.moduleVersion)
return File(versionCacheDirectory, computeDependenciesHash(dependency))
val uniqueName = artifact
?.let {
if (libraryFilter(it))
it.file
else
null
}
?.let {
resolveSingleFileKlib(org.jetbrains.kotlin.konan.file.File(it.absolutePath))
}
?.uniqueName
val cacheDirectory = if (uniqueName != null) {
val digest = MessageDigest.getInstance("SHA-256")
val hash = digest.digest(uniqueName.toByteArray(StandardCharsets.UTF_8)).toHexString()
versionCacheDirectory.resolve(hash)
} else versionCacheDirectory
return File(cacheDirectory, computeDependenciesHash(dependency))
}
private fun ByteArray.toHexString() = joinToString("") { (0xFF and it.toInt()).toString(16).padStart(2, '0') }
@@ -36,17 +59,22 @@ private fun computeDependenciesHash(dependency: ResolvedDependency): String {
fun getDependenciesCacheDirectories(
rootCacheDirectory: File,
dependency: ResolvedDependency
dependency: ResolvedDependency,
libraryFilter: (ResolvedArtifact) -> Boolean = { it.file.absolutePath.endsWith(".klib") }
): List<File>? {
return getAllDependencies(dependency)
.map { childDependency ->
val hasKlibs = childDependency.moduleArtifacts.any { it.file.absolutePath.endsWith(".klib") }
val cacheDirectory = getCacheDirectory(rootCacheDirectory, childDependency)
// We can only compile klib to cache if all of its dependencies are also cached.
if (hasKlibs && !cacheDirectory.exists())
return null
cacheDirectory
.flatMap { childDependency ->
childDependency.moduleArtifacts.map {
if (libraryFilter(it)) {
val cacheDirectory = getCacheDirectory(rootCacheDirectory, childDependency, it, libraryFilter)
if (!cacheDirectory.exists()) return null
cacheDirectory
} else {
null
}
}
}
.filterNotNull()
.filter { it.exists() }
}