Skip to content

Commit e200d72

Browse files
[Caching] Path remapping support
Teach swift-driver to remap path when needed. This involves: * Infer SDK/toolchain related path that needs to remapped * Send path remap related arguments to swift-frontend for depscanning * Send reverse map to swift-frontend for diagnostics replay * Constructing the compilation command for main module using remapped path
1 parent 94317a7 commit e200d72

File tree

7 files changed

+264
-45
lines changed

7 files changed

+264
-45
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,10 @@ public struct Driver {
224224
/// Should use file lists for inputs (number of inputs exceeds `fileListThreshold`).
225225
let shouldUseInputFileList: Bool
226226

227-
/// VirtualPath for shared all sources file list. `nil` if unused.
228-
@_spi(Testing) public let allSourcesFileList: VirtualPath?
227+
/// VirtualPath for shared all sources file list. `nil` if unused. This is used as a cache for
228+
/// the file list computed during CompileJob creation and only holds valid to be query by tests
229+
/// after planning to build.
230+
@_spi(Testing) public var allSourcesFileList: VirtualPath? = nil
229231

230232
/// The mode in which the compiler will execute.
231233
@_spi(Testing) public let compilerMode: CompilerMode
@@ -272,6 +274,35 @@ public struct Driver {
272274
let enableCaching: Bool
273275
let useClangIncludeTree: Bool
274276

277+
/// Scanner prefix mapping.
278+
let scannerPrefixMap: [AbsolutePath: AbsolutePath]
279+
let scannerPrefixMapSDK: AbsolutePath?
280+
let scannerPrefixMapToolchain: AbsolutePath?
281+
lazy var prefixMapping: [(AbsolutePath, AbsolutePath)] = {
282+
var mapping: [(AbsolutePath, AbsolutePath)] = scannerPrefixMap.map {
283+
return ($0.key, $0.value)
284+
}
285+
do {
286+
guard isFrontendArgSupported(.scannerPrefixMap) else {
287+
return []
288+
}
289+
if let sdkMapping = scannerPrefixMapSDK,
290+
let sdkPath = absoluteSDKPath {
291+
mapping.append((sdkPath, sdkMapping))
292+
}
293+
if let toolchainMapping = scannerPrefixMapToolchain {
294+
let toolchainPath = try toolchain.executableDir.parentDirectory // usr
295+
.parentDirectory // toolchain
296+
mapping.append((toolchainPath, toolchainMapping))
297+
}
298+
// The mapping needs to be sorted so the mapping is determinisitic.
299+
// The sorting order is reversed so /tmp/tmp is preferred over /tmp in remapping.
300+
return mapping.sorted { $0.0 > $1.0 }
301+
} catch {
302+
return mapping.sorted { $0.0 > $1.0 }
303+
}
304+
}()
305+
275306
/// Code & data for incremental compilation. Nil if not running in incremental mode.
276307
/// Set during planning because needs the jobs to look at outputs.
277308
@_spi(Testing) public private(set) var incrementalCompilationState: IncrementalCompilationState? = nil
@@ -598,6 +629,17 @@ public struct Driver {
598629
let cachingEnableOverride = parsedOptions.hasArgument(.driverExplicitModuleBuild) && env.keys.contains("SWIFT_ENABLE_CACHING")
599630
self.enableCaching = parsedOptions.hasArgument(.cacheCompileJob) || cachingEnableOverride
600631
self.useClangIncludeTree = enableCaching && env.keys.contains("SWIFT_CACHING_USE_INCLUDE_TREE")
632+
self.scannerPrefixMap = try Self.computeScanningPrefixMapper(&parsedOptions)
633+
if let sdkMapping = parsedOptions.getLastArgument(.scannerPrefixMapSdk)?.asSingle {
634+
self.scannerPrefixMapSDK = try AbsolutePath(validating: sdkMapping)
635+
} else {
636+
self.scannerPrefixMapSDK = nil
637+
}
638+
if let toolchainMapping = parsedOptions.getLastArgument(.scannerPrefixMapToolchain)?.asSingle {
639+
self.scannerPrefixMapToolchain = try AbsolutePath(validating: toolchainMapping)
640+
} else {
641+
self.scannerPrefixMapToolchain = nil
642+
}
601643

602644
// Compute the working directory.
603645
workingDirectory = try parsedOptions.getLastArgument(.workingDirectory).map { workingDirectoryArg in
@@ -678,13 +720,6 @@ public struct Driver {
678720

679721
self.fileListThreshold = try Self.computeFileListThreshold(&self.parsedOptions, diagnosticsEngine: diagnosticsEngine)
680722
self.shouldUseInputFileList = inputFiles.count > fileListThreshold
681-
if shouldUseInputFileList {
682-
let swiftInputs = inputFiles.filter(\.type.isPartOfSwiftCompilation)
683-
self.allSourcesFileList = try VirtualPath.createUniqueFilelist(RelativePath(validating: "sources"),
684-
.list(swiftInputs.map(\.file)))
685-
} else {
686-
self.allSourcesFileList = nil
687-
}
688723

689724
self.lto = Self.ltoKind(&parsedOptions, diagnosticsEngine: diagnosticsEngine)
690725
// Figure out the primary outputs from the driver.
@@ -3502,4 +3537,18 @@ extension Driver {
35023537
}
35033538
return options
35043539
}
3540+
3541+
static func computeScanningPrefixMapper(_ parsedOptions: inout ParsedOptions) throws -> [AbsolutePath: AbsolutePath] {
3542+
var mapping: [AbsolutePath: AbsolutePath] = [:]
3543+
for opt in parsedOptions.arguments(for: .scannerPrefixMap) {
3544+
let pluginArg = opt.argument.asSingle.split(separator: "=", maxSplits: 1)
3545+
if pluginArg.count != 2 {
3546+
throw Error.invalidArgumentValue(Option.scannerPrefixMap.spelling, opt.argument.asSingle)
3547+
}
3548+
let key = try AbsolutePath(validating: String(pluginArg[0]))
3549+
let value = try AbsolutePath(validating: String(pluginArg[1]))
3550+
mapping[key] = value
3551+
}
3552+
return mapping
3553+
}
35053554
}

Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ public extension Driver {
124124
try commandLine.appendLast(.clangScannerModuleCachePath, from: &parsedOptions)
125125
}
126126

127+
if isFrontendArgSupported(.scannerPrefixMap) {
128+
// construct `-scanner-prefix-mapper` for scanner.
129+
for (key, value) in prefixMapping {
130+
commandLine.appendFlag(.scannerPrefixMap)
131+
commandLine.appendFlag(key.pathString + "=" + value.pathString)
132+
}
133+
}
134+
127135
// Pass on the input files
128136
commandLine.append(contentsOf: inputFiles.filter { $0.type == .swift }.map { .path($0.file) })
129137
return (inputs, commandLine)

Sources/SwiftDriver/Jobs/CompileJob.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,21 +112,26 @@ extension Driver {
112112
outputType: FileType?,
113113
commandLine: inout [Job.ArgTemplate])
114114
throws -> ([TypedVirtualPath], [TypedVirtualPath]) {
115-
let useInputFileList: Bool
116-
if let allSourcesFileList = allSourcesFileList {
117-
useInputFileList = true
115+
let useInputFileList = shouldUseInputFileList
116+
if let sourcesFileList = allSourcesFileList {
118117
commandLine.appendFlag(.filelist)
119-
commandLine.appendPath(allSourcesFileList)
120-
} else {
121-
useInputFileList = false
118+
commandLine.appendPath(sourcesFileList)
119+
} else if shouldUseInputFileList {
120+
let swiftInputs = inputFiles.filter(\.type.isPartOfSwiftCompilation)
121+
let remappedSourcesFileList = try VirtualPath.createUniqueFilelist(RelativePath(validating: "sources"),
122+
.list(swiftInputs.map{ return remapPath($0.file) }))
123+
// Remember the filelist created.
124+
self.allSourcesFileList = remappedSourcesFileList
125+
commandLine.appendFlag(.filelist)
126+
commandLine.appendPath(remappedSourcesFileList)
122127
}
123128

124129
let usePrimaryInputFileList = primaryInputs.count > fileListThreshold
125130
if usePrimaryInputFileList {
126131
// primary file list
127132
commandLine.appendFlag(.primaryFilelist)
128133
let fileList = try VirtualPath.createUniqueFilelist(RelativePath(validating: "primaryInputs"),
129-
.list(primaryInputs.map(\.file)))
134+
.list(primaryInputs.map{ return remapPath($0.file) }))
130135
commandLine.appendPath(fileList)
131136
}
132137

@@ -166,12 +171,11 @@ extension Driver {
166171
let isPrimary = usesPrimaryFileInputs && primaryInputFiles.contains(input)
167172
if isPrimary {
168173
if !usePrimaryInputFileList {
169-
commandLine.appendFlag(.primaryFile)
170-
commandLine.appendPath(input.file)
174+
try addPathOption(option: .primaryFile, path: input.file, to:&commandLine)
171175
}
172176
} else {
173177
if !useInputFileList {
174-
commandLine.appendPath(input.file)
178+
try addPathArgument(input.file, to: &commandLine)
175179
}
176180
}
177181

0 commit comments

Comments
 (0)