Skip to content

Commit 9b4d197

Browse files
authored
Merge pull request #10 from apple/master
merge upstream
2 parents e09783a + 3eafea1 commit 9b4d197

19 files changed

+597
-324
lines changed

Sources/SwiftDriver/Driver/CompilerMode.swift

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ public enum CompilerMode: Equatable {
2626

2727
/// Compile and execute the inputs immediately.
2828
case immediate
29+
30+
/// Compile a Clang module (.pcm).
31+
case compilePCM
2932
}
3033

3134
/// Information about batch mode, which is used to determine how to form
@@ -40,7 +43,7 @@ extension CompilerMode {
4043
/// Whether this compilation mode uses -primary-file to specify its inputs.
4144
public var usesPrimaryFileInputs: Bool {
4245
switch self {
43-
case .immediate, .repl, .singleCompile:
46+
case .immediate, .repl, .singleCompile, .compilePCM:
4447
return false
4548

4649
case .standardCompile, .batchCompile:
@@ -54,26 +57,27 @@ extension CompilerMode {
5457
case .immediate, .repl, .standardCompile, .batchCompile:
5558
return false
5659

57-
case .singleCompile:
60+
case .singleCompile, .compilePCM:
5861
return true
5962
}
6063
}
6164
}
6265

6366
extension CompilerMode: CustomStringConvertible {
6467
public var description: String {
65-
switch self {
66-
67-
case .standardCompile:
68-
return "standard compilation"
69-
case .batchCompile:
70-
return "batch compilation"
71-
case .singleCompile:
72-
return "whole module optimization"
73-
case .repl:
74-
return "read-eval-print-loop compilation"
75-
case .immediate:
76-
return "immediate compilation"
77-
}
68+
switch self {
69+
case .standardCompile:
70+
return "standard compilation"
71+
case .batchCompile:
72+
return "batch compilation"
73+
case .singleCompile:
74+
return "whole module optimization"
75+
case .repl:
76+
return "read-eval-print-loop compilation"
77+
case .immediate:
78+
return "immediate compilation"
79+
case .compilePCM:
80+
return "compile Clang module (.pcm)"
81+
}
7882
}
7983
}

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public struct Driver {
4444
case invalidDriverName(String)
4545
case invalidInput(String)
4646
case subcommandPassedToDriver
47+
case relativeFrontendPath(String)
4748
}
4849

4950
/// The set of environment variables that are visible to the driver and
@@ -69,9 +70,6 @@ public struct Driver {
6970
/// The set of parsed options.
7071
var parsedOptions: ParsedOptions
7172

72-
/// The Swift compiler executable.
73-
public let swiftCompiler: VirtualPath
74-
7573
/// Extra command-line arguments to pass to the Swift compiler.
7674
public let swiftCompilerPrefixArgs: [String]
7775

@@ -221,16 +219,16 @@ public struct Driver {
221219

222220
// Find the Swift compiler executable.
223221
if let frontendPath = self.parsedOptions.getLastArgument(.driverUseFrontendPath) {
224-
let frontendCommandLine = frontendPath.asSingle.split(separator: ";").map { String($0) }
222+
var frontendCommandLine = frontendPath.asSingle.split(separator: ";").map { String($0) }
225223
if frontendCommandLine.isEmpty {
226224
self.diagnosticEngine.emit(.error_no_swift_frontend)
227-
self.swiftCompiler = .absolute(try self.toolchain.getToolPath(.swiftCompiler))
225+
self.swiftCompilerPrefixArgs = []
228226
} else {
229-
self.swiftCompiler = try VirtualPath(path: frontendCommandLine.first!)
227+
let frontendPath = frontendCommandLine.removeFirst()
228+
self.toolchain.overrideToolPath(.swiftCompiler, path: try AbsolutePath(validating: frontendPath))
229+
self.swiftCompilerPrefixArgs = frontendCommandLine
230230
}
231-
self.swiftCompilerPrefixArgs = Array(frontendCommandLine.dropFirst())
232231
} else {
233-
self.swiftCompiler = .absolute(try self.toolchain.getToolPath(.swiftCompiler))
234232
self.swiftCompilerPrefixArgs = []
235233
}
236234

@@ -296,7 +294,11 @@ public struct Driver {
296294
importedObjCHeader: importedObjCHeader,
297295
outputFileMap: outputFileMap)
298296

299-
self.enabledSanitizers = try Self.parseSanitizerArgValues(&parsedOptions, diagnosticEngine: diagnosticEngine, toolchain: toolchain, targetTriple: targetTriple)
297+
self.enabledSanitizers = try Self.parseSanitizerArgValues(
298+
&parsedOptions,
299+
diagnosticEngine: diagnosticEngine,
300+
toolchain: toolchain,
301+
targetTriple: targetTriple)
300302

301303
// Supplemental outputs.
302304
self.dependenciesFilePath = try Self.computeSupplementaryOutputPath(
@@ -557,15 +559,23 @@ extension Driver {
557559
) throws {
558560
// We just need to invoke the corresponding tool if the kind isn't Swift compiler.
559561
guard driverKind.isSwiftCompiler else {
560-
let swiftCompiler = try getSwiftCompilerPath()
561-
return try exec(path: swiftCompiler.pathString, args: driverKind.usageArgs + parsedOptions.commandLine)
562+
return try exec(path: toolchain.getToolPath(.swiftCompiler).pathString, args: driverKind.usageArgs + parsedOptions.commandLine)
562563
}
563564

564565
if parsedOptions.contains(.help) || parsedOptions.contains(.helpHidden) {
565566
optionTable.printHelp(driverKind: driverKind, includeHidden: parsedOptions.contains(.helpHidden))
566567
return
567568
}
568569

570+
if parsedOptions.hasArgument(.version) || parsedOptions.hasArgument(.version_) {
571+
// Follow gcc/clang behavior and use stdout for --version and stderr for -v.
572+
try printVersion(outputStream: &stdoutStream)
573+
return
574+
}
575+
if parsedOptions.hasArgument(.v) {
576+
try printVersion(outputStream: &stderrStream)
577+
}
578+
569579
// Plan the build.
570580
let jobs = try planBuild()
571581
if jobs.isEmpty { return }
@@ -603,12 +613,6 @@ extension Driver {
603613
try jobExecutor.execute(env: env)
604614
}
605615

606-
/// Returns the path to the Swift binary.
607-
func getSwiftCompilerPath() throws -> AbsolutePath {
608-
// FIXME: This is very preliminary. Need to figure out how to get the actual Swift executable path.
609-
try toolchain.getToolPath(.swiftCompiler)
610-
}
611-
612616
public mutating func createToolExecutionDelegate() -> ToolExecutionDelegate {
613617
var mode: ToolExecutionDelegate.Mode = .regular
614618

@@ -634,6 +638,11 @@ extension Driver {
634638

635639
return try exec(path: tool, args: arguments)
636640
}
641+
642+
private func printVersion<S: OutputByteStream>(outputStream: inout S) throws {
643+
outputStream.write(try Process.checkNonZeroExit(args: toolchain.getToolPath(.swiftCompiler).pathString, "--version"))
644+
outputStream.flush()
645+
}
637646
}
638647

639648
extension Diagnostic.Message {
@@ -692,6 +701,9 @@ extension Driver {
692701
case .repl, .deprecatedIntegratedRepl, .lldbRepl:
693702
return .repl
694703

704+
case .emitPcm:
705+
return .compilePCM
706+
695707
default:
696708
// Output flag doesn't determine the compiler mode.
697709
break
@@ -851,6 +863,9 @@ extension Driver {
851863
case .emitPch:
852864
compilerOutputType = .pch
853865

866+
case .emitPcm:
867+
compilerOutputType = .pcm
868+
854869
case .emitImportedModules:
855870
compilerOutputType = .importedModules
856871

Sources/SwiftDriver/Incremental Compilation/IncrementalCompilation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ fileprivate extension CompilerMode {
154154
var supportsIncrementalCompilation: Bool {
155155
switch self {
156156
case .standardCompile, .immediate, .repl, .batchCompile: return true
157-
case .singleCompile: return false
157+
case .singleCompile, .compilePCM: return false
158158
}
159159
}
160160
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
//===--- CommandLineArguments.swift - Command Line Argument Manipulation --===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
import TSCBasic
13+
14+
/// Utilities for manipulating a list of command line arguments, including
15+
/// constructing one from a set of ParsedOptions.
16+
extension Array where Element == Job.ArgTemplate {
17+
/// Append a fixed flag to the command line arguments.
18+
///
19+
/// When possible, use the more semantic forms `appendFlag` or
20+
/// `append(_: Option)`.
21+
mutating func appendFlag<StringType: StringProtocol>(_ string: StringType) {
22+
append(.flag(String(string)))
23+
}
24+
25+
/// Append multiple flags to the command line arguments.
26+
///
27+
/// When possible, use the more semantic forms `appendFlag` or
28+
/// `append(_: Option)`.
29+
mutating func appendFlags(_ flags: String...) {
30+
appendFlags(flags)
31+
}
32+
33+
/// Append multiple flags to the command line arguments.
34+
///
35+
/// When possible, use the more semantic forms `appendFlag` or
36+
/// `append(_: Option)`.
37+
mutating func appendFlags(_ flags: [String]) {
38+
for flag in flags {
39+
append(.flag(flag))
40+
}
41+
}
42+
43+
/// Append a virtual path to the command line arguments.
44+
mutating func appendPath(_ path: VirtualPath) {
45+
append(.path(path))
46+
}
47+
48+
/// Append an absolute path to the command line arguments.
49+
mutating func appendPath(_ path: AbsolutePath) {
50+
append(.path(.absolute(path)))
51+
}
52+
53+
/// Append an option's spelling to the command line arguments.
54+
mutating func appendFlag(_ option: Option) {
55+
switch option.kind {
56+
case .flag, .joinedOrSeparate, .remaining, .separate:
57+
break
58+
case .commaJoined, .input, .joined:
59+
fatalError("Option cannot be appended as a flag: \(option)")
60+
}
61+
62+
append(.flag(option.spelling))
63+
}
64+
65+
/// Append a single argument from the given option.
66+
private mutating func appendSingleArgument(option: Option, argument: String) throws {
67+
if option.attributes.contains(.argumentIsPath) {
68+
append(.path(try VirtualPath(path: argument)))
69+
} else {
70+
appendFlag(argument)
71+
}
72+
}
73+
74+
/// Append a parsed option to the array of argument templates, expanding
75+
/// until multiple arguments if required.
76+
mutating func append(_ parsedOption: ParsedOption) throws {
77+
let option = parsedOption.option
78+
let argument = parsedOption.argument
79+
80+
switch option.kind {
81+
case .input:
82+
try appendSingleArgument(option: option, argument: argument.asSingle)
83+
84+
case .flag:
85+
appendFlag(option)
86+
87+
case .separate, .joinedOrSeparate:
88+
appendFlag(option.spelling)
89+
try appendSingleArgument(option: option, argument: argument.asSingle)
90+
91+
case .commaJoined:
92+
assert(!option.attributes.contains(.argumentIsPath))
93+
appendFlag(option.spelling + argument.asMultiple.joined(separator: ","))
94+
95+
case .remaining:
96+
appendFlag(option.spelling)
97+
for arg in argument.asMultiple {
98+
try appendSingleArgument(option: option, argument: arg)
99+
}
100+
101+
case .joined:
102+
if option.attributes.contains(.argumentIsPath) {
103+
fatalError("Not currently implementable")
104+
} else {
105+
appendFlag(option.spelling + argument.asSingle)
106+
}
107+
}
108+
}
109+
110+
/// Append the last parsed option that matches one of the given options
111+
/// to this command line.
112+
mutating func appendLast(_ options: Option..., from parsedOptions: inout ParsedOptions) throws {
113+
guard let parsedOption = parsedOptions.last(for: options) else {
114+
return
115+
}
116+
117+
try append(parsedOption)
118+
}
119+
120+
/// Append the last parsed option from the given group to this command line.
121+
mutating func appendLast(in group: Option.Group, from parsedOptions: inout ParsedOptions) throws {
122+
guard let parsedOption = parsedOptions.getLast(in: group) else {
123+
return
124+
}
125+
126+
try append(parsedOption)
127+
}
128+
129+
mutating func append(contentsOf options: [ParsedOption]) throws {
130+
for option in options {
131+
try append(option)
132+
}
133+
}
134+
135+
/// Append all parsed options that match one of the given options
136+
/// to this command line.
137+
mutating func appendAll(_ options: Option..., from parsedOptions: inout ParsedOptions) throws {
138+
for matching in parsedOptions.arguments(for: options) {
139+
try append(matching)
140+
}
141+
}
142+
143+
/// Append just the arguments from all parsed options that match one of the given options
144+
/// to this command line.
145+
mutating func appendAllArguments(_ options: Option..., from parsedOptions: inout ParsedOptions) throws {
146+
for matching in parsedOptions.arguments(for: options) {
147+
try self.appendSingleArgument(option: matching.option, argument: matching.argument.asSingle)
148+
}
149+
}
150+
151+
/// Append the last of the given flags that appears in the parsed options,
152+
/// or the flag that corresponds to the default value if neither
153+
/// appears.
154+
mutating func appendFlag(true trueFlag: Option, false falseFlag: Option, default defaultValue: Bool, from parsedOptions: inout ParsedOptions) {
155+
let isTrue = parsedOptions.hasFlag(
156+
positive: trueFlag,
157+
negative: falseFlag,
158+
default: defaultValue
159+
)
160+
appendFlag(isTrue ? trueFlag : falseFlag)
161+
}
162+
163+
/// A shell-escaped string representation of the arguments, as they would appear on the command line.
164+
var joinedArguments: String {
165+
return self.map {
166+
switch $0 {
167+
case .flag(let string):
168+
return string.spm_shellEscaped()
169+
case .path(let path):
170+
return path.name.spm_shellEscaped()
171+
}
172+
}.joined(separator: " ")
173+
}
174+
}

0 commit comments

Comments
 (0)