Skip to content

Commit

Permalink
Support proto-gen-swift's proto-to-module mapping.
Browse files Browse the repository at this point in the history
This feature lets us support build systems like Bazel where proto
files are spread out among multiple proto_library target, and each
such target becomes its own Swift module. Downstream modules (and
in our case, generated service code) must know which module has
the proto definitions that they depend on so that it can import
them. This information is conveyed using a text proto formatted
file that the build system generates as it traverses the build
graph.
  • Loading branch information
allevato authored and MrMage committed Dec 22, 2018
1 parent 824814b commit ff2d161
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Sources/protoc-gen-swiftgrpc/Generator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ class Generator {
for moduleName in moduleNames {
println("import \(moduleName)")
}
// Build systems like Bazel will generate the Swift service definitions in a different module
// than the rest of the protos defined in the same file (because they are generated by separate
// build rules that invoke the separate generator plugins). So, we need to specify module
// mappings to import the service protos as well as and any other proto modules that the file
// imports.
let moduleMappings = options.protoToModuleMappings
if let serviceProtoModuleName = moduleMappings.moduleName(forFile: file) {
println("import \(serviceProtoModuleName)")
}
for importedProtoModuleName in moduleMappings.neededModules(forFile: file) ?? [] {
println("import \(importedProtoModuleName)")
}
println()

if options.generateClient {
Expand Down
17 changes: 17 additions & 0 deletions Sources/protoc-gen-swiftgrpc/options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,24 @@
* limitations under the License.
*/
import Foundation
import SwiftProtobufPluginLibrary

enum GenerationError: Error {
/// Raised when parsing the parameter string and found an unknown key
case unknownParameter(name: String)
/// Raised when a parameter was giving an invalid value
case invalidParameterValue(name: String, value: String)
/// Raised to wrap another error but provide a context message.
case wrappedError(message: String, error: Error)

var localizedDescription: String {
switch self {
case .unknownParameter(let name):
return "Unknown generation parameter '\(name)'"
case .invalidParameterValue(let name, let value):
return "Unknown value for generation parameter '\(name)': '\(value)'"
case .wrappedError(let message, let error):
return "\(message): \(error.localizedDescription)"
}
}
}
Expand All @@ -53,6 +58,7 @@ final class GeneratorOptions {
private(set) var generateSynchronous = true
private(set) var generateTestStubs = false
private(set) var generateNIOImplementation = false
private(set) var protoToModuleMappings = ProtoFileToModuleMappings()

init(parameter: String?) throws {
for pair in GeneratorOptions.parseParameter(string: parameter) {
Expand Down Expand Up @@ -106,6 +112,17 @@ final class GeneratorOptions {
throw GenerationError.invalidParameterValue(name: pair.key, value: pair.value)
}

case "ProtoPathModuleMappings":
if !pair.value.isEmpty {
do {
protoToModuleMappings = try ProtoFileToModuleMappings(path: pair.value)
} catch let e {
throw GenerationError.wrappedError(
message: "Parameter 'ProtoPathModuleMappings=\(pair.value)'",
error: e)
}
}

default:
throw GenerationError.unknownParameter(name: pair.key)
}
Expand Down

0 comments on commit ff2d161

Please sign in to comment.