Skip to content

Commit

Permalink
Determine driver kind based binary name and --driver-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
aciidgh committed Sep 27, 2019
1 parent f94aacc commit 5b0fcf5
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/Packages
/*.xcodeproj
xcuserdata/
.swiftpm
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ $ swift build -Xcc -I/path/to/build/Ninja-ReleaseAssert/swift-.../include
The driver currently does very little. Next steps:

* [x] Implement parsing of command line arguments (e.g., the `[String]` produced by `CommandLine.arguments`) into an array of `Option` values, capturing arguments and diagnosing unrecognized options, missing arguments, and other user errors.
* [ ] Infer the driver mode/kind from the name of the binary (e.g., `swift` -> `DriverKind.interactive`, `swiftc` -> `DriverKind.batch`, etc.) so we get the right options table. Recognize `--driver-mode` to change the mode from the command line.
* [x] Infer the driver mode/kind from the name of the binary (e.g., `swift` -> `DriverKind.interactive`, `swiftc` -> `DriverKind.batch`, etc.) so we get the right options table. Recognize `--driver-mode` to change the mode from the command line.
* [ ] Start building abstractions for inputs, outputs, and jobs.
* [ ] Write a little script to help automate the compilation of that horrible C++ program `makeOptions.cpp` (passing in the Swift build directory so it can find the generated `Options.inc`) so we can automatically update `Options.swift`. Is there any way to do this via `Package.swift` to make it automatic?
* [ ] Reflect option "group" information from `Options.inc` in the generated `Option`, since we'll need group-based queries.
Expand Down
66 changes: 66 additions & 0 deletions Sources/SwiftDriver/Driver.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#if os(macOS)
import Darwin.C
#else
import Glibc
#endif

/// The Swift driver.
public final class Driver {

enum Error: Swift.Error {
case invalidDriverName(String)
}

/// The kind of driver.
let driverKind: DriverKind

/// Create the driver with the given arguments.
public init(args: [String]) {
// FIXME: Determine if we should run as subcommand.

do {
driverKind = try Self.determineDriverKind(args: args)
} catch {
print("error: \(error)")
exit(EXIT_FAILURE)
}
}

/// Determine the driver kind based on the command-line arguments.
static func determineDriverKind(args: [String]) throws -> DriverKind {
// We always expect to have the first argument. By default, the driver name
// is used to determine the kind.
var driverName = args.first!

// Determine driver kind based on the first argument.
if args.count > 1 {
let driverModeOption = "--driver-mode="
if args[1].starts(with: driverModeOption) {
driverName = String(args[1].dropFirst(driverModeOption.count))
} else if args[1] == "-frontend" {
return .frontend
} else if args[1] == "-modulewrap" {
return .moduleWrap
}
}

switch driverName {
case "swift":
return .interactive
case "swiftc":
return .batch
case "swift-autolink-extract":
return .autolinkExtract
case "swift-indent":
return .indent
default:
throw Error.invalidDriverName(driverName)
}
}

/// Run the driver.
public func run() {
let options = OptionTable(driverKind: driverKind)
options.printHelp(usage: driverKind.usage, title: driverKind.title, includeHidden: false)
}
}
5 changes: 2 additions & 3 deletions Sources/driver/main.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import SwiftDriver

let driverKind = DriverKind.interactive
let options = OptionTable(driverKind: driverKind)
options.printHelp(usage: driverKind.usage, title: driverKind.title, includeHidden: false)
let driver = Driver(args: CommandLine.arguments)
driver.run()
24 changes: 20 additions & 4 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SwiftDriver
@testable import SwiftDriver
import XCTest

final class SwiftDriverTests: XCTestCase {
Expand Down Expand Up @@ -67,8 +67,24 @@ final class SwiftDriverTests: XCTestCase {
generator: .remaining(Option._DASH_DASH))

// FIXME: Check for the exact form of the error
XCTAssertThrowsError(try options.parse(["-unrecognized"]));
XCTAssertThrowsError(try options.parse(["-I"]));
XCTAssertThrowsError(try options.parse(["-module-name"]));
XCTAssertThrowsError(try options.parse(["-unrecognized"]))
XCTAssertThrowsError(try options.parse(["-I"]))
XCTAssertThrowsError(try options.parse(["-module-name"]))
}

func testDriverKindParsing() throws {
XCTAssertEqual(try Driver.determineDriverKind(args: ["swift"]), .interactive)
XCTAssertEqual(try Driver.determineDriverKind(args: ["swiftc"]), .batch)
XCTAssertEqual(try Driver.determineDriverKind(args: ["swiftc", "-frontend"]), .frontend)
XCTAssertEqual(try Driver.determineDriverKind(args: ["swiftc", "-modulewrap"]), .moduleWrap)

XCTAssertEqual(try Driver.determineDriverKind(args: ["swiftc", "--driver-mode=swift"]), .interactive)
XCTAssertEqual(try Driver.determineDriverKind(args: ["swiftc", "--driver-mode=swift-autolink-extract"]), .autolinkExtract)
XCTAssertEqual(try Driver.determineDriverKind(args: ["swiftc", "--driver-mode=swift-indent"]), .indent)
XCTAssertEqual(try Driver.determineDriverKind(args: ["swift", "--driver-mode=swift-autolink-extract"]), .autolinkExtract)

XCTAssertThrowsError(try Driver.determineDriverKind(args: ["driver"]))
XCTAssertThrowsError(try Driver.determineDriverKind(args: ["swiftc", "--driver-mode=blah"]))
XCTAssertThrowsError(try Driver.determineDriverKind(args: ["swiftc", "--driver-mode="]))
}
}
1 change: 1 addition & 0 deletions Tests/SwiftDriverTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extension SwiftDriverTests {
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__SwiftDriverTests = [
("testDriverKindParsing", testDriverKindParsing),
("testParseErrors", testParseErrors),
("testParsing", testParsing),
]
Expand Down

0 comments on commit 5b0fcf5

Please sign in to comment.