in Sources/SwiftDriver/Jobs/Planning.swift [773:832]
mutating func formBatchedJobs(_ jobs: [Job], showJobLifecycle: Bool) throws -> [Job] {
guard compilerMode.isBatchCompile else {
// Don't even go through the logic so as to not print out confusing
// "batched foobar" messages.
return jobs
}
let noncompileJobs = jobs.filter {$0.kind != .compile}
let compileJobs = jobs.filter {$0.kind == .compile}
let inputsAndJobs = compileJobs.flatMap { job in
job.primaryInputs.map {($0, job)}
}
let jobsByInput = Dictionary(uniqueKeysWithValues: inputsAndJobs)
// Try to preserve input order for easier testing
let inputsInOrder = inputFiles.filter {jobsByInput[$0] != nil}
let partitions = batchPartitions(
inputs: inputsInOrder,
showJobLifecycle: showJobLifecycle)
let outputType = parsedOptions.hasArgument(.embedBitcode)
? .llvmBitcode
: compilerOutputType
let inputsRequiringModuleTrace = Set(
compileJobs.filter { $0.outputs.contains {$0.type == .moduleTrace} }
.flatMap {$0.primaryInputs}
)
let batchedCompileJobs = try inputsInOrder.compactMap { anInput -> Job? in
let idx = partitions.assignment[anInput]!
let primaryInputs = partitions.partitions[idx]
guard primaryInputs[0] == anInput
else {
// This input file isn't the first
// file in the partition, skip it: it's been accounted for already.
return nil
}
if showJobLifecycle {
// Log life cycle for added batch job
primaryInputs.forEach {
diagnosticEngine
.emit(
.remark(
"Adding {compile: \($0.file.basename)} to batch \(idx)"))
}
let constituents = primaryInputs.map {$0.file.basename}.joined(separator: ", ")
diagnosticEngine
.emit(
.remark(
"Forming batch job from \(primaryInputs.count) constituents: \(constituents)"))
}
let constituentsEmittedModuleTrace = !inputsRequiringModuleTrace.intersection(primaryInputs).isEmpty
// no need to add job outputs again
return try compileJob(primaryInputs: primaryInputs,
outputType: outputType,
addJobOutputs: {_ in },
emitModuleTrace: constituentsEmittedModuleTrace)
}
return batchedCompileJobs + noncompileJobs
}