[K/N] Extract cache management in linker to a separate file
Also, more meaningful names.
This commit is contained in:
committed by
Space Team
parent
2f1e9844df
commit
e6081e5851
+55
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.target.LinkerOutputKind
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we should link static caches into an object file before running full linkage.
|
||||||
|
*/
|
||||||
|
internal fun shouldPerformPreLink(config: KonanConfig, caches: ResolvedCacheBinaries, linkerOutputKind: LinkerOutputKind): Boolean {
|
||||||
|
// Pre-link is only useful when producing static library. Otherwise its just a waste of time.
|
||||||
|
val isStaticLibrary = linkerOutputKind == LinkerOutputKind.STATIC_LIBRARY &&
|
||||||
|
config.isFinalBinary
|
||||||
|
val enabled = config.cacheSupport.preLinkCaches
|
||||||
|
val nonEmptyCaches = caches.static.isNotEmpty()
|
||||||
|
return isStaticLibrary && enabled && nonEmptyCaches
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of cache binaries that are required for the final artifact.
|
||||||
|
* [static] is a list of static libraries (e.g. "libcache.a")
|
||||||
|
* [dynamic] is a list of dynamic libraries (e.g. "libcache.dylib")
|
||||||
|
*/
|
||||||
|
internal class ResolvedCacheBinaries(val static: List<String>, val dynamic: List<String>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find binary files for compiler caches that are actually required for the linkage.
|
||||||
|
*/
|
||||||
|
internal fun resolveCacheBinaries(
|
||||||
|
cachedLibraries: CachedLibraries,
|
||||||
|
dependenciesTrackingResult: DependenciesTrackingResult,
|
||||||
|
): ResolvedCacheBinaries {
|
||||||
|
val staticCaches = mutableListOf<String>()
|
||||||
|
val dynamicCaches = mutableListOf<String>()
|
||||||
|
|
||||||
|
dependenciesTrackingResult.allCachedBitcodeDependencies.forEach { dependency ->
|
||||||
|
val library = dependency.library
|
||||||
|
val cache = cachedLibraries.getLibraryCache(library)
|
||||||
|
// Maybe turn it into a warning and continue linkage without caches?
|
||||||
|
?: error("Library $library is expected to be cached")
|
||||||
|
|
||||||
|
val list = when (cache.kind) {
|
||||||
|
CachedLibraries.Kind.DYNAMIC -> dynamicCaches
|
||||||
|
CachedLibraries.Kind.STATIC -> staticCaches
|
||||||
|
}
|
||||||
|
|
||||||
|
list += if (dependency.kind is DependenciesTracker.DependencyKind.CertainFiles && cache is CachedLibraries.Cache.PerFile)
|
||||||
|
dependency.kind.files.map { cache.getFileBinaryPath(it) }
|
||||||
|
else cache.binariesPaths
|
||||||
|
}
|
||||||
|
return ResolvedCacheBinaries(static = staticCaches, dynamic = dynamicCaches)
|
||||||
|
}
|
||||||
+6
-44
@@ -1,9 +1,6 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.ClassFieldsSerializer
|
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.EagerInitializedPropertySerializer
|
|
||||||
import org.jetbrains.kotlin.backend.konan.serialization.InlineFunctionBodyReferenceSerializer
|
|
||||||
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
||||||
import org.jetbrains.kotlin.konan.TempFiles
|
import org.jetbrains.kotlin.konan.TempFiles
|
||||||
import org.jetbrains.kotlin.konan.exec.Command
|
import org.jetbrains.kotlin.konan.exec.Command
|
||||||
@@ -166,33 +163,24 @@ internal class Linker(
|
|||||||
return executable
|
return executable
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldPerformPreLink(caches: CachesToLink, linkerOutputKind: LinkerOutputKind): Boolean {
|
|
||||||
// Pre-link is only useful when producing static library. Otherwise its just a waste of time.
|
|
||||||
val isStaticLibrary = linkerOutputKind == LinkerOutputKind.STATIC_LIBRARY &&
|
|
||||||
config.isFinalBinary
|
|
||||||
val enabled = config.cacheSupport.preLinkCaches
|
|
||||||
val nonEmptyCaches = caches.static.isNotEmpty()
|
|
||||||
return isStaticLibrary && enabled && nonEmptyCaches
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun determineLinkerInput(
|
private fun determineLinkerInput(
|
||||||
objectFiles: List<ObjectFile>,
|
objectFiles: List<ObjectFile>,
|
||||||
linkerOutputKind: LinkerOutputKind,
|
linkerOutputKind: LinkerOutputKind,
|
||||||
dependenciesTrackingResult: DependenciesTrackingResult,
|
dependenciesTrackingResult: DependenciesTrackingResult,
|
||||||
): LinkerInput {
|
): LinkerInput {
|
||||||
val caches = determineCachesToLink(context, dependenciesTrackingResult)
|
val caches = resolveCacheBinaries(context.config.cachedLibraries, dependenciesTrackingResult)
|
||||||
// Since we have several linker stages that involve caching,
|
// Since we have several linker stages that involve caching,
|
||||||
// we should detect cache usage early to report errors correctly.
|
// we should detect cache usage early to report errors correctly.
|
||||||
val cachingInvolved = caches.static.isNotEmpty() || caches.dynamic.isNotEmpty()
|
val cachingInvolved = caches.static.isNotEmpty() || caches.dynamic.isNotEmpty()
|
||||||
return when {
|
return when {
|
||||||
config.produce == CompilerOutputKind.STATIC_CACHE -> {
|
config.produce == CompilerOutputKind.STATIC_CACHE -> {
|
||||||
// Do not link static cache dependencies.
|
// Do not link static cache dependencies.
|
||||||
LinkerInput(objectFiles, CachesToLink(emptyList(), caches.dynamic), emptyList(), cachingInvolved)
|
LinkerInput(objectFiles, ResolvedCacheBinaries(emptyList(), caches.dynamic), emptyList(), cachingInvolved)
|
||||||
}
|
}
|
||||||
shouldPerformPreLink(caches, linkerOutputKind) -> {
|
shouldPerformPreLink(config, caches, linkerOutputKind) -> {
|
||||||
val preLinkResult = tempFiles.create("withStaticCaches", ".o").absolutePath
|
val preLinkResult = tempFiles.create("withStaticCaches", ".o").absolutePath
|
||||||
val preLinkCommands = linker.preLinkCommands(objectFiles + caches.static, preLinkResult)
|
val preLinkCommands = linker.preLinkCommands(objectFiles + caches.static, preLinkResult)
|
||||||
LinkerInput(listOf(preLinkResult), CachesToLink(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved)
|
LinkerInput(listOf(preLinkResult), ResolvedCacheBinaries(emptyList(), caches.dynamic), preLinkCommands, cachingInvolved)
|
||||||
}
|
}
|
||||||
else -> LinkerInput(objectFiles, caches, emptyList(), cachingInvolved)
|
else -> LinkerInput(objectFiles, caches, emptyList(), cachingInvolved)
|
||||||
}
|
}
|
||||||
@@ -201,33 +189,7 @@ internal class Linker(
|
|||||||
|
|
||||||
private class LinkerInput(
|
private class LinkerInput(
|
||||||
val objectFiles: List<ObjectFile>,
|
val objectFiles: List<ObjectFile>,
|
||||||
val caches: CachesToLink,
|
val caches: ResolvedCacheBinaries,
|
||||||
val preLinkCommands: List<Command>,
|
val preLinkCommands: List<Command>,
|
||||||
val cachingInvolved: Boolean
|
val cachingInvolved: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
private class CachesToLink(val static: List<String>, val dynamic: List<String>)
|
|
||||||
|
|
||||||
private fun determineCachesToLink(
|
|
||||||
context: PhaseContext,
|
|
||||||
dependenciesTrackingResult: DependenciesTrackingResult,
|
|
||||||
): CachesToLink {
|
|
||||||
val staticCaches = mutableListOf<String>()
|
|
||||||
val dynamicCaches = mutableListOf<String>()
|
|
||||||
|
|
||||||
dependenciesTrackingResult.allCachedBitcodeDependencies.forEach { dependency ->
|
|
||||||
val library = dependency.library
|
|
||||||
val cache = context.config.cachedLibraries.getLibraryCache(library)
|
|
||||||
?: error("Library $library is expected to be cached")
|
|
||||||
|
|
||||||
val list = when (cache.kind) {
|
|
||||||
CachedLibraries.Kind.DYNAMIC -> dynamicCaches
|
|
||||||
CachedLibraries.Kind.STATIC -> staticCaches
|
|
||||||
}
|
|
||||||
|
|
||||||
list += if (dependency.kind is DependenciesTracker.DependencyKind.CertainFiles && cache is CachedLibraries.Cache.PerFile)
|
|
||||||
dependency.kind.files.map { cache.getFileBinaryPath(it) }
|
|
||||||
else cache.binariesPaths
|
|
||||||
}
|
|
||||||
return CachesToLink(static = staticCaches, dynamic = dynamicCaches)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user