Skip to content

Commit ff2d161

Browse files
allevatoMrMage
authored andcommitted
Support proto-gen-swift's proto-to-module mapping.
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.
1 parent 824814b commit ff2d161

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

Sources/protoc-gen-swiftgrpc/Generator.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,18 @@ class Generator {
9191
for moduleName in moduleNames {
9292
println("import \(moduleName)")
9393
}
94+
// Build systems like Bazel will generate the Swift service definitions in a different module
95+
// than the rest of the protos defined in the same file (because they are generated by separate
96+
// build rules that invoke the separate generator plugins). So, we need to specify module
97+
// mappings to import the service protos as well as and any other proto modules that the file
98+
// imports.
99+
let moduleMappings = options.protoToModuleMappings
100+
if let serviceProtoModuleName = moduleMappings.moduleName(forFile: file) {
101+
println("import \(serviceProtoModuleName)")
102+
}
103+
for importedProtoModuleName in moduleMappings.neededModules(forFile: file) ?? [] {
104+
println("import \(importedProtoModuleName)")
105+
}
94106
println()
95107

96108
if options.generateClient {

Sources/protoc-gen-swiftgrpc/options.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,24 @@
1414
* limitations under the License.
1515
*/
1616
import Foundation
17+
import SwiftProtobufPluginLibrary
1718

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

2427
var localizedDescription: String {
2528
switch self {
2629
case .unknownParameter(let name):
2730
return "Unknown generation parameter '\(name)'"
2831
case .invalidParameterValue(let name, let value):
2932
return "Unknown value for generation parameter '\(name)': '\(value)'"
33+
case .wrappedError(let message, let error):
34+
return "\(message): \(error.localizedDescription)"
3035
}
3136
}
3237
}
@@ -53,6 +58,7 @@ final class GeneratorOptions {
5358
private(set) var generateSynchronous = true
5459
private(set) var generateTestStubs = false
5560
private(set) var generateNIOImplementation = false
61+
private(set) var protoToModuleMappings = ProtoFileToModuleMappings()
5662

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

115+
case "ProtoPathModuleMappings":
116+
if !pair.value.isEmpty {
117+
do {
118+
protoToModuleMappings = try ProtoFileToModuleMappings(path: pair.value)
119+
} catch let e {
120+
throw GenerationError.wrappedError(
121+
message: "Parameter 'ProtoPathModuleMappings=\(pair.value)'",
122+
error: e)
123+
}
124+
}
125+
109126
default:
110127
throw GenerationError.unknownParameter(name: pair.key)
111128
}

0 commit comments

Comments
 (0)