in skiko/buildSrc/src/main/kotlin/CompileSkikoCppTask.kt [111:203]
override fun execute(mode: ToolMode, args: ArgBuilder) {
val sourcesToCompile: Collection<File> = when (mode) {
is ToolMode.Incremental -> mode.newOrModifiedFiles()
is ToolMode.NonIncremental -> sourceFiles.files.also {
logger.warn("Performing non-incremental compilation: ${mode.reason}")
}
}
updateSourcesToOutputsMapping(sourcesToCompile)
val outDir = outDir.get().asFile
val compilerExecutablePath = findCompilerExecutable().absolutePath
val workQueue = workerExecutor.noIsolation()
val submittedWorks = HashSet<String>()
val sourceOutputPairs = sourcesToCompile.map { sourceFile ->
// check all output files and their parent dirs before compiling anything
val outputFile = sourceToOutputMapping[sourceFile]
?: error("Could not find output file for source file: $sourceFile")
outputFile.parentFile.mkdirs()
check(!outputFile.exists()) {
"Output file should not exist before compilation: '$outputFile'"
}
sourceFile to outputFile
}
val argFilesDir = compilerArgsRootDir.get().asFile
cleanDirs(argFilesDir)
val commonArgsFile = argFilesDir.parentFile.resolve("common-args.txt")
args.createArgFile(commonArgsFile)
logArgs("Compiler args", args, commonArgsFile)
for ((sourceFile, outputFile) in sourceOutputPairs) {
val workId = "Compiling '${sourceFile.absolutePath}'"
submittedWorks.add(workId)
val workArgs = args.copy {
// Replace slash for Windows paths
arg("-o", outputFile.absolutePath.replace("\\", "/"))
arg(value = sourceFile.absolutePath.replace("\\", "/"))
if (compiler.get().startsWith("clang")) {
// We use Clang-CL on Windows which doesn't directly support the -MJ flag.
// We have to use the /clang:-MJ"path" form instead.
when {
buildTargetOS.get().isWindows -> rawArg("/clang:-MJ\"" + outputFile.absolutePath + ".json\"")
else -> arg("-MJ", outputFile.absolutePath + ".json")
}
}
}
val argFile = run {
val relative = outputFile.parentFile.relativeTo(outDir).path
val argFileDir = argFilesDir.resolve(relative)
argFileDir.resolve("${outputFile.nameWithoutExtension}-args.txt")
}
workQueue.submit(RunExternalProcessWork::class.java) {
this.workId = workId
executable = compilerExecutablePath
workingDir = outDir
this.args = listOf(workArgs.createArgFile(argFile))
}
}
try {
workQueue.await()
} catch (e: WorkerExecutionException) {
for (work in submittedWorks) {
val result = RunExternalProcessWork.workResults[work]
if (result == null) {
logger.error("Error: no results for work '$work'")
} else if (result.failure != null) {
logger.warn("\n$work:")
result.log.flushTo(logger)
}
}
error("Some files were not compiled. Check the log for more details")
} finally {
for (work in submittedWorks) {
RunExternalProcessWork.workResults.remove(work)
}
// Create compile_commands.json to be able to open the project in Fleet. It is CLang convention (https://clang.llvm.org/docs/JSONCompilationDatabase.html#build-system-integration)
if (compiler.get().startsWith("clang")) {
val compileCommands = buildString {
appendLine("[")
append(sourceOutputPairs.joinToString(",\n") { (_, outputFile) ->
Files.readString(Path.of(outputFile.absolutePath + ".json")).trim().removeSuffix(",")
})
appendLine("]")
}
Files.writeString(outDir.toPath().resolve("compile_commands.json"), compileCommands)
}
}
}