Skip to content

Handle all FileTypes in OutputFileMap #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ The goal of the new Swift driver is to provide a drop-in replacement for the exi
* [x] Parseable output, as used by SwiftPM
* [x] Response files
* [ ] Input and primary input file lists
* [ ] Complete `OutputFileMap` implementation to handle all file types uniformly
* [x] Complete `OutputFileMap` implementation to handle all file types uniformly
* Testing
* [ ] Build stuff with SwiftPM or Xcode or your favorite build system, using `swift-driver`. Were the results identical? What changed?
* [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).
Expand Down
80 changes: 42 additions & 38 deletions Sources/SwiftDriver/Driver/OutputFileMap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,48 @@ fileprivate struct OutputFileMapJSON: Codable {
/// The data associated with an input file.
/// \c fileprivate so that the \c store method above can see it
fileprivate struct Entry: Codable {
enum CodingKeys: String, CodingKey {
case dependencies
case object
case swiftmodule
case swiftinterface
case swiftDependencies = "swift-dependencies"
case diagnostics

private struct CodingKeys: CodingKey {

let fileType: FileType

init(fileType: FileType) {
self.fileType = fileType
}

init?(stringValue: String) {
guard let fileType = FileType(name: stringValue) else { return nil }
self.fileType = fileType
}

var stringValue: String { fileType.name }
var intValue: Int? { nil }
init?(intValue: Int) { nil }
}

let dependencies: String?
let object: String?
let swiftmodule: String?
let swiftinterface: String?
let swiftDependencies: String?
let diagnostics: String?
let paths: [FileType: String]

fileprivate init(paths: [FileType: String]) {
self.paths = paths
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

paths = try Dictionary(uniqueKeysWithValues:
container.allKeys.map { key in (key.fileType, try container.decode(String.self, forKey: key)) }
)
}

func encode(to encoder: Encoder) throws {

var container = encoder.container(keyedBy: CodingKeys.self)

try paths.forEach { fileType, path in try container.encode(path, forKey: CodingKeys(fileType: fileType)) }
}
}

/// The parsed entires
/// The parsed entries
/// \c fileprivate so that the \c store method above can see it
fileprivate let entries: [String: Entry]

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

/// Converts into virtual path entries.
func toVirtualOutputFileMap() throws -> [VirtualPath : [FileType : VirtualPath]] {
var result: [VirtualPath : [FileType : VirtualPath]] = [:]

for (input, entry) in entries {
let input = try VirtualPath(path: input)

var map: [FileType: String] = [:]
map[.dependencies] = entry.dependencies
map[.object] = entry.object
map[.swiftModule] = entry.swiftmodule
map[.swiftInterface] = entry.swiftinterface
map[.swiftDeps] = entry.swiftDependencies
map[.diagnostics] = entry.diagnostics

result[input] = try map.mapValues(VirtualPath.init(path:))
}

return result
Dictionary(uniqueKeysWithValues: try entries.map { input, entry in
(try VirtualPath(path: input), try entry.paths.mapValues(VirtualPath.init(path:)))
})
}

/// Converts from virtual path entries
Expand All @@ -161,13 +171,7 @@ fileprivate struct OutputFileMapJSON: Codable {
return (fixedIfMaster, convert(outputs: entry.value))
}
func convert(outputs: [FileType: VirtualPath]) -> Entry {
Entry(
dependencies: outputs[.dependencies]?.name,
object: outputs[.object]?.name,
swiftmodule: outputs[.swiftModule]?.name,
swiftinterface: outputs[.swiftInterface]?.name,
swiftDependencies: outputs[.swiftDeps]?.name,
diagnostics: outputs[.diagnostics]?.name)
Entry(paths: outputs.mapValues({ $0.name }))
}
return Self(entries: Dictionary(uniqueKeysWithValues: entries.map(convert(entry:))))
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftDriver/Jobs/CompileJob.swift
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ extension FileType {

case .swift, .dSYM, .autolink, .dependencies, .swiftDocumentation, .pcm,
.diagnostics, .objcHeader, .image, .swiftDeps, .moduleTrace, .tbd,
.optimizationRecord,.swiftInterface:
.optimizationRecord, .swiftInterface, .swiftSourceInfoFile:
fatalError("Output type can never be a primary output")
}
}
Expand Down
86 changes: 82 additions & 4 deletions Sources/SwiftDriver/Utilities/FileType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

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

/// Swift documentation for amodule.
/// Swift documentation for a module.
case swiftDocumentation = "swiftdoc"

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

/// Serialized source information.
case swiftSourceInfoFile = "swiftsourceinfo"

/// Assembler source.
case assembly = "s"

Expand Down Expand Up @@ -110,7 +113,7 @@ extension FileType: CustomStringConvertible {
public var description: String {
switch self {
case .swift, .sil, .sib, .image, .object, .dSYM, .dependencies, .autolink,
.swiftModule, .swiftDocumentation, .swiftInterface, .assembly,
.swiftModule, .swiftDocumentation, .swiftInterface, .swiftSourceInfoFile, .assembly,
.remap, .tbd, .pcm, .pch:
return rawValue

Expand Down Expand Up @@ -163,8 +166,83 @@ extension FileType {
case .object, .pch, .ast, .llvmIR, .llvmBitcode, .assembly, .swiftModule,
.importedModules, .indexData, .remap, .dSYM, .autolink, .dependencies,
.swiftDocumentation, .pcm, .diagnostics, .objcHeader, .image,
.swiftDeps, .moduleTrace, .tbd, .optimizationRecord, .swiftInterface:
.swiftDeps, .moduleTrace, .tbd, .optimizationRecord, .swiftInterface, .swiftSourceInfoFile:
return false
}
}
}

extension FileType {

private static let typesByName = Dictionary(uniqueKeysWithValues: FileType.allCases.map { ($0.name, $0) })

init?(name: String) {
guard let type = Self.typesByName[name] else { return nil }

self = type
}

/// The NAME values as specified in FileTypes.def
var name: String {
switch self {
case .swift:
return "swift"
case .sil:
return "sil"
case .sib:
return "sib"
case .image:
return "image"
case .object:
return "object"
case .dSYM:
return "dSYM"
case .dependencies:
return "dependencies"
case .autolink:
return "autolink"
case .swiftModule:
return "swiftmodule"
case .swiftDocumentation:
return "swiftdoc"
case .swiftInterface:
return "swiftinterface"
case .swiftSourceInfoFile:
return "swiftsourceinfo"
case .assembly:
return "assembly"
case .remap:
return "remap"
case .tbd:
return "tbd"
case .pcm:
return "pcm"
case .pch:
return "pch"
case .ast:
return "ast-dump"
case .raw_sil:
return "raw-sil"
case .raw_sib:
return "raw-sib"
case .llvmIR:
return "llvm-ir"
case .llvmBitcode:
return "llvm-bc"
case .objcHeader:
return "objc-header"
case .swiftDeps:
return "swift-dependencies"
case .importedModules:
return "imported-modules"
case .moduleTrace:
return "module-trace"
case .indexData:
return "index-data"
case .optimizationRecord:
return "opt-record"
case .diagnostics:
return "diagnostics"
}
}
}