[Gradle, Native] Propagate -Xpartial-linkage flag to compiler invocations that build static cache for 3rd-party and user libs

^KT-51441
This commit is contained in:
Dmitriy Dolovov
2022-03-27 22:44:50 +03:00
parent 7579be6c68
commit 053ddb51ce
2 changed files with 38 additions and 23 deletions
@@ -629,7 +629,7 @@ constructor(
} }
val externalDependenciesArgs = ExternalDependenciesBuilder(project, compilation).buildCompilerArgs() val externalDependenciesArgs = ExternalDependenciesBuilder(project, compilation).buildCompilerArgs()
val cacheArgs = CacheBuilder(project, binary, konanTarget, externalDependenciesArgs).buildCompilerArgs() val cacheArgs = CacheBuilder(project, binary, konanTarget, localKotlinOptions, externalDependenciesArgs).buildCompilerArgs()
val buildArgs = buildKotlinNativeBinaryLinkerArgs( val buildArgs = buildKotlinNativeBinaryLinkerArgs(
output, output,
@@ -837,6 +837,7 @@ internal class CacheBuilder(
val project: Project, val project: Project,
val binary: NativeBinary, val binary: NativeBinary,
val konanTarget: KonanTarget, val konanTarget: KonanTarget,
val kotlinOptions: KotlinCommonToolOptions,
val externalDependenciesArgs: List<String> val externalDependenciesArgs: List<String>
) { ) {
@@ -870,11 +871,15 @@ internal class CacheBuilder(
getRootCacheDirectory(File(project.konanHome), konanTarget, debuggable, konanCacheKind) getRootCacheDirectory(File(project.konanHome), konanTarget, debuggable, konanCacheKind)
} }
private fun getCacheDirectory( private val partialLinkage: Boolean
dependency: ResolvedDependency get() = PARTIAL_LINKAGE in kotlinOptions.freeCompilerArgs
): File {
return getCacheDirectory(rootCacheDirectory, dependency) private fun getCacheDirectory(dependency: ResolvedDependency): File = getCacheDirectory(
} rootCacheDirectory = rootCacheDirectory,
dependency = dependency,
artifact = null,
partialLinkage = partialLinkage
)
private fun needCache(libraryPath: String) = private fun needCache(libraryPath: String) =
libraryPath.startsWith(project.gradle.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib") libraryPath.startsWith(project.gradle.gradleUserHomeDir.absolutePath) && libraryPath.endsWith(".klib")
@@ -889,8 +894,10 @@ internal class CacheBuilder(
if (artifactsToAddToCache.isEmpty()) return if (artifactsToAddToCache.isEmpty()) return
val dependenciesCacheDirectories = getDependenciesCacheDirectories( val dependenciesCacheDirectories = getDependenciesCacheDirectories(
rootCacheDirectory, rootCacheDirectory = rootCacheDirectory,
dependency dependency = dependency,
considerArtifact = false,
partialLinkage = partialLinkage
) ?: return ) ?: return
val cacheDirectory = getCacheDirectory(dependency) val cacheDirectory = getCacheDirectory(dependency)
@@ -933,10 +940,10 @@ internal class CacheBuilder(
"-p", konanCacheKind.produce!!, "-p", konanCacheKind.produce!!,
"-target", target "-target", target
) )
if (debuggable) if (debuggable) args += "-g"
args += "-g"
args += konanPropertiesService.additionalCacheFlags(konanTarget) args += konanPropertiesService.additionalCacheFlags(konanTarget)
args += externalDependenciesArgs args += externalDependenciesArgs
if (partialLinkage) args += PARTIAL_LINKAGE
args += "-Xadd-cache=${library.libraryFile.absolutePath}" args += "-Xadd-cache=${library.libraryFile.absolutePath}"
args += "-Xcache-directory=${cacheDirectory.absolutePath}" args += "-Xcache-directory=${cacheDirectory.absolutePath}"
args += "-Xcache-directory=${rootCacheDirectory.absolutePath}" args += "-Xcache-directory=${rootCacheDirectory.absolutePath}"
@@ -1045,6 +1052,8 @@ internal class CacheBuilder(
cacheKind.outputKind?.let { cacheKind.outputKind?.let {
"${baseName}-cache" "${baseName}-cache"
} ?: error("No output for kind $cacheKind") } ?: error("No output for kind $cacheKind")
private const val PARTIAL_LINKAGE = "-Xpartial-linkage"
} }
} }
@@ -17,8 +17,8 @@ import java.security.MessageDigest
fun getCacheDirectory( fun getCacheDirectory(
rootCacheDirectory: File, rootCacheDirectory: File,
dependency: ResolvedDependency, dependency: ResolvedDependency,
artifact: ResolvedArtifact? = null, artifact: ResolvedArtifact?,
libraryFilter: (ResolvedArtifact) -> Boolean = { it.file.absolutePath.endsWith(".klib") } partialLinkage: Boolean
): File { ): File {
val moduleCacheDirectory = File(rootCacheDirectory, dependency.moduleName) val moduleCacheDirectory = File(rootCacheDirectory, dependency.moduleName)
val versionCacheDirectory = File(moduleCacheDirectory, dependency.moduleVersion) val versionCacheDirectory = File(moduleCacheDirectory, dependency.moduleVersion)
@@ -40,38 +40,42 @@ fun getCacheDirectory(
versionCacheDirectory.resolve(hash) versionCacheDirectory.resolve(hash)
} else versionCacheDirectory } else versionCacheDirectory
return File(cacheDirectory, computeDependenciesHash(dependency)) return File(cacheDirectory, computeDependenciesHash(dependency, 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): String { private fun computeDependenciesHash(dependency: ResolvedDependency, partialLinkage: Boolean): String {
val allArtifactsPaths = val hashedValue = buildString {
if (partialLinkage) append("#__PL__#")
(dependency.moduleArtifacts + getAllDependencies(dependency).flatMap { it.moduleArtifacts }) (dependency.moduleArtifacts + getAllDependencies(dependency).flatMap { it.moduleArtifacts })
.map { it.file.absolutePath } .map { it.file.absolutePath }
.distinct() .distinct()
.sortedBy { it } .sortedBy { it }
.joinToString("|") { it } .joinTo(this, separator = "|")
}
val digest = MessageDigest.getInstance("SHA-256") val digest = MessageDigest.getInstance("SHA-256")
val hash = digest.digest(allArtifactsPaths.toByteArray(StandardCharsets.UTF_8)) val hash = digest.digest(hashedValue.toByteArray(StandardCharsets.UTF_8))
return hash.toHexString() return hash.toHexString()
} }
fun getDependenciesCacheDirectories( fun getDependenciesCacheDirectories(
rootCacheDirectory: File, rootCacheDirectory: File,
dependency: ResolvedDependency, dependency: ResolvedDependency,
libraryFilter: (ResolvedArtifact) -> Boolean = { it.file.absolutePath.endsWith(".klib") }, considerArtifact: Boolean,
considerArtifact: Boolean = false partialLinkage: Boolean
): List<File>? { ): List<File>? {
return getAllDependencies(dependency) return getAllDependencies(dependency)
.flatMap { childDependency -> .flatMap { childDependency ->
childDependency.moduleArtifacts.map { childDependency.moduleArtifacts.map {
if (libraryFilter(it)) { if (libraryFilter(it)) {
val cacheDirectory = getCacheDirectory( val cacheDirectory = getCacheDirectory(
rootCacheDirectory, rootCacheDirectory = rootCacheDirectory,
childDependency, dependency = childDependency,
if (considerArtifact) it else null, artifact = if (considerArtifact) it else null,
libraryFilter partialLinkage = partialLinkage
) )
if (!cacheDirectory.exists()) return null if (!cacheDirectory.exists()) return null
cacheDirectory cacheDirectory
@@ -104,3 +108,5 @@ internal class GradleLoggerAdapter(private val gradleLogger: Logger) : org.jetbr
override fun error(message: String) = kotlin.error(message) override fun error(message: String) = kotlin.error(message)
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")