Skip to content

Commit 5c1b876

Browse files
committed
Merge branch 'master' into where-are-the-tools
2 parents 35f0e18 + 95d7f4e commit 5c1b876

File tree

10 files changed

+224
-108
lines changed

10 files changed

+224
-108
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ The goal of the new Swift driver is to provide a drop-in replacement for the exi
136136
* [x] Parseable output, as used by SwiftPM
137137
* [x] Response files
138138
* [ ] Input and primary input file lists
139-
* [ ] Complete `OutputFileMap` implementation to handle all file types uniformly
139+
* [x] Complete `OutputFileMap` implementation to handle all file types uniformly
140140
* Testing
141141
* [ ] Build stuff with SwiftPM or Xcode or your favorite build system, using `swift-driver`. Were the results identical? What changed?
142142
* [x] Shim in `swift-driver` so it can run the Swift repository's [driver test suite](https://github.com/apple/swift/tree/master/test/Driver).

Sources/SwiftDriver/Driver/OutputFileMap.swift

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,48 @@ fileprivate struct OutputFileMapJSON: Codable {
100100
/// The data associated with an input file.
101101
/// \c fileprivate so that the \c store method above can see it
102102
fileprivate struct Entry: Codable {
103-
enum CodingKeys: String, CodingKey {
104-
case dependencies
105-
case object
106-
case swiftmodule
107-
case swiftinterface
108-
case swiftDependencies = "swift-dependencies"
109-
case diagnostics
103+
104+
private struct CodingKeys: CodingKey {
105+
106+
let fileType: FileType
107+
108+
init(fileType: FileType) {
109+
self.fileType = fileType
110+
}
111+
112+
init?(stringValue: String) {
113+
guard let fileType = FileType(name: stringValue) else { return nil }
114+
self.fileType = fileType
115+
}
116+
117+
var stringValue: String { fileType.name }
118+
var intValue: Int? { nil }
119+
init?(intValue: Int) { nil }
110120
}
111121

112-
let dependencies: String?
113-
let object: String?
114-
let swiftmodule: String?
115-
let swiftinterface: String?
116-
let swiftDependencies: String?
117-
let diagnostics: String?
122+
let paths: [FileType: String]
123+
124+
fileprivate init(paths: [FileType: String]) {
125+
self.paths = paths
126+
}
127+
128+
init(from decoder: Decoder) throws {
129+
let container = try decoder.container(keyedBy: CodingKeys.self)
130+
131+
paths = try Dictionary(uniqueKeysWithValues:
132+
container.allKeys.map { key in (key.fileType, try container.decode(String.self, forKey: key)) }
133+
)
134+
}
135+
136+
func encode(to encoder: Encoder) throws {
137+
138+
var container = encoder.container(keyedBy: CodingKeys.self)
139+
140+
try paths.forEach { fileType, path in try container.encode(path, forKey: CodingKeys(fileType: fileType)) }
141+
}
118142
}
119143

120-
/// The parsed entires
144+
/// The parsed entries
121145
/// \c fileprivate so that the \c store method above can see it
122146
fileprivate let entries: [String: Entry]
123147

@@ -132,23 +156,9 @@ fileprivate struct OutputFileMapJSON: Codable {
132156

133157
/// Converts into virtual path entries.
134158
func toVirtualOutputFileMap() throws -> [VirtualPath : [FileType : VirtualPath]] {
135-
var result: [VirtualPath : [FileType : VirtualPath]] = [:]
136-
137-
for (input, entry) in entries {
138-
let input = try VirtualPath(path: input)
139-
140-
var map: [FileType: String] = [:]
141-
map[.dependencies] = entry.dependencies
142-
map[.object] = entry.object
143-
map[.swiftModule] = entry.swiftmodule
144-
map[.swiftInterface] = entry.swiftinterface
145-
map[.swiftDeps] = entry.swiftDependencies
146-
map[.diagnostics] = entry.diagnostics
147-
148-
result[input] = try map.mapValues(VirtualPath.init(path:))
149-
}
150-
151-
return result
159+
Dictionary(uniqueKeysWithValues: try entries.map { input, entry in
160+
(try VirtualPath(path: input), try entry.paths.mapValues(VirtualPath.init(path:)))
161+
})
152162
}
153163

154164
/// Converts from virtual path entries
@@ -161,13 +171,7 @@ fileprivate struct OutputFileMapJSON: Codable {
161171
return (fixedIfMaster, convert(outputs: entry.value))
162172
}
163173
func convert(outputs: [FileType: VirtualPath]) -> Entry {
164-
Entry(
165-
dependencies: outputs[.dependencies]?.name,
166-
object: outputs[.object]?.name,
167-
swiftmodule: outputs[.swiftModule]?.name,
168-
swiftinterface: outputs[.swiftInterface]?.name,
169-
swiftDependencies: outputs[.swiftDeps]?.name,
170-
diagnostics: outputs[.diagnostics]?.name)
174+
Entry(paths: outputs.mapValues({ $0.name }))
171175
}
172176
return Self(entries: Dictionary(uniqueKeysWithValues: entries.map(convert(entry:))))
173177
}

Sources/SwiftDriver/Jobs/CompileJob.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ extension FileType {
349349

350350
case .swift, .dSYM, .autolink, .dependencies, .swiftDocumentation, .pcm,
351351
.diagnostics, .objcHeader, .image, .swiftDeps, .moduleTrace, .tbd,
352-
.optimizationRecord,.swiftInterface:
352+
.optimizationRecord, .swiftInterface, .swiftSourceInfoFile:
353353
fatalError("Output type can never be a primary output")
354354
}
355355
}

Sources/SwiftDriver/Toolchains/DarwinToolchain.swift

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111
//===----------------------------------------------------------------------===//
1212
import TSCBasic
1313

14-
fileprivate func envVarName(forExecutable toolName: String) -> String {
15-
return "SWIFT_DRIVER_\(toolName.uppercased())_EXEC"
16-
}
17-
1814
/// Toolchain for Darwin-based platforms, such as macOS and iOS.
1915
///
2016
/// FIXME: This class is not thread-safe.
@@ -119,31 +115,4 @@ public final class DarwinToolchain: Toolchain {
119115
\(isShared ? "_dynamic.dylib" : ".a")
120116
"""
121117
}
122-
123-
/// Looks for the executable in the `SWIFT_DRIVER_TOOLNAME_EXEC` environment variable, if found nothing,
124-
/// looks in the executable path; finally, fallback to xcrunFind.
125-
/// - Parameter exec: executable to look for [i.e. `swift`].
126-
func lookup(executable: String) throws -> AbsolutePath {
127-
if let overrideString = env[envVarName(forExecutable: executable)] {
128-
return try AbsolutePath(validating: overrideString)
129-
} else if let path = lookupExecutablePath(filename: executable, searchPaths: [executableDir]) {
130-
return path
131-
}
132-
return try xcrunFind(executable: executable)
133-
}
134-
135-
private func xcrunFind(executable: String) throws -> AbsolutePath {
136-
let xcrun = "xcrun"
137-
guard lookupExecutablePath(filename: xcrun, searchPaths: searchPaths) != nil else {
138-
// This is a hack so our tests work on linux. We need a better way for looking up tools in general.
139-
// TODO: remove this hack and emit an error once we have a generalized Toolchain routine for finding Tools.
140-
return AbsolutePath("/usr/bin/" + executable)
141-
}
142-
143-
let path = try Process.checkNonZeroExit(
144-
arguments: [xcrun, "-sdk", "macosx", "--find", executable],
145-
environment: env
146-
).spm_chomp()
147-
return AbsolutePath(path)
148-
}
149118
}

Sources/SwiftDriver/Toolchains/GenericUnixToolchain.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,10 @@ import TSCBasic
1313

1414
/// Toolchain for Unix-like systems.
1515
public final class GenericUnixToolchain: Toolchain {
16-
enum Error: Swift.Error {
17-
case unableToFind(tool: String)
18-
}
19-
2016
public let env: [String: String]
2117

22-
private let searchPaths: [AbsolutePath]
23-
2418
public init(env: [String: String]) {
2519
self.env = env
26-
self.searchPaths = getEnvSearchPaths(pathString: env["PATH"], currentWorkingDirectory: localFileSystem.currentWorkingDirectory)
27-
}
28-
29-
/// Looks in the `executablePath`, if found nothing, looks in the environment search paths.
30-
/// - Parameter executable: executable to look for [i.e. `swift`].
31-
private func lookup(executable: String) throws -> AbsolutePath {
32-
if let path = lookupExecutablePath(filename: executable, searchPaths: [executableDir]) {
33-
return path
34-
} else if let path = lookupExecutablePath(filename: executable, searchPaths: searchPaths) {
35-
return path
36-
}
37-
38-
// If we happen to be on a macOS host, some tools might not be in our
39-
// PATH, so we'll just use xcrun to find them too.
40-
#if os(macOS)
41-
return try DarwinToolchain(env: self.env).lookup(executable: executable)
42-
#else
43-
throw Error.unableToFind(tool: executable)
44-
#endif
4520
}
4621

4722
public func makeLinkerOutputFilename(moduleName: String, type: LinkOutputType) -> String {

Sources/SwiftDriver/Toolchains/Toolchain.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public protocol Toolchain {
2828

2929
var env: [String: String] { get }
3030

31+
var searchPaths: [AbsolutePath] { get }
32+
3133
/// Retrieve the absolute path to a particular tool.
3234
func getToolPath(_ tool: Tool) throws -> AbsolutePath
3335

@@ -87,4 +89,50 @@ extension Toolchain {
8789
}
8890
return AbsolutePath(path).parentDirectory
8991
}
92+
93+
/// Looks for `SWIFT_DRIVER_TOOLNAME_EXEC` in the `env` property.
94+
/// - Returns: Environment variable value, if any.
95+
func envVar(forExecutable toolName: String) -> String? {
96+
return env[envVarName(for: toolName)]
97+
}
98+
99+
/// - Returns: String in the form of: `SWIFT_DRIVER_TOOLNAME_EXEC`
100+
private func envVarName(for toolName: String) -> String {
101+
return "SWIFT_DRIVER_\(toolName.uppercased())_EXEC"
102+
}
103+
104+
/// Looks for the executable in the `SWIFT_DRIVER_TOOLNAME_EXEC` environment variable, if found nothing,
105+
/// looks in the `executableDir`, `xcrunFind` or in the `searchPaths`.
106+
/// - Parameter executable: executable to look for [i.e. `swift`].
107+
func lookup(executable: String) throws -> AbsolutePath {
108+
if let overrideString = envVar(forExecutable: executable) {
109+
return try AbsolutePath(validating: overrideString)
110+
} else if let path = lookupExecutablePath(filename: executable, searchPaths: [executableDir]) {
111+
return path
112+
} else if let path = try? xcrunFind(executable: executable) {
113+
return path
114+
} else if let path = lookupExecutablePath(filename: executable, searchPaths: searchPaths) {
115+
return path
116+
} else {
117+
// This is a hack so our tests work on linux.
118+
return AbsolutePath("/usr/bin/" + executable)
119+
}
120+
}
121+
122+
private func xcrunFind(executable: String) throws -> AbsolutePath {
123+
let xcrun = "xcrun"
124+
guard lookupExecutablePath(filename: xcrun, searchPaths: searchPaths) != nil else {
125+
throw ToolchainError.unableToFind(tool: xcrun)
126+
}
127+
128+
let path = try Process.checkNonZeroExit(
129+
arguments: [xcrun, "-sdk", "macosx", "--find", executable],
130+
environment: env
131+
).spm_chomp()
132+
return AbsolutePath(path)
133+
}
134+
}
135+
136+
fileprivate enum ToolchainError: Swift.Error {
137+
case unableToFind(tool: String)
90138
}

Sources/SwiftDriver/Utilities/FileType.swift

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
/// Describes the kinds of files that the driver understands.
1414
///
15-
/// The raw values for these enumerations describe the default extension for]
15+
/// The raw values for these enumerations describe the default extension for
1616
/// the file type.
1717
public enum FileType: String, Hashable, CaseIterable, Codable {
1818
/// Swift source file.
@@ -45,12 +45,15 @@ public enum FileType: String, Hashable, CaseIterable, Codable {
4545
/// A compiled Swift module file.
4646
case swiftModule = "swiftmodule"
4747

48-
/// Swift documentation for amodule.
48+
/// Swift documentation for a module.
4949
case swiftDocumentation = "swiftdoc"
5050

5151
/// A textual Swift interface file.
5252
case swiftInterface = "swiftinterface"
5353

54+
/// Serialized source information.
55+
case swiftSourceInfoFile = "swiftsourceinfo"
56+
5457
/// Assembler source.
5558
case assembly = "s"
5659

@@ -110,7 +113,7 @@ extension FileType: CustomStringConvertible {
110113
public var description: String {
111114
switch self {
112115
case .swift, .sil, .sib, .image, .object, .dSYM, .dependencies, .autolink,
113-
.swiftModule, .swiftDocumentation, .swiftInterface, .assembly,
116+
.swiftModule, .swiftDocumentation, .swiftInterface, .swiftSourceInfoFile, .assembly,
114117
.remap, .tbd, .pcm, .pch:
115118
return rawValue
116119

@@ -163,8 +166,83 @@ extension FileType {
163166
case .object, .pch, .ast, .llvmIR, .llvmBitcode, .assembly, .swiftModule,
164167
.importedModules, .indexData, .remap, .dSYM, .autolink, .dependencies,
165168
.swiftDocumentation, .pcm, .diagnostics, .objcHeader, .image,
166-
.swiftDeps, .moduleTrace, .tbd, .optimizationRecord, .swiftInterface:
169+
.swiftDeps, .moduleTrace, .tbd, .optimizationRecord, .swiftInterface, .swiftSourceInfoFile:
167170
return false
168171
}
169172
}
170173
}
174+
175+
extension FileType {
176+
177+
private static let typesByName = Dictionary(uniqueKeysWithValues: FileType.allCases.map { ($0.name, $0) })
178+
179+
init?(name: String) {
180+
guard let type = Self.typesByName[name] else { return nil }
181+
182+
self = type
183+
}
184+
185+
/// The NAME values as specified in FileTypes.def
186+
var name: String {
187+
switch self {
188+
case .swift:
189+
return "swift"
190+
case .sil:
191+
return "sil"
192+
case .sib:
193+
return "sib"
194+
case .image:
195+
return "image"
196+
case .object:
197+
return "object"
198+
case .dSYM:
199+
return "dSYM"
200+
case .dependencies:
201+
return "dependencies"
202+
case .autolink:
203+
return "autolink"
204+
case .swiftModule:
205+
return "swiftmodule"
206+
case .swiftDocumentation:
207+
return "swiftdoc"
208+
case .swiftInterface:
209+
return "swiftinterface"
210+
case .swiftSourceInfoFile:
211+
return "swiftsourceinfo"
212+
case .assembly:
213+
return "assembly"
214+
case .remap:
215+
return "remap"
216+
case .tbd:
217+
return "tbd"
218+
case .pcm:
219+
return "pcm"
220+
case .pch:
221+
return "pch"
222+
case .ast:
223+
return "ast-dump"
224+
case .raw_sil:
225+
return "raw-sil"
226+
case .raw_sib:
227+
return "raw-sib"
228+
case .llvmIR:
229+
return "llvm-ir"
230+
case .llvmBitcode:
231+
return "llvm-bc"
232+
case .objcHeader:
233+
return "objc-header"
234+
case .swiftDeps:
235+
return "swift-dependencies"
236+
case .importedModules:
237+
return "imported-modules"
238+
case .moduleTrace:
239+
return "module-trace"
240+
case .indexData:
241+
return "index-data"
242+
case .optimizationRecord:
243+
return "opt-record"
244+
case .diagnostics:
245+
return "diagnostics"
246+
}
247+
}
248+
}

0 commit comments

Comments
 (0)