in Sources/SwiftDriver/Jobs/CompileJob.swift [104:218]
mutating func addCompileInputs(primaryInputs: [TypedVirtualPath],
indexFilePath: TypedVirtualPath?,
inputs: inout [TypedVirtualPath],
inputOutputMap: inout [TypedVirtualPath: [TypedVirtualPath]],
outputType: FileType?,
commandLine: inout [Job.ArgTemplate])
-> ([TypedVirtualPath], [TypedVirtualPath]) {
let useInputFileList: Bool
if let allSourcesFileList = allSourcesFileList {
useInputFileList = true
commandLine.appendFlag(.filelist)
commandLine.appendPath(allSourcesFileList)
} else {
useInputFileList = false
}
let usePrimaryInputFileList = primaryInputs.count > fileListThreshold
if usePrimaryInputFileList {
// primary file list
commandLine.appendFlag(.primaryFilelist)
let fileList = VirtualPath.createUniqueFilelist(RelativePath("primaryInputs"),
.list(primaryInputs.map(\.file)))
commandLine.appendPath(fileList)
}
let isTopLevel = isTopLevelOutput(type: outputType)
// If we will be passing primary files via -primary-file, form a set of primary input files so
// we can check more quickly.
let usesPrimaryFileInputs: Bool
// N.B. We use an array instead of a hashed collection like a set because
// TypedVirtualPaths are quite expensive to hash. To the point where a
// linear scan beats Set.contains by a factor of 4 for heavy workloads.
let primaryInputFiles: [TypedVirtualPath]
if compilerMode.usesPrimaryFileInputs {
assert(!primaryInputs.isEmpty)
usesPrimaryFileInputs = true
primaryInputFiles = primaryInputs
} else if let path = indexFilePath {
// If -index-file is used, we perform a single compile but pass the
// -index-file-path as a primary input file.
usesPrimaryFileInputs = true
primaryInputFiles = [path]
} else {
usesPrimaryFileInputs = false
primaryInputFiles = []
}
let isMultithreaded = numThreads > 0
// Add each of the input files.
var primaryOutputs: [TypedVirtualPath] = []
var primaryIndexUnitOutputs: [TypedVirtualPath] = []
var indexUnitOutputDiffers = false
let firstSwiftInput = inputs.count
for input in self.inputFiles where input.type.isPartOfSwiftCompilation {
inputs.append(input)
let isPrimary = usesPrimaryFileInputs && primaryInputFiles.contains(input)
if isPrimary {
if !usePrimaryInputFileList {
commandLine.appendFlag(.primaryFile)
commandLine.appendPath(input.file)
}
} else {
if !useInputFileList {
commandLine.appendPath(input.file)
}
}
// If there is a primary output or we are doing multithreaded compiles,
// add an output for the input.
if let outputType = outputType,
isPrimary || (!usesPrimaryFileInputs && isMultithreaded && outputType.isAfterLLVM) {
let output = computePrimaryOutput(for: input,
outputType: outputType,
isTopLevel: isTopLevel)
primaryOutputs.append(output)
inputOutputMap[input] = [output]
if let indexUnitOut = computeIndexUnitOutput(for: input, outputType: outputType, topLevel: isTopLevel) {
indexUnitOutputDiffers = true
primaryIndexUnitOutputs.append(indexUnitOut)
} else {
primaryIndexUnitOutputs.append(output)
}
}
}
// When not using primary file inputs or multithreading, add a single output.
if let outputType = outputType,
!usesPrimaryFileInputs && !(isMultithreaded && outputType.isAfterLLVM) {
let input = TypedVirtualPath(file: OutputFileMap.singleInputKey, type: inputs[firstSwiftInput].type)
let output = computePrimaryOutput(for: input,
outputType: outputType,
isTopLevel: isTopLevel)
primaryOutputs.append(output)
inputOutputMap[input] = [output]
if let indexUnitOut = computeIndexUnitOutput(for: input, outputType: outputType, topLevel: isTopLevel) {
indexUnitOutputDiffers = true
primaryIndexUnitOutputs.append(indexUnitOut)
} else {
primaryIndexUnitOutputs.append(output)
}
}
if !indexUnitOutputDiffers {
primaryIndexUnitOutputs.removeAll()
} else {
assert(primaryOutputs.count == primaryIndexUnitOutputs.count)
}
return (primaryOutputs, primaryIndexUnitOutputs)
}