Added shortcut option -add-cache for convenience
This commit is contained in:
@@ -94,7 +94,7 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
|
||||
val K2NativeCompilerArguments.isUsefulWithoutFreeArgs: Boolean
|
||||
get() = listTargets || listPhases || checkDependencies || !includes.isNullOrEmpty() ||
|
||||
!librariesToCache.isNullOrEmpty()
|
||||
!librariesToCache.isNullOrEmpty() || libraryToAddToCache != null
|
||||
|
||||
fun Array<String>?.toNonNullList(): List<String> {
|
||||
return this?.asList<String>() ?: listOf<String>()
|
||||
@@ -114,9 +114,9 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
with(KonanConfigKeys) {
|
||||
with(configuration) {
|
||||
|
||||
put(NODEFAULTLIBS, arguments.nodefaultlibs)
|
||||
put(NOENDORSEDLIBS, arguments.noendorsedlibs)
|
||||
put(NOSTDLIB, arguments.nostdlib)
|
||||
put(NODEFAULTLIBS, arguments.nodefaultlibs || !arguments.libraryToAddToCache.isNullOrEmpty())
|
||||
put(NOENDORSEDLIBS, arguments.noendorsedlibs || !arguments.libraryToAddToCache.isNullOrEmpty())
|
||||
put(NOSTDLIB, arguments.nostdlib || !arguments.libraryToAddToCache.isNullOrEmpty())
|
||||
put(NOPACK, arguments.nopack)
|
||||
put(NOMAIN, arguments.nomain)
|
||||
put(LIBRARY_FILES,
|
||||
@@ -218,7 +218,12 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
put(OBJC_GENERICS, arguments.objcGenerics)
|
||||
|
||||
put(LIBRARIES_TO_CACHE, parseLibrariesToCache(arguments, configuration, outputKind))
|
||||
put(CACHE_DIRECTORIES, arguments.cacheDirectories.toNonNullList())
|
||||
val libraryToAddToCache = parseLibraryToAddToCache(arguments, configuration, outputKind)
|
||||
if (libraryToAddToCache != null && !arguments.outputName.isNullOrEmpty())
|
||||
configuration.report(ERROR, "$ADD_CACHE already implicitly sets output file name")
|
||||
val cacheDirectories = arguments.cacheDirectories.toNonNullList()
|
||||
libraryToAddToCache?.let { put(LIBRARY_TO_ADD_TO_CACHE, it) }
|
||||
put(CACHE_DIRECTORIES, cacheDirectories)
|
||||
put(CACHED_LIBRARIES, parseCachedLibraries(arguments, configuration))
|
||||
}
|
||||
}
|
||||
@@ -342,6 +347,24 @@ private fun parseLibrariesToCache(
|
||||
return if (input.isNotEmpty() && !outputKind.isCache) {
|
||||
configuration.report(ERROR, "$MAKE_CACHE can't be used when not producing cache")
|
||||
emptyList()
|
||||
} else if (input.isNotEmpty() && !arguments.libraryToAddToCache.isNullOrEmpty()) {
|
||||
configuration.report(ERROR, "supplied both $MAKE_CACHE and $ADD_CACHE options")
|
||||
emptyList()
|
||||
} else {
|
||||
input
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseLibraryToAddToCache(
|
||||
arguments: K2NativeCompilerArguments,
|
||||
configuration: CompilerConfiguration,
|
||||
outputKind: CompilerOutputKind
|
||||
): String? {
|
||||
val input = arguments.libraryToAddToCache
|
||||
|
||||
return if (input != null && !outputKind.isCache) {
|
||||
configuration.report(ERROR, "$ADD_CACHE can't be used when not producing cache")
|
||||
null
|
||||
} else {
|
||||
input
|
||||
}
|
||||
|
||||
@@ -163,6 +163,14 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var librariesToCache: Array<String>? = null
|
||||
|
||||
@Argument(
|
||||
value = ADD_CACHE,
|
||||
valueDescription = "<path>",
|
||||
description = "Path to the library to be added to cache",
|
||||
delimiter = ""
|
||||
)
|
||||
var libraryToAddToCache: String? = null
|
||||
|
||||
@Argument(value = "-Xprint-bitcode", deprecatedName = "--print_bitcode", description = "Print llvm bitcode")
|
||||
var printBitCode: Boolean = false
|
||||
|
||||
@@ -248,4 +256,5 @@ const val EMBED_BITCODE_MARKER_FLAG = "-Xembed-bitcode-marker"
|
||||
const val STATIC_FRAMEWORK_FLAG = "-Xstatic-framework"
|
||||
const val INCLUDE_ARG = "-Xinclude"
|
||||
const val CACHED_LIBRARY = "-Xcached-library"
|
||||
const val MAKE_CACHE = "-Xmake-cache"
|
||||
const val MAKE_CACHE = "-Xmake-cache"
|
||||
const val ADD_CACHE = "-Xadd-cache"
|
||||
+40
-15
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
|
||||
|
||||
class CacheSupport(
|
||||
configuration: CompilerConfiguration,
|
||||
val configuration: CompilerConfiguration,
|
||||
resolvedLibraries: KotlinLibraryResolveResult,
|
||||
target: KonanTarget,
|
||||
produce: CompilerOutputKind
|
||||
@@ -23,6 +23,22 @@ class CacheSupport(
|
||||
// TODO: consider using [FeaturedLibraries.kt].
|
||||
private val fileToLibrary = allLibraries.associateBy { it.libraryFile }
|
||||
|
||||
private val implicitCacheDirectories = configuration.get(KonanConfigKeys.CACHE_DIRECTORIES)!!
|
||||
.map {
|
||||
File(it).takeIf { it.isDirectory }
|
||||
?: configuration.reportCompilationError("cache directory $it is not found or not a directory")
|
||||
}
|
||||
|
||||
internal fun tryGetImplicitOutput(): String? {
|
||||
val libraryToAddToCache = configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE) ?: return null
|
||||
// Put the resulting library in the first cache directory.
|
||||
val cacheDirectory = implicitCacheDirectories.firstOrNull() ?: return null
|
||||
val libraryToAddToCacheFile = File(libraryToAddToCache)
|
||||
val library = allLibraries.single { it.libraryFile == libraryToAddToCacheFile }
|
||||
return cacheDirectory.child(CachedLibraries.getCachedLibraryName(library)).absolutePath
|
||||
}
|
||||
|
||||
|
||||
internal val cachedLibraries: CachedLibraries = run {
|
||||
val explicitCacheFiles = configuration.get(KonanConfigKeys.CACHED_LIBRARIES)!!
|
||||
|
||||
@@ -33,12 +49,6 @@ class CacheSupport(
|
||||
library to cachePath
|
||||
}
|
||||
|
||||
val implicitCacheDirectories = configuration.get(KonanConfigKeys.CACHE_DIRECTORIES)!!
|
||||
.map {
|
||||
File(it).takeIf { it.isDirectory }
|
||||
?: configuration.reportCompilationError("cache directory $it is not found or not a directory")
|
||||
}
|
||||
|
||||
CachedLibraries(
|
||||
target = target,
|
||||
allLibraries = allLibraries,
|
||||
@@ -47,14 +57,29 @@ class CacheSupport(
|
||||
)
|
||||
}
|
||||
|
||||
internal val librariesToCache: Set<KotlinLibrary> = configuration.get(KonanConfigKeys.LIBRARIES_TO_CACHE)!!
|
||||
.map { File(it) }.map {
|
||||
fileToLibrary[it] ?: error("library to cache\n" +
|
||||
" ${it.absolutePath}\n" +
|
||||
"not found among resolved libraries:\n " +
|
||||
allLibraries.joinToString("\n ") { it.libraryFile.absolutePath })
|
||||
}.toSet()
|
||||
.also { if (!produce.isCache) check(it.isEmpty()) }
|
||||
private fun getLibrary(file: File) =
|
||||
fileToLibrary[file] ?: error("library to cache\n" +
|
||||
" ${file.absolutePath}\n" +
|
||||
"not found among resolved libraries:\n " +
|
||||
allLibraries.joinToString("\n ") { it.libraryFile.absolutePath })
|
||||
|
||||
internal val librariesToCache: Set<KotlinLibrary> = run {
|
||||
val libraryToAddToCachePath = configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE)
|
||||
if (libraryToAddToCachePath.isNullOrEmpty()) {
|
||||
configuration.get(KonanConfigKeys.LIBRARIES_TO_CACHE)!!
|
||||
.map { getLibrary(File(it)) }
|
||||
.toSet()
|
||||
.also { if (!produce.isCache) check(it.isEmpty()) }
|
||||
} else {
|
||||
val libraryToAddToCacheFile = File(libraryToAddToCachePath)
|
||||
val libraryToAddToCache = getLibrary(libraryToAddToCacheFile)
|
||||
val libraryCache = cachedLibraries.getLibraryCache(libraryToAddToCache)
|
||||
if (libraryCache == null)
|
||||
setOf(libraryToAddToCache)
|
||||
else
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// Ensure dependencies of every cached library are cached too:
|
||||
|
||||
+6
-2
@@ -35,7 +35,7 @@ internal class CachedLibraries(
|
||||
Cache(kind, explicitPath)
|
||||
} else {
|
||||
implicitCacheDirectories.firstNotNullResult { dir ->
|
||||
val baseName = "${library.uniqueName}-cache"
|
||||
val baseName = getCachedLibraryName(library)
|
||||
val dynamicFile = dir.child(getArtifactName(baseName, CompilerOutputKind.DYNAMIC_CACHE))
|
||||
val staticFile = dir.child(getArtifactName(baseName, CompilerOutputKind.STATIC_CACHE))
|
||||
|
||||
@@ -50,7 +50,7 @@ internal class CachedLibraries(
|
||||
cache?.let { library to it }
|
||||
}.toMap()
|
||||
|
||||
private fun getArtifactName(baseName: String, kind: CompilerOutputKind) =
|
||||
fun getArtifactName(baseName: String, kind: CompilerOutputKind) =
|
||||
"${kind.prefix(target)}$baseName${kind.suffix(target)}"
|
||||
|
||||
fun isLibraryCached(library: KotlinLibrary): Boolean =
|
||||
@@ -72,4 +72,8 @@ internal class CachedLibraries(
|
||||
Cache.Kind.DYNAMIC -> true
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getCachedLibraryName(library: KotlinLibrary): String = "${library.uniqueName}-cache"
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,8 +16,8 @@ import org.jetbrains.kotlin.library.SearchPathResolver
|
||||
import org.jetbrains.kotlin.library.isInterop
|
||||
import org.jetbrains.kotlin.library.toUnresolvedLibraries
|
||||
|
||||
internal fun Context.getExportedDependencies(): List<ModuleDescriptor> = getDescriptorsFromLibraries((config.exportedLibraries + config.includedLibraries).toSet())
|
||||
internal fun Context.getIncludedLibraryDescriptors(): List<ModuleDescriptor> = getDescriptorsFromLibraries(config.includedLibraries.toSet())
|
||||
internal fun Context.getExportedDependencies(): List<ModuleDescriptor> = getDescriptorsFromLibraries((config.resolve.exportedLibraries + config.resolve.includedLibraries).toSet())
|
||||
internal fun Context.getIncludedLibraryDescriptors(): List<ModuleDescriptor> = getDescriptorsFromLibraries(config.resolve.includedLibraries.toSet())
|
||||
|
||||
private fun Context.getDescriptorsFromLibraries(libraries: Set<KonanLibrary>) =
|
||||
moduleDescriptor.allDependencyModules.filter {
|
||||
|
||||
+27
-85
@@ -6,28 +6,29 @@
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.konan.*
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.MetaVersion
|
||||
import org.jetbrains.kotlin.konan.TempFiles
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.target.Distribution
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import kotlin.system.exitProcess
|
||||
import org.jetbrains.kotlin.library.toUnresolvedLibraries
|
||||
import org.jetbrains.kotlin.konan.CompilerVersion
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.resolver.impl.libraryResolver
|
||||
import org.jetbrains.kotlin.library.UnresolvedLibrary
|
||||
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
|
||||
|
||||
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||
|
||||
@@ -41,10 +42,6 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
internal val target = targetManager.target
|
||||
internal val phaseConfig = configuration.get(CLIConfigurationKeys.PHASE_CONFIG)!!
|
||||
|
||||
val infoArgsOnly = configuration.kotlinSourceRoots.isEmpty()
|
||||
&& configuration[KonanConfigKeys.INCLUDED_LIBRARIES].isNullOrEmpty()
|
||||
&& configuration[KonanConfigKeys.LIBRARIES_TO_CACHE].isNullOrEmpty()
|
||||
|
||||
// TODO: debug info generation mode and debug/release variant selection probably requires some refactoring.
|
||||
val debug: Boolean get() = configuration.getBoolean(KonanConfigKeys.DEBUG)
|
||||
val lightDebug: Boolean get() = configuration.getBoolean(KonanConfigKeys.LIGHT_DEBUG)
|
||||
@@ -76,83 +73,14 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
|
||||
internal val produceStaticFramework get() = configuration.getBoolean(KonanConfigKeys.STATIC_FRAMEWORK)
|
||||
|
||||
val outputFiles = OutputFiles(configuration.get(KonanConfigKeys.OUTPUT), target, produce)
|
||||
val tempFiles = TempFiles(outputFiles.outputName, configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR))
|
||||
|
||||
val outputFile = outputFiles.mainFile
|
||||
|
||||
val moduleId: String
|
||||
get() = configuration.get(KonanConfigKeys.MODULE_NAME) ?: File(outputFiles.outputName).name
|
||||
|
||||
internal val purgeUserLibs: Boolean
|
||||
get() = configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS)
|
||||
|
||||
private val libraryNames: List<String>
|
||||
get() = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
||||
internal val resolve = KonanLibrariesResolveSupport(configuration, target, distribution)
|
||||
|
||||
private val includedLibraryFiles
|
||||
get() = configuration.getList(KonanConfigKeys.INCLUDED_LIBRARIES).map { File(it) }
|
||||
internal val resolvedLibraries get() = resolve.resolvedLibraries
|
||||
|
||||
private val librariesToCacheFiles
|
||||
get() = configuration.getList(KonanConfigKeys.LIBRARIES_TO_CACHE).map { File(it) }
|
||||
|
||||
private val unresolvedLibraries = libraryNames.toUnresolvedLibraries
|
||||
|
||||
private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES)
|
||||
private val resolverLogger =
|
||||
object : Logger {
|
||||
private val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
override fun warning(message: String)= collector.report(STRONG_WARNING, message)
|
||||
override fun error(message: String) = collector.report(ERROR, message)
|
||||
override fun log(message: String) = collector.report(LOGGING, message)
|
||||
override fun fatal(message: String): Nothing {
|
||||
collector.report(ERROR, message)
|
||||
(collector as? GroupingMessageCollector)?.flush()
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
|
||||
private val compatibleCompilerVersions: List<CompilerVersion> =
|
||||
configuration.getList(KonanConfigKeys.COMPATIBLE_COMPILER_VERSIONS).map { it.parseCompilerVersion() }
|
||||
|
||||
private val resolver = defaultResolver(
|
||||
repositories,
|
||||
libraryNames.filter { it.contains(File.separator) },
|
||||
target,
|
||||
distribution,
|
||||
compatibleCompilerVersions,
|
||||
resolverLogger
|
||||
).libraryResolver()
|
||||
|
||||
// We pass included libraries by absolute paths to avoid repository-based resolution for them.
|
||||
// Strictly speaking such "direct" libraries should be specially handled by the resolver, not by KonanConfig.
|
||||
// But currently the resolver is in the middle of a complex refactoring so it was decided to avoid changes in its logic.
|
||||
// TODO: Handle included libraries in KonanLibraryResolver when it's refactored and moved into the big Kotlin repo.
|
||||
internal val resolvedLibraries by lazy {
|
||||
val additionalLibraryFiles = includedLibraryFiles + librariesToCacheFiles
|
||||
resolver.resolveWithDependencies(
|
||||
unresolvedLibraries + additionalLibraryFiles.map { UnresolvedLibrary(it.absolutePath, null) },
|
||||
noStdLib = configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
|
||||
noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS),
|
||||
noEndorsedLibs = configuration.getBoolean(KonanConfigKeys.NOENDORSEDLIBS)
|
||||
)
|
||||
}
|
||||
|
||||
internal val exportedLibraries by lazy {
|
||||
getExportedLibraries(configuration, resolvedLibraries, resolver.searchPathResolver, report = true)
|
||||
}
|
||||
|
||||
internal val coveredLibraries by lazy {
|
||||
getCoveredLibraries(configuration, resolvedLibraries, resolver.searchPathResolver)
|
||||
}
|
||||
|
||||
internal val includedLibraries by lazy {
|
||||
getIncludedLibraries(includedLibraryFiles, configuration, resolvedLibraries)
|
||||
}
|
||||
|
||||
internal val cacheSupport: CacheSupport by lazy {
|
||||
CacheSupport(configuration, resolvedLibraries, target, produce)
|
||||
}
|
||||
internal val cacheSupport = CacheSupport(configuration, resolvedLibraries, target, produce)
|
||||
|
||||
internal val cachedLibraries: CachedLibraries
|
||||
get() = cacheSupport.cachedLibraries
|
||||
@@ -160,6 +88,21 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
internal val librariesToCache: Set<KotlinLibrary>
|
||||
get() = cacheSupport.librariesToCache
|
||||
|
||||
val outputFiles =
|
||||
OutputFiles(configuration.get(KonanConfigKeys.OUTPUT) ?: cacheSupport.tryGetImplicitOutput(),
|
||||
target, produce)
|
||||
|
||||
val tempFiles = TempFiles(outputFiles.outputName, configuration.get(KonanConfigKeys.TEMPORARY_FILES_DIR))
|
||||
|
||||
val outputFile get() = outputFiles.mainFile
|
||||
|
||||
val moduleId: String
|
||||
get() = configuration.get(KonanConfigKeys.MODULE_NAME) ?: File(outputFiles.outputName).name
|
||||
|
||||
val infoArgsOnly = configuration.kotlinSourceRoots.isEmpty()
|
||||
&& configuration[KonanConfigKeys.INCLUDED_LIBRARIES].isNullOrEmpty()
|
||||
&& librariesToCache.isEmpty()
|
||||
|
||||
fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List<KonanLibrary> {
|
||||
if (moduleDescriptor == null) error("purgeUnneeded() only works correctly after resolve is over, and we have successfully marked package files as needed or not needed.")
|
||||
|
||||
@@ -206,5 +149,4 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||
|
||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||
+2
@@ -34,6 +34,8 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create<List<String>>("libraries included into produced framework API")
|
||||
val LIBRARIES_TO_CACHE: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create<List<String>>("paths to libraries that to be compiled to cache")
|
||||
val LIBRARY_TO_ADD_TO_CACHE: CompilerConfigurationKey<String?>
|
||||
= CompilerConfigurationKey.create<String?>("path to library that to be added to cache")
|
||||
val CACHE_DIRECTORIES: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create<List<String>>("paths to directories containing caches")
|
||||
val CACHED_LIBRARIES: CompilerConfigurationKey<Map<String, String>>
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.konan.CompilerVersion
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.parseCompilerVersion
|
||||
import org.jetbrains.kotlin.konan.target.Distribution
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.library.UnresolvedLibrary
|
||||
import org.jetbrains.kotlin.library.resolver.impl.libraryResolver
|
||||
import org.jetbrains.kotlin.library.toUnresolvedLibraries
|
||||
import org.jetbrains.kotlin.util.Logger
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class KonanLibrariesResolveSupport(
|
||||
configuration: CompilerConfiguration,
|
||||
target: KonanTarget,
|
||||
distribution: Distribution
|
||||
) {
|
||||
private val includedLibraryFiles =
|
||||
configuration.getList(KonanConfigKeys.INCLUDED_LIBRARIES).map { File(it) }
|
||||
|
||||
private val librariesToCacheFiles =
|
||||
configuration.getList(KonanConfigKeys.LIBRARIES_TO_CACHE).map { File(it) } +
|
||||
configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE).let {
|
||||
if (it.isNullOrEmpty()) emptyList() else listOf(File(it))
|
||||
}
|
||||
|
||||
private val libraryNames = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
||||
|
||||
private val unresolvedLibraries = libraryNames.toUnresolvedLibraries
|
||||
|
||||
private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES)
|
||||
private val resolverLogger =
|
||||
object : Logger {
|
||||
private val collector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
override fun warning(message: String)= collector.report(CompilerMessageSeverity.STRONG_WARNING, message)
|
||||
override fun error(message: String) = collector.report(CompilerMessageSeverity.ERROR, message)
|
||||
override fun log(message: String) = collector.report(CompilerMessageSeverity.LOGGING, message)
|
||||
override fun fatal(message: String): Nothing {
|
||||
collector.report(CompilerMessageSeverity.ERROR, message)
|
||||
(collector as? GroupingMessageCollector)?.flush()
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
|
||||
private val compatibleCompilerVersions: List<CompilerVersion> =
|
||||
configuration.getList(KonanConfigKeys.COMPATIBLE_COMPILER_VERSIONS).map { it.parseCompilerVersion() }
|
||||
|
||||
private val resolver = defaultResolver(
|
||||
repositories,
|
||||
libraryNames.filter { it.contains(File.separator) },
|
||||
target,
|
||||
distribution,
|
||||
compatibleCompilerVersions,
|
||||
resolverLogger
|
||||
).libraryResolver()
|
||||
|
||||
// We pass included libraries by absolute paths to avoid repository-based resolution for them.
|
||||
// Strictly speaking such "direct" libraries should be specially handled by the resolver, not by KonanConfig.
|
||||
// But currently the resolver is in the middle of a complex refactoring so it was decided to avoid changes in its logic.
|
||||
// TODO: Handle included libraries in KonanLibraryResolver when it's refactored and moved into the big Kotlin repo.
|
||||
internal val resolvedLibraries = run {
|
||||
val additionalLibraryFiles = includedLibraryFiles + librariesToCacheFiles
|
||||
resolver.resolveWithDependencies(
|
||||
unresolvedLibraries + additionalLibraryFiles.map { UnresolvedLibrary(it.absolutePath, null) },
|
||||
noStdLib = configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
|
||||
noDefaultLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS),
|
||||
noEndorsedLibs = configuration.getBoolean(KonanConfigKeys.NOENDORSEDLIBS)
|
||||
)
|
||||
}
|
||||
|
||||
internal val exportedLibraries =
|
||||
getExportedLibraries(configuration, resolvedLibraries, resolver.searchPathResolver, report = true)
|
||||
|
||||
internal val coveredLibraries =
|
||||
getCoveredLibraries(configuration, resolvedLibraries, resolver.searchPathResolver)
|
||||
|
||||
internal val includedLibraries =
|
||||
getIncludedLibraries(includedLibraryFiles, configuration, resolvedLibraries)
|
||||
}
|
||||
+25
-6
@@ -36,6 +36,22 @@ internal class Linker(val context: Context) {
|
||||
val includedBinaries = nativeDependencies.map { it.includedPaths }.flatten()
|
||||
val libraryProvidedLinkerFlags = nativeDependencies.map { it.linkerOpts }.flatten()
|
||||
runLinker(objectFiles, includedBinaries, libraryProvidedLinkerFlags)
|
||||
renameOutput()
|
||||
}
|
||||
|
||||
private fun renameOutput() {
|
||||
val libraryToAddToCache = context.configuration.get(KonanConfigKeys.LIBRARY_TO_ADD_TO_CACHE)
|
||||
if (context.config.produce.isCache && !libraryToAddToCache.isNullOrEmpty()) {
|
||||
val outputFiles = context.config.outputFiles
|
||||
val outputFile = java.io.File(outputFiles.mainFileMangled)
|
||||
val outputDsymBundle = java.io.File(outputFiles.mainFileMangled + ".dSYM")
|
||||
if (outputFile.renameTo(java.io.File(outputFiles.mainFile)))
|
||||
outputDsymBundle.renameTo(java.io.File(outputFiles.mainFile + ".dSYM"))
|
||||
else {
|
||||
outputFile.delete()
|
||||
outputDsymBundle.deleteRecursively()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun asLinkerArgs(args: List<String>): List<String> {
|
||||
@@ -58,12 +74,15 @@ internal class Linker(val context: Context) {
|
||||
private fun runLinker(objectFiles: List<ObjectFile>,
|
||||
includedBinaries: List<String>,
|
||||
libraryProvidedLinkerFlags: List<String>): ExecutableFile? {
|
||||
val frameworkLinkerArgs: List<String>
|
||||
val additionalLinkerArgs: List<String>
|
||||
val executable: String
|
||||
|
||||
if (context.config.produce != CompilerOutputKind.FRAMEWORK) {
|
||||
frameworkLinkerArgs = emptyList()
|
||||
executable = context.config.outputFile
|
||||
if (context.config.produce == CompilerOutputKind.DYNAMIC_CACHE && target.family.isAppleFamily)
|
||||
additionalLinkerArgs = listOf("-install_name", context.config.outputFiles.mainFile)
|
||||
else
|
||||
additionalLinkerArgs = emptyList()
|
||||
executable = context.config.outputFiles.mainFileMangled
|
||||
} else {
|
||||
val framework = File(context.config.outputFile)
|
||||
val dylibName = framework.name.removeSuffix(".framework")
|
||||
@@ -74,7 +93,7 @@ internal class Linker(val context: Context) {
|
||||
Family.OSX -> "Versions/A/$dylibName"
|
||||
else -> error(target)
|
||||
}
|
||||
frameworkLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath")
|
||||
additionalLinkerArgs = listOf("-install_name", "@rpath/${framework.name}/$dylibRelativePath")
|
||||
val dylibPath = framework.child(dylibRelativePath)
|
||||
dylibPath.parentFile.mkdirs()
|
||||
executable = dylibPath.absolutePath
|
||||
@@ -92,9 +111,9 @@ internal class Linker(val context: Context) {
|
||||
linkerArgs = asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
|
||||
BitcodeEmbedding.getLinkerOptions(context.config) +
|
||||
caches.dynamic +
|
||||
libraryProvidedLinkerFlags + frameworkLinkerArgs,
|
||||
libraryProvidedLinkerFlags + additionalLinkerArgs,
|
||||
optimize = optimize, debug = debug, kind = linkerOutput,
|
||||
outputDsymBundle = context.config.outputFile + ".dSYM",
|
||||
outputDsymBundle = context.config.outputFiles.mainFileMangled + ".dSYM",
|
||||
needsProfileLibrary = needsProfileLibrary).forEach {
|
||||
it.logWith(context::log)
|
||||
it.execute()
|
||||
|
||||
+31
-3
@@ -11,12 +11,13 @@ import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.visibleName
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
/**
|
||||
* Creates and stores terminal compiler outputs.
|
||||
*/
|
||||
class OutputFiles(outputPath: String?, target: KonanTarget, produce: CompilerOutputKind) {
|
||||
class OutputFiles(outputPath: String?, target: KonanTarget, val produce: CompilerOutputKind) {
|
||||
|
||||
private val prefix = produce.prefix(target)
|
||||
private val suffix = produce.suffix(target)
|
||||
@@ -33,6 +34,33 @@ class OutputFiles(outputPath: String?, target: KonanTarget, produce: CompilerOut
|
||||
* Main compiler's output file.
|
||||
*/
|
||||
val mainFile = outputName
|
||||
.prefixBaseNameIfNot(prefix)
|
||||
.suffixIfNot(suffix)
|
||||
.prefixBaseNameIfNeeded(prefix)
|
||||
.suffixIfNeeded(suffix)
|
||||
|
||||
val mainFileMangled = if (!produce.isCache) mainFile else {
|
||||
(outputName + Random.nextLong().toString())
|
||||
.prefixBaseNameIfNeeded(prefix)
|
||||
.suffixIfNeeded(suffix)
|
||||
}
|
||||
|
||||
private fun String.prefixBaseNameIfNeeded(prefix: String): String {
|
||||
return if (produce.isCache)
|
||||
prefixBaseNameAlways(prefix)
|
||||
else prefixBaseNameIfNot(prefix)
|
||||
}
|
||||
|
||||
private fun String.suffixIfNeeded(prefix: String): String {
|
||||
return if (produce.isCache)
|
||||
suffixAlways(prefix)
|
||||
else suffixIfNot(prefix)
|
||||
}
|
||||
|
||||
private fun String.prefixBaseNameAlways(prefix: String): String {
|
||||
val file = File(this).absoluteFile
|
||||
val name = file.name
|
||||
val directory = file.parent
|
||||
return "$directory/$prefix$name"
|
||||
}
|
||||
|
||||
private fun String.suffixAlways(suffix: String) = "$this$suffix"
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ internal class CoverageManager(val context: Context) {
|
||||
context.config.shouldCoverSources
|
||||
|
||||
private val librariesToCover: Set<String> =
|
||||
context.config.coveredLibraries.map { it.libraryName }.toSet()
|
||||
context.config.resolve.coveredLibraries.map { it.libraryName }.toSet()
|
||||
|
||||
private val llvmProfileFilenameGlobal = "__llvm_profile_filename"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user