Platform lib generator: Allow rebuilding platform libs

This commit is contained in:
Ilya Matveev
2020-02-11 17:32:21 +07:00
committed by Ilya Matveev
parent a4422c22e5
commit c7cd560228
@@ -59,16 +59,6 @@ private fun Logger.logStackTrace(error: Throwable) {
verbose(stringWriter.toString()) verbose(stringWriter.toString())
} }
private fun createTempDir(prefix: String, parent: File): File =
File(createTempDir(prefix, directory = JFile(parent.absolutePath)).absolutePath)
private sealed class ProcessingStatus {
object WAIT: ProcessingStatus()
object SUCCESS: ProcessingStatus()
object FAILED_DEPENDENCIES: ProcessingStatus()
class FAIL(val error: Throwable) : ProcessingStatus()
}
// TODO: Use Distribution's paths after compiler update. // TODO: Use Distribution's paths after compiler update.
fun generatePlatformLibraries(args: Array<String>) { fun generatePlatformLibraries(args: Array<String>) {
// IMPORTANT! These command line keys are used by the Gradle plugin to configure platform libraries generation, // IMPORTANT! These command line keys are used by the Gradle plugin to configure platform libraries generation,
@@ -122,6 +112,10 @@ fun generatePlatformLibraries(args: Array<String>) {
description = "An argument passed to compiler during cache building. Used only if -cache-directory is specified." description = "An argument passed to compiler during cache building. Used only if -cache-directory is specified."
).multiple() ).multiple()
val rebuild by argParser.option(
ArgType.Boolean, fullName = "rebuild", description = "Rebuild already existing libraries"
).default(false)
argParser.parse(args) argParser.parse(args)
val distribution = customerDistribution() val distribution = customerDistribution()
@@ -147,18 +141,44 @@ fun generatePlatformLibraries(args: Array<String>) {
val logger = Logger(if (verbose) Logger.Level.VERBOSE else Logger.Level.NORMAL) val logger = Logger(if (verbose) Logger.Level.VERBOSE else Logger.Level.NORMAL)
val cacheInfo = cacheDirectory?.let { CacheInfo(it, cacheKind, cacheArgs) }
generatePlatformLibraries( generatePlatformLibraries(
target, mode, target, mode,
inputDirectory, outputDirectory, DirectoriesInfo(inputDirectory, outputDirectory, stdlibFile), cacheInfo,
saveTemps, cacheDirectory, stdlibFile, rebuild, saveTemps, logger
cacheKind, cacheArgs, logger
) )
} }
private sealed class ProcessingStatus {
object WAIT: ProcessingStatus()
object SUCCESS: ProcessingStatus()
object FAILED_DEPENDENCIES: ProcessingStatus()
class FAIL(val error: Throwable) : ProcessingStatus()
}
private data class DirectoriesInfo(val inputDirectory: File, val outputDirectory: File, val stdlib: File)
private data class CacheInfo(val cacheDirectory: File, val cacheKind: String, val cacheArgs: List<String>)
private class DefFile(val name: String, val depends: MutableList<DefFile>) { private class DefFile(val name: String, val depends: MutableList<DefFile>) {
override fun toString(): String = "$name: [${depends.joinToString(separator = ", ") { it.name }}]" override fun toString(): String = "$name: [${depends.joinToString(separator = ", ") { it.name }}]"
} }
private fun createTempDir(prefix: String, parent: File): File =
File(createTempDir(prefix, directory = JFile(parent.absolutePath)).absolutePath)
private fun File.deleteAtomicallyIfPossible(tmpDirectory: File) {
// Try to atomically delete the old directory.
val tmpToDelete = createTempFile(directory = JFile(tmpDirectory.absolutePath))
if (renameAtomic(this.absolutePath, tmpToDelete.absolutePath, replaceExisting = true)) {
tmpToDelete.deleteRecursively()
} else {
// Can't move to a tmp directory -> delete in a regular way.
this.deleteRecursively()
}
}
private fun topoSort(defFiles: List<DefFile>): List<DefFile> { private fun topoSort(defFiles: List<DefFile>): List<DefFile> {
// Do DFS toposort. // Do DFS toposort.
val markGray = mutableSetOf<DefFile>() val markGray = mutableSetOf<DefFile>()
@@ -188,15 +208,15 @@ private fun generateLibrary(
target: KonanTarget, target: KonanTarget,
mode: String, mode: String,
def: DefFile, def: DefFile,
inputDirectory: File, directories: DirectoriesInfo,
outputDirectory: File,
tmpDirectory: File, tmpDirectory: File,
rebuild: Boolean,
logger: Logger logger: Logger
) { ) = with(directories) {
val defFile = inputDirectory.child("${def.name}.def") val defFile = inputDirectory.child("${def.name}.def")
val outKlib = outputDirectory.child(def.name) val outKlib = outputDirectory.child(def.name)
if (outKlib.exists) { if (outKlib.exists && !rebuild) {
logger.verbose("Skip generating ${def.name} as it's already generated") logger.verbose("Skip generating ${def.name} as it's already generated")
return return
} }
@@ -217,6 +237,10 @@ private fun generateLibrary(
logger.verbose("Run cinterop with args: ${cinteropArgs.joinToString(separator = " ")}") logger.verbose("Run cinterop with args: ${cinteropArgs.joinToString(separator = " ")}")
invokeInterop("native", cinteropArgs)?.let { K2Native.mainNoExit(it) } invokeInterop("native", cinteropArgs)?.let { K2Native.mainNoExit(it) }
if (rebuild) {
outKlib.deleteAtomicallyIfPossible(tmpDirectory)
}
// Atomically move the generated library to the destination path. // Atomically move the generated library to the destination path.
if (!renameAtomic(tmpKlib.absolutePath, outKlib.absolutePath, replaceExisting = false)) { if (!renameAtomic(tmpKlib.absolutePath, outKlib.absolutePath, replaceExisting = false)) {
tmpKlib.deleteRecursively() tmpKlib.deleteRecursively()
@@ -241,17 +265,20 @@ private fun buildCache(
target: KonanTarget, target: KonanTarget,
def: DefFile, def: DefFile,
outputDirectory: File, outputDirectory: File,
cacheDirectory: File, cacheInfo: CacheInfo,
cacheKind: String, rebuild: Boolean,
cacheArgs: List<String>,
logger: Logger logger: Logger
) { ) = with(cacheInfo) {
val cacheFile = getCacheFile(def.name, target, cacheDirectory, cacheKind) val cacheFile = getCacheFile(def.name, target, cacheDirectory, cacheKind)
if (cacheFile.exists) { if (cacheFile.exists && !rebuild) {
logger.verbose("Skip precompiling ${def.name} as it's already precompiled") logger.verbose("Skip precompiling ${def.name} as it's already precompiled")
return return
} }
if (rebuild) {
cacheFile.delete()
}
val compilerArgs = arrayOf( val compilerArgs = arrayOf(
"-p", cacheKind, "-p", cacheKind,
"-target", target.visibleName, "-target", target.visibleName,
@@ -267,11 +294,9 @@ private fun buildCache(
private fun buildStdlibCache( private fun buildStdlibCache(
target: KonanTarget, target: KonanTarget,
stdlib: File, stdlib: File,
cacheDirectory: File, cacheInfo: CacheInfo,
cacheKind: String,
cacheArgs: List<String>,
logger: Logger logger: Logger
) { ) = with(cacheInfo) {
val stdlibCacheFile = getCacheFile("stdlib", target, cacheDirectory, cacheKind) val stdlibCacheFile = getCacheFile("stdlib", target, cacheDirectory, cacheKind)
if (stdlibCacheFile.exists) { if (stdlibCacheFile.exists) {
logger.verbose("Skip precompiling standard library as it's already precompiled") logger.verbose("Skip precompiling standard library as it's already precompiled")
@@ -291,17 +316,15 @@ private fun buildStdlibCache(
} }
private fun generatePlatformLibraries(target: KonanTarget, mode: String, private fun generatePlatformLibraries(target: KonanTarget, mode: String,
inputDirectory: File, outputDirectory: File, directories: DirectoriesInfo, cacheInfo: CacheInfo?,
saveTemps: Boolean, cacheDirectory: File?, stdlibFile: File, rebuild: Boolean, saveTemps: Boolean, logger: Logger) = with(directories) {
cacheKind: String, cacheArgs: List<String>, if (cacheInfo != null) {
logger: Logger) { buildStdlibCache(target, stdlib, cacheInfo, logger)
if (cacheDirectory != null) {
buildStdlibCache(target, stdlibFile, cacheDirectory, cacheKind, cacheArgs, logger)
} }
logger.verbose("Generating platform libraries from $inputDirectory to $outputDirectory for ${target.visibleName}") logger.verbose("Generating platform libraries from $inputDirectory to $outputDirectory for ${target.visibleName}")
if (cacheDirectory != null) { if (cacheInfo != null) {
logger.verbose("Precompiling platform libraries to $cacheDirectory (cache kind: $cacheKind)") logger.verbose("Precompiling platform libraries to ${cacheInfo.cacheDirectory} (cache kind: ${cacheInfo.cacheKind})")
} }
val tmpDirectory = createTempDir("build-", outputDirectory) val tmpDirectory = createTempDir("build-", outputDirectory)
@@ -359,9 +382,9 @@ private fun generatePlatformLibraries(target: KonanTarget, mode: String,
} }
logger.log("Processing ${def.name} (${countProcessed.incrementAndGet()}/$countTotal)...") logger.log("Processing ${def.name} (${countProcessed.incrementAndGet()}/$countTotal)...")
generateLibrary(target, mode, def, inputDirectory, outputDirectory, tmpDirectory, logger) generateLibrary(target, mode, def, directories, tmpDirectory, rebuild, logger)
if (cacheDirectory != null) { if (cacheInfo != null) {
buildCache(target, def, outputDirectory, cacheDirectory, cacheKind, cacheArgs, logger) buildCache(target, def, outputDirectory, cacheInfo, rebuild, logger)
} }
built[def] = ProcessingStatus.SUCCESS built[def] = ProcessingStatus.SUCCESS