Skip to content

Commit bc1d31b

Browse files
committed
Allow relative paths in output file map
1 parent 353940d commit bc1d31b

File tree

3 files changed

+75
-5
lines changed

3 files changed

+75
-5
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,19 @@ 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

259265
// Determine the compilation mode.

Sources/SwiftDriver/Driver/OutputFileMap.swift

Lines changed: 28 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+
// Special case for single dependency record, leave it as is
54+
if ($0.key == .relative(.init(""))) {
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,10 @@ 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+
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,44 @@ final class SwiftDriverTests: XCTestCase {
453453
}
454454
}
455455

456+
func testOutputFileMapResolving() throws {
457+
// Create sample OutputFileMap:
458+
459+
let stringyEntries: [String: [FileType: String]] = [
460+
"": [.swiftDeps: "foo.build/master.swiftdeps"],
461+
"foo.swift" : [
462+
.dependencies: "foo.build/foo.d",
463+
.object: "foo.build/foo.swift.o",
464+
.swiftModule: "foo.build/foo~partial.swiftmodule",
465+
.swiftDeps: "foo.build/foo.swiftdeps"
466+
]
467+
]
468+
let resolvedStringyEntries: [String: [FileType: String]] = [
469+
"": [.swiftDeps: "/foo_root/foo.build/master.swiftdeps"],
470+
"/foo_root/foo.swift" : [
471+
.dependencies: "/foo_root/foo.build/foo.d",
472+
.object: "/foo_root/foo.build/foo.swift.o",
473+
.swiftModule: "/foo_root/foo.build/foo~partial.swiftmodule",
474+
.swiftDeps: "/foo_root/foo.build/foo.swiftdeps"
475+
]
476+
]
477+
func outputFileMapFromStringyEntries(
478+
_ entries: [String: [FileType: String]]
479+
) throws -> OutputFileMap {
480+
.init(entries: Dictionary(uniqueKeysWithValues: try entries.map { try (
481+
VirtualPath(path: $0.key),
482+
$0.value.mapValues(VirtualPath.init(path:))
483+
)}))
484+
}
485+
let sampleOutputFileMap =
486+
try outputFileMapFromStringyEntries(stringyEntries)
487+
let resolvedOutputFileMap = sampleOutputFileMap
488+
.resolveRelativePaths(relativeTo: .init("/foo_root"))
489+
let expectedOutputFileMap =
490+
try outputFileMapFromStringyEntries(resolvedStringyEntries)
491+
XCTAssertEqual(expectedOutputFileMap, resolvedOutputFileMap)
492+
}
493+
456494
func testResponseFileExpansion() throws {
457495
try withTemporaryDirectory { path in
458496
let diags = DiagnosticsEngine()

0 commit comments

Comments
 (0)