Skip to content

Commit d05dd6e

Browse files
authored
Merge pull request #711 from artemcm/AllowMultipleStdOutOutputs
Verify usage of `-o` arguments in multi-threading mode.
2 parents 04fceed + fffd342 commit d05dd6e

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public struct Driver {
2424
case relativeFrontendPath(String)
2525
case subcommandPassedToDriver
2626
case integratedReplRemoved
27+
case cannotSpecify_OForMultipleOutputs
2728
case conflictingOptions(Option, Option)
2829
case unableToLoadOutputFileMap(String)
2930
case unableToDecodeFrontendTargetInfo(String?, [String], String)
@@ -58,6 +59,8 @@ public struct Driver {
5859
return "subcommand passed to driver"
5960
case .integratedReplRemoved:
6061
return "Compiler-internal integrated REPL has been removed; use the LLDB-enhanced REPL instead."
62+
case .cannotSpecify_OForMultipleOutputs:
63+
return "cannot specify -o when generating multiple output files"
6164
case .conflictingOptions(let one, let two):
6265
return "conflicting options '\(one.spelling)' and '\(two.spelling)'"
6366
case let .unableToDecodeFrontendTargetInfo(outputString, arguments, errorDesc):
@@ -696,6 +699,8 @@ public struct Driver {
696699
compilerMode: compilerMode,
697700
outputFileMap: self.outputFileMap,
698701
moduleName: moduleOutputInfo.name)
702+
703+
try verifyOutputOptions()
699704
}
700705

701706
public mutating func planBuild() throws -> [Job] {
@@ -781,6 +786,29 @@ extension Driver {
781786
}
782787
}
783788

789+
extension Driver {
790+
// Detect mis-use of multi-threading and output file options
791+
private func verifyOutputOptions() throws {
792+
if compilerOutputType != .swiftModule,
793+
parsedOptions.hasArgument(.o),
794+
linkerOutputType == nil {
795+
let shouldComplain: Bool
796+
if numThreads > 0 {
797+
// Multi-threading compilation has multiple outputs unless there's only
798+
// one input.
799+
shouldComplain = self.inputFiles.count > 1
800+
} else {
801+
// Single-threaded compilation is a problem if we're compiling more than
802+
// one file.
803+
shouldComplain = self.inputFiles.filter { $0.type.isPartOfSwiftCompilation }.count > 1 && .singleCompile != compilerMode
804+
}
805+
if shouldComplain {
806+
diagnosticEngine.emit(Error.cannotSpecify_OForMultipleOutputs)
807+
}
808+
}
809+
}
810+
}
811+
784812
// MARK: - Response files.
785813
extension Driver {
786814
/// Tokenize a single line in a response file.

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ extension Driver {
8585
-> ([Job], IncrementalCompilationState?) {
8686
precondition(compilerMode.isStandardCompilationForPlanning,
8787
"compiler mode \(compilerMode) is handled elsewhere")
88-
8988
// Determine the initial state for incremental compilation that is required during
9089
// the planning process. This state contains the module dependency graph and
9190
// cross-module dependency information.

Sources/SwiftDriverExecution/MultiJobExecutor.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ public final class MultiJobExecutor {
191191
to producerMap: inout [VirtualPath.Handle: Int]
192192
) {
193193
for output in job.outputs {
194-
if let otherJobIndex = producerMap.updateValue(index, forKey: output.fileHandle) {
194+
if output.file != .standardOutput,
195+
let otherJobIndex = producerMap.updateValue(index, forKey: output.fileHandle) {
195196
fatalError("multiple producers for output \(output.file): \(job) & \(knownJobs[otherJobIndex])")
196197
}
197198
producerMap[output.fileHandle] = index

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ final class SwiftDriverTests: XCTestCase {
314314
}
315315
}
316316

317+
func testMultiThreadingOutputs() throws {
318+
try assertDriverDiagnostics(args: "swiftc", "-c", "foo.swift", "bar.swift", "-o", "bar.ll", "-o", "foo.ll", "-num-threads", "2", "-whole-module-optimization") {
319+
$1.expect(.error("cannot specify -o when generating multiple output files"))
320+
}
321+
322+
try assertDriverDiagnostics(args: "swiftc", "-c", "foo.swift", "bar.swift", "-o", "bar.ll", "-o", "foo.ll", "-num-threads", "0") {
323+
$1.expect(.error("cannot specify -o when generating multiple output files"))
324+
}
325+
}
326+
317327
func testBaseOutputPaths() throws {
318328
// Test the combination of -c and -o includes the base output path.
319329
do {

0 commit comments

Comments
 (0)