Skip to content

Commit 518e2fd

Browse files
committed
Handle base output paths correctly for frontend-only plans
1 parent 26e8e06 commit 518e2fd

File tree

5 files changed

+58
-8
lines changed

5 files changed

+58
-8
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ extension Driver {
604604
return
605605
}
606606

607-
if jobs.contains(where: { $0.requiresInPlaceExecution }) {
607+
if jobs.contains(where: { $0.requiresInPlaceExecution }) || jobs.count == 1 {
608608
assert(jobs.count == 1, "Cannot execute in place for multi-job build plans")
609609
return try executeJobInPlace(jobs[0], resolver: resolver, forceResponseFiles: forceResponseFiles)
610610
}

Sources/SwiftDriver/Jobs/CompileJob.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extension Driver {
2626
}
2727

2828
/// Add the compiler inputs for a frontend compilation job, and return the corresponding primary set of outputs.
29-
func addCompileInputs(primaryInputs: [TypedVirtualPath], inputs: inout [TypedVirtualPath], commandLine: inout [Job.ArgTemplate]) -> [TypedVirtualPath] {
29+
func addCompileInputs(primaryInputs: [TypedVirtualPath], inputs: inout [TypedVirtualPath], commandLine: inout [Job.ArgTemplate], baseOutput: VirtualPath?) -> [TypedVirtualPath] {
3030
// Collect the set of input files that are part of the Swift compilation.
3131
let swiftInputFiles: [TypedVirtualPath] = inputFiles.compactMap { inputFile in
3232
if inputFile.type.isPartOfSwiftCompilation {
@@ -58,7 +58,7 @@ extension Driver {
5858
// add an output for the input.
5959
if isPrimary || numThreads > 0,
6060
let compilerOutputType = compilerOutputType {
61-
let output = (outputFileMap ?? OutputFileMap()).getOutput(
61+
let output = baseOutput ?? (outputFileMap ?? OutputFileMap()).getOutput(
6262
inputFile: input.file,
6363
outputType: compilerOutputType
6464
)
@@ -69,7 +69,7 @@ extension Driver {
6969
// When not using primary file inputs or multithreading, add a single output.
7070
if !usesPrimaryFileInputs && numThreads == 0,
7171
let outputType = compilerOutputType {
72-
let existingOutputPath = outputFileMap?.existingOutputForSingleInput(
72+
let existingOutputPath = baseOutput ?? outputFileMap?.existingOutputForSingleInput(
7373
outputType: outputType)
7474
let output = existingOutputPath ?? VirtualPath.temporary(.init(moduleName.appendingFileTypeExtension(outputType)))
7575
primaryOutputs.append(TypedVirtualPath(file: output, type: outputType))
@@ -80,14 +80,14 @@ extension Driver {
8080

8181
/// Form a compile job, which executes the Swift frontend to produce various outputs.
8282
mutating func compileJob(primaryInputs: [TypedVirtualPath], outputType: FileType?,
83-
allOutputs: inout [TypedVirtualPath]) throws -> Job {
83+
allOutputs: inout [TypedVirtualPath], baseOutputPath: VirtualPath?) throws -> Job {
8484
var commandLine: [Job.ArgTemplate] = swiftCompilerPrefixArgs.map { Job.ArgTemplate.flag($0) }
8585
var inputs: [TypedVirtualPath] = []
8686
var outputs: [TypedVirtualPath] = []
8787

8888
commandLine.appendFlag("-frontend")
8989
addCompileModeOption(outputType: outputType, commandLine: &commandLine)
90-
let primaryOutputs = addCompileInputs(primaryInputs: primaryInputs, inputs: &inputs, commandLine: &commandLine)
90+
let primaryOutputs = addCompileInputs(primaryInputs: primaryInputs, inputs: &inputs, commandLine: &commandLine, baseOutput: baseOutputPath)
9191
outputs += primaryOutputs
9292
outputs += try addFrontendSupplementaryOutputArguments(commandLine: &commandLine, primaryInputs: primaryInputs)
9393

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ extension Driver {
6262
jobs.append(try emitModuleJob())
6363
}
6464

65+
var compileBaseOutputPath: VirtualPath? = nil
66+
if (compilerOutputType == .object && linkerOutputType == nil) ||
67+
compilerOutputType == .assembly || compilerOutputType == .sil ||
68+
compilerOutputType == .raw_sil || compilerOutputType == .llvmIR {
69+
if let baseOutput = parsedOptions.getLastArgument(.o)?.asSingle {
70+
compileBaseOutputPath = try VirtualPath(path: baseOutput)
71+
} else if compilerOutputType?.isTextual ?? false {
72+
compileBaseOutputPath = .standardOutput
73+
}
74+
}
75+
6576
let partitions: BatchPartitions?
6677
switch compilerMode {
6778
case .batchCompile(let batchInfo):
@@ -74,7 +85,7 @@ extension Driver {
7485
// Create a single compile job for all of the files, none of which
7586
// are primary.
7687
var jobOutputs: [TypedVirtualPath] = []
77-
let job = try compileJob(primaryInputs: [], outputType: compilerOutputType, allOutputs: &jobOutputs)
88+
let job = try compileJob(primaryInputs: [], outputType: compilerOutputType, allOutputs: &jobOutputs, baseOutputPath: compileBaseOutputPath)
7889
jobs.append(job)
7990
addJobOutputs(jobOutputs)
8091

@@ -104,7 +115,7 @@ extension Driver {
104115
}
105116

106117
var jobOutputs: [TypedVirtualPath] = []
107-
let job = try compileJob(primaryInputs: primaryInputs, outputType: compilerOutputType, allOutputs: &jobOutputs)
118+
let job = try compileJob(primaryInputs: primaryInputs, outputType: compilerOutputType, allOutputs: &jobOutputs, baseOutputPath: compileBaseOutputPath)
108119
jobs.append(job)
109120
addJobOutputs(jobOutputs)
110121

Sources/SwiftDriver/Utilities/FileType.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,14 @@ extension FileType {
246246
}
247247
}
248248
}
249+
250+
extension FileType {
251+
var isTextual: Bool {
252+
switch self {
253+
case .swift, .sil, .dependencies, .assembly, .ast, .raw_sil, .llvmIR, .objcHeader, .autolink, .importedModules, .tbd, .moduleTrace, .optimizationRecord, .swiftInterface:
254+
return true
255+
case .image, .object, .dSYM, .pch, .sib, .raw_sib, .swiftModule, .swiftDocumentation, .swiftSourceInfoFile, .llvmBitcode, .diagnostics, .pcm, .swiftDeps, .remap, .indexData:
256+
return false
257+
}
258+
}
259+
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,34 @@ final class SwiftDriverTests: XCTestCase {
363363
try assertNoDriverDiagnostics(args: "swiftc", "foo-bar.swift")
364364
}
365365

366+
func testBaseOutputPaths() throws {
367+
// Test the combination of -c and -o includes the base output path.
368+
do {
369+
var driver = try Driver(args: ["swiftc", "-c", "foo.swift", "-o", "/some/output/path/bar.o"])
370+
let plannedJobs = try driver.planBuild()
371+
XCTAssertEqual(plannedJobs.count, 1)
372+
XCTAssertEqual(plannedJobs[0].kind, .compile)
373+
XCTAssertTrue(plannedJobs[0].commandLine.contains(.path(try VirtualPath(path: "/some/output/path/bar.o"))))
374+
}
375+
376+
do {
377+
var driver = try Driver(args: ["swiftc", "-emit-sil", "foo.swift", "-o", "/some/output/path/bar.sil"])
378+
let plannedJobs = try driver.planBuild()
379+
XCTAssertEqual(plannedJobs.count, 1)
380+
XCTAssertEqual(plannedJobs[0].kind, .compile)
381+
XCTAssertTrue(plannedJobs[0].commandLine.contains(.path(try VirtualPath(path: "/some/output/path/bar.sil"))))
382+
}
383+
384+
do {
385+
// If no output is specified, verify we print to stdout for textual formats.
386+
var driver = try Driver(args: ["swiftc", "-emit-assembly", "foo.swift"])
387+
let plannedJobs = try driver.planBuild()
388+
XCTAssertEqual(plannedJobs.count, 1)
389+
XCTAssertEqual(plannedJobs[0].kind, .compile)
390+
XCTAssertTrue(plannedJobs[0].commandLine.contains(.path(.standardOutput)))
391+
}
392+
}
393+
366394
func testStandardCompileJobs() throws {
367395
var driver1 = try Driver(args: ["swiftc", "foo.swift", "bar.swift", "-module-name", "Test"])
368396
let plannedJobs = try driver1.planBuild()

0 commit comments

Comments
 (0)