override fun execute()

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)
            }
        }
    }