Skip to content

Commit e0604b6

Browse files
committed
Ensure supplementary output file maps associate Swift Source inputs with expected outputs in WMO
When handling invocations with many input kinds, it is important that the Swift compiler is passed a supplementary output filemap that maps the first `.swift` input to the expected outputs. It is already just a convention that we use the first input for a WMO compilation task. In cases where we use the first input which happens to not be a `.swift` input (e.g. a `.o` input), the Swift compiler fails to map it to expected output kinds of Swift compilation. Resolves rdar://115577783
1 parent ac90110 commit e0604b6

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,10 @@ extension Driver {
693693
if let input = input?.fileHandle, input != OutputFileMap.singleInputKey {
694694
entryInput = input
695695
} else {
696-
entryInput = inputFiles[0].fileHandle
696+
guard let firstSourceInputHandle = inputFiles.first(where:{ $0.type == .swift })?.fileHandle else {
697+
fatalError("Formulating swift-frontend invocation without any input .swift files")
698+
}
699+
entryInput = firstSourceInputHandle
697700
}
698701
entries[entryInput, default: [:]][output.type] = output.fileHandle
699702
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2906,6 +2906,30 @@ final class SwiftDriverTests: XCTestCase {
29062906
XCTAssertEqual(firstKey, "foo.swift")
29072907
}
29082908

2909+
func testWMOWithNonSourceInputFirstAndModuleOutput() throws {
2910+
var driver1 = try Driver(args: [
2911+
"swiftc", "-wmo", "danger.o", "foo.swift", "bar.swift", "wibble.swift", "-module-name", "Test",
2912+
"-driver-filelist-threshold=0", "-emit-module", "-emit-library"
2913+
])
2914+
let plannedJobs = try driver1.planBuild().removingAutolinkExtractJobs()
2915+
XCTAssertEqual(plannedJobs.count, 2)
2916+
let compileJob = plannedJobs[0]
2917+
XCTAssertEqual(compileJob.kind, .compile)
2918+
XCTAssert(compileJob.commandLine.contains(.flag("-supplementary-output-file-map")))
2919+
let argIdx = try XCTUnwrap(compileJob.commandLine.firstIndex(where: { $0 == .flag("-supplementary-output-file-map") }))
2920+
let supplOutputs = compileJob.commandLine[argIdx+1]
2921+
guard case let .path(path) = supplOutputs,
2922+
case let .fileList(_, fileList) = path,
2923+
case let .outputFileMap(outFileMap) = fileList else {
2924+
throw StringError("Unexpected argument for output file map")
2925+
}
2926+
let firstKeyHandle = try XCTUnwrap(outFileMap.entries.keys.first)
2927+
let firstKey = try VirtualPath.lookup(firstKeyHandle).description
2928+
XCTAssertEqual(firstKey, "foo.swift")
2929+
let firstKeyOutputs = try XCTUnwrap(outFileMap.entries[firstKeyHandle])
2930+
XCTAssertTrue(firstKeyOutputs.keys.contains(where: { $0 == .swiftModule }))
2931+
}
2932+
29092933
func testDashDashPassingDownInput() throws {
29102934
do {
29112935
var driver = try Driver(args: ["swiftc", "-module-name=ThisModule", "-wmo", "-num-threads", "4", "-emit-module", "-o", "test.swiftmodule", "--", "main.swift", "multi-threaded.swift"])

0 commit comments

Comments
 (0)