Skip to content

Commit c835d02

Browse files
authored
Merge pull request #63 from zienag/rel_paths_in_outputmap
Allow relative paths in output file map
2 parents 7eb61ec + bc1d31b commit c835d02

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
@@ -259,13 +259,19 @@ public struct Driver {
259259
return nil
260260
})
261261

262+
let outputFileMap: OutputFileMap?
262263
// Initialize an empty output file map, which will be populated when we start creating jobs.
263264
if let outputFileMapArg = parsedOptions.getLastArgument(.outputFileMap)?.asSingle {
264265
let path = try AbsolutePath(validating: outputFileMapArg)
265-
self.outputFileMap = try .load(file: path, diagnosticEngine: diagnosticEngine)
266+
outputFileMap = try .load(file: path, diagnosticEngine: diagnosticEngine)
267+
} else {
268+
outputFileMap = nil
266269
}
267-
else {
268-
self.outputFileMap = nil
270+
271+
if let workingDirectory = self.workingDirectory {
272+
self.outputFileMap = outputFileMap?.resolveRelativePaths(relativeTo: workingDirectory)
273+
} else {
274+
self.outputFileMap = outputFileMap
269275
}
270276

271277
// 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
@@ -494,6 +494,44 @@ final class SwiftDriverTests: XCTestCase {
494494
}
495495
}
496496

497+
func testOutputFileMapResolving() throws {
498+
// Create sample OutputFileMap:
499+
500+
let stringyEntries: [String: [FileType: String]] = [
501+
"": [.swiftDeps: "foo.build/master.swiftdeps"],
502+
"foo.swift" : [
503+
.dependencies: "foo.build/foo.d",
504+
.object: "foo.build/foo.swift.o",
505+
.swiftModule: "foo.build/foo~partial.swiftmodule",
506+
.swiftDeps: "foo.build/foo.swiftdeps"
507+
]
508+
]
509+
let resolvedStringyEntries: [String: [FileType: String]] = [
510+
"": [.swiftDeps: "/foo_root/foo.build/master.swiftdeps"],
511+
"/foo_root/foo.swift" : [
512+
.dependencies: "/foo_root/foo.build/foo.d",
513+
.object: "/foo_root/foo.build/foo.swift.o",
514+
.swiftModule: "/foo_root/foo.build/foo~partial.swiftmodule",
515+
.swiftDeps: "/foo_root/foo.build/foo.swiftdeps"
516+
]
517+
]
518+
func outputFileMapFromStringyEntries(
519+
_ entries: [String: [FileType: String]]
520+
) throws -> OutputFileMap {
521+
.init(entries: Dictionary(uniqueKeysWithValues: try entries.map { try (
522+
VirtualPath(path: $0.key),
523+
$0.value.mapValues(VirtualPath.init(path:))
524+
)}))
525+
}
526+
let sampleOutputFileMap =
527+
try outputFileMapFromStringyEntries(stringyEntries)
528+
let resolvedOutputFileMap = sampleOutputFileMap
529+
.resolveRelativePaths(relativeTo: .init("/foo_root"))
530+
let expectedOutputFileMap =
531+
try outputFileMapFromStringyEntries(resolvedStringyEntries)
532+
XCTAssertEqual(expectedOutputFileMap, resolvedOutputFileMap)
533+
}
534+
497535
func testResponseFileExpansion() throws {
498536
try withTemporaryDirectory { path in
499537
let diags = DiagnosticsEngine()

0 commit comments

Comments
 (0)