Skip to content

Commit a911c1d

Browse files
committed
Allow relative paths in output file map
1 parent 90bc104 commit a911c1d

File tree

2 files changed

+49
-14
lines changed

2 files changed

+49
-14
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public struct Driver {
4646
case subcommandPassedToDriver
4747
case relativeFrontendPath(String)
4848
}
49-
49+
5050
/// The set of environment variables that are visible to the driver and
5151
/// processes it launches. This is a hook for testing; in actual use
5252
/// it should be identical to the real environment.
@@ -233,10 +233,10 @@ public struct Driver {
233233
}
234234

235235
// Compute the working directory.
236+
let cwd = localFileSystem.currentWorkingDirectory
236237
workingDirectory = try parsedOptions.getLastArgument(.workingDirectory).map { workingDirectoryArg in
237-
let cwd = localFileSystem.currentWorkingDirectory
238-
return try cwd.map{ AbsolutePath(workingDirectoryArg.asSingle, relativeTo: $0) } ?? AbsolutePath(validating: workingDirectoryArg.asSingle)
239-
}
238+
try cwd.map { AbsolutePath(workingDirectoryArg.asSingle, relativeTo: $0) } ?? AbsolutePath(validating: workingDirectoryArg.asSingle)
239+
} ?? cwd
240240

241241
// Apply the working directory to the parsed options.
242242
if let workingDirectory = self.workingDirectory {
@@ -247,15 +247,22 @@ public struct Driver {
247247
let inputFiles = try Self.collectInputFiles(&self.parsedOptions)
248248
self.inputFiles = inputFiles
249249

250+
let outputFileMap: OutputFileMap?
250251
// Initialize an empty output file map, which will be populated when we start creating jobs.
251252
if let outputFileMapArg = parsedOptions.getLastArgument(.outputFileMap)?.asSingle {
252253
let path = try AbsolutePath(validating: outputFileMapArg)
253-
self.outputFileMap = try .load(file: path, diagnosticEngine: diagnosticEngine)
254+
outputFileMap = try .load(file: path, diagnosticEngine: diagnosticEngine)
255+
} else {
256+
outputFileMap = nil
254257
}
255-
else {
256-
self.outputFileMap = nil
258+
259+
if let workingDirectory = self.workingDirectory {
260+
self.outputFileMap = outputFileMap?.resolveRelativePaths(relativeTo: workingDirectory)
261+
} else {
262+
self.outputFileMap = outputFileMap
257263
}
258264

265+
259266
// Determine the compilation mode.
260267
self.compilerMode = Self.computeCompilerMode(&parsedOptions, driverKind: driverKind, diagnosticsEngine: diagnosticEngine)
261268

@@ -440,7 +447,7 @@ extension Driver {
440447
var isEscaping = false
441448
// Indicates if we are currently parsing quoted text.
442449
var quoted = false
443-
450+
444451
for char in line {
445452
// Backslash escapes to the next character.
446453
if char == #"\"#, !isEscaping {
@@ -479,7 +486,7 @@ extension Driver {
479486
return content.split { $0 == "\n" || $0 == "\r\n" }
480487
.flatMap { tokenizeResponseFileLine($0) }
481488
}
482-
489+
483490
/// Recursively expands the response files.
484491
/// - Parameter visitedResponseFiles: Set containing visited response files to detect recursive parsing.
485492
private static func expandResponseFiles(
@@ -1250,7 +1257,7 @@ extension Driver {
12501257
// This value will fail the isSwiftIdentifier test below.
12511258
moduleName = ""
12521259
}
1253-
1260+
12541261
func fallbackOrDiagnose(_ error: Diagnostic.Message) {
12551262
// FIXME: Current driver notes that this is a "fallback module name".
12561263
if compilerOutputType == nil || maybeBuildingExecutable(&parsedOptions, linkerOutputType: linkerOutputType) {
@@ -1329,7 +1336,7 @@ extension Driver {
13291336
sdkPath = try? toolchain.defaultSDKPath()?.pathString
13301337
}
13311338
}
1332-
1339+
13331340
// An empty string explicitly clears the SDK.
13341341
if sdkPath == "" {
13351342
sdkPath = nil
@@ -1442,7 +1449,7 @@ extension Driver {
14421449
#else
14431450
static let defaultToolchainType: Toolchain.Type = GenericUnixToolchain.self
14441451
#endif
1445-
1452+
14461453
static func computeToolchain(
14471454
_ explicitTarget: Triple?,
14481455
diagnosticsEngine: DiagnosticsEngine,

Sources/SwiftDriver/Driver/OutputFileMap.swift

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ public struct OutputFileMap: Equatable {
4747
try! existingOutput(inputFile: VirtualPath(path: ""), outputType: outputType)
4848
}
4949

50+
public func resolveRelativePaths(relativeTo absPath: AbsolutePath) -> OutputFileMap {
51+
let resolvedKeyValues: [(VirtualPath, [FileType : VirtualPath])] = entries.map {
52+
let resolvedKey: VirtualPath
53+
if ($0.key == .singleDep) {
54+
// Special case for single dependency record, leave it as is
55+
resolvedKey = $0.key
56+
} else {
57+
resolvedKey = $0.key.resolvedRelativePath(base: absPath)
58+
}
59+
let resolvedValue = $0.value.mapValues {
60+
$0.resolvedRelativePath(base: absPath)
61+
}
62+
return (resolvedKey, resolvedValue)
63+
}
64+
return OutputFileMap(entries: .init(resolvedKeyValues, uniquingKeysWith: { _,_ in
65+
fatalError("Paths collided after resolving")
66+
}))
67+
}
68+
5069
/// Load the output file map at the given path.
5170
public static func load(
5271
file: AbsolutePath,
@@ -156,9 +175,9 @@ fileprivate struct OutputFileMapJSON: Codable {
156175

157176
/// Converts into virtual path entries.
158177
func toVirtualOutputFileMap() throws -> [VirtualPath : [FileType : VirtualPath]] {
159-
Dictionary(uniqueKeysWithValues: try entries.map { input, entry in
178+
Dictionary(try entries.map { input, entry in
160179
(try VirtualPath(path: input), try entry.paths.mapValues(VirtualPath.init(path:)))
161-
})
180+
}, uniquingKeysWith: { $1 })
162181
}
163182

164183
/// Converts from virtual path entries
@@ -186,3 +205,12 @@ extension String {
186205
return self + "." + ext
187206
}
188207
}
208+
209+
extension VirtualPath {
210+
fileprivate func resolvedRelativePath(base: AbsolutePath) -> VirtualPath {
211+
guard case let .relative(relPath) = self else { return self }
212+
return .absolute(.init(base, relPath))
213+
}
214+
215+
fileprivate static let singleDep = VirtualPath.relative(.init(""))
216+
}

0 commit comments

Comments
 (0)