Skip to content

Commit 6cb362c

Browse files
committed
Document use of the build plugin
Motivation: To ease use of the `grpc-swift-protobuf` Swift Package Manager build plugin. Modifications: Documentation added. Result: Greater understanding?
1 parent 5e92f64 commit 6cb362c

File tree

1 file changed

+92
-4
lines changed

1 file changed

+92
-4
lines changed

Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ Learn how to generate stubs for gRPC Swift from a service defined using the Prot
44

55
## Overview
66

7-
### Using protoc
8-
97
If you've used Protocol Buffers before then generating gRPC Swift stubs should be simple. If you're
108
unfamiliar with Protocol Buffers then you should get comfortable with the concepts before
119
continuing; the [Protocol Buffers website](https://protobuf.dev/) is a great place to start.
@@ -16,7 +14,17 @@ The [`grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf) package
1614
> `protoc-gen-grpc-swift` only generates gRPC stubs, it doesn't generate messages. You must use
1715
> `protoc-gen-swift` to generate messages in addition to gRPC Stubs.
1816
19-
To generate gRPC stubs for your `.proto` files you must run the `protoc` command with
17+
The protoc plugin can be used from the command line directly, passed to `protoc`, or
18+
you can make use of a convenience which adds the stub generation to the Swift build graph.
19+
The automatic gRPC Swift stub generation makes use of a [Swift Package Manager build plugin](
20+
https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) to use the
21+
`.proto` files as inputs to the build graph, input them into `protoc` using `protoc-gen-grpc-swift`
22+
and `protoc-gen-swift` as needed, and make the resulting gRPC Swift stubs available to code
23+
against without committing them as source. The build plugin may be invoked either from the command line or from Xcode.
24+
25+
### Using protoc
26+
27+
To generate gRPC stubs for your `.proto` files directly you must run the `protoc` command with
2028
the `--grpc-swift_out=<DIRECTORY>` option:
2129

2230
```console
@@ -69,7 +77,7 @@ allows you to specify a mapping from `.proto` files to the Swift module they are
6977
allows the code generator to add appropriate imports to your generated stubs. This is described in
7078
more detail in the [SwiftProtobuf documentation](https://github.com/apple/swift-protobuf/blob/main/Documentation/PLUGIN.md).
7179

72-
#### Building the plugin
80+
#### Building the protoc plugin
7381

7482
> The version of `protoc-gen-grpc-swift` you use mustn't be newer than the version of
7583
> the `grpc-swift-protobuf` you're using.
@@ -83,3 +91,83 @@ swift build --product protoc-gen-grpc-swift
8391

8492
This command will build the plugin into `.build/debug` directory. You can get the full path using
8593
`swift build --show-bin-path`.
94+
95+
## Using the build plugin
96+
97+
The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations.
98+
Because it generates the gRPC Swift stubs as part of the build it has the requirement that `protoc` must be guaranteed
99+
to be available at compile time. Also because of a limitation of Swift Package Manager build plugins, the plugin
100+
will only be invoked when applied to the source contained in a leaf package, so it is not useful for generating code for
101+
library authors.
102+
103+
The build plugin will detect `.proto` files in the source tree and perform one invocation of `protoc` for each file
104+
(caching results and performing the generation as necessary).
105+
106+
### Adoption
107+
Swift Package Manager build plugins must be adopted on a per-target basis, you can do this by modifying your
108+
package manifest (`Package.swift` file). You will need to declare the `grpc-swift-protobuf` package as a package
109+
dependency and then add the plugin to any desired targets.
110+
111+
For example, to make use of the plugin for generating gRPC Swift stubs as part of the
112+
`plugin-adopter` target:
113+
```swift
114+
targets: [
115+
.executableTarget(
116+
name: "plugin-adopter",
117+
dependencies: [
118+
// ...
119+
],
120+
plugins: [
121+
.plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf")
122+
]
123+
)
124+
]
125+
```
126+
Once this is done you need to ensure that that the `.proto` files to be used for generation
127+
are included in the target's source directory (below relevant the `Source` directory) and that you have
128+
defined at least one configuration file.
129+
130+
### Configuration
131+
132+
The build plugin requires a configuration file to be present in a directory which encloses all `.proto` files
133+
(in the same directory or a parent).
134+
Configuration files are JSON which tells the build plugin about the options which will be used in the
135+
invocations of `protoc`. Configuration files must be named `grpc-swift-proto-generator-config.json`
136+
and have the following format:
137+
```json
138+
{
139+
"generate": {
140+
"clients": true,
141+
"servers": true,
142+
"messages": true,
143+
},
144+
"generatedSource": {
145+
"accessLevelOnImports": false,
146+
"accessLevel": "internal",
147+
}
148+
"protoc": {
149+
"executablePath": "/opt/homebrew/bin/protoc"
150+
"importPaths": [
151+
"../directory_1",
152+
],
153+
},
154+
}
155+
```
156+
157+
The options do not need to be specified and each have default values.
158+
159+
| Name | Possible Values | Default | Description |
160+
|----------------------------------------|--------------------------------------------|--------------------------------------|----------------------------------------------------------|
161+
| `generate.servers` | `true`, `false` | `True` | Generate server stubs |
162+
| `generate.clients` | `true`, `false` | `True` | Generate client stubs |
163+
| `generate.messages` | `true`, `false` | `True` | Generate message stubs |
164+
| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels |
165+
| `generatedSource.accessLevel` | `public`, `package`, `internal` | `internal` | Access level for generated stubs |
166+
| `protoc.executablePath` | N/A | N/A (attempted discovery) | Path to the `protoc` executable |
167+
| `protoc.importPaths` | N/A | Directory containing the config file | Access level for generated stubs |
168+
169+
Many of these map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options.
170+
171+
If you require greater flexibility you may specify more than one configuration file.
172+
Configuration files apply to all `.proto` files equal to or below it in the file hierarchy. A configuration file
173+
lower in the file hierarchy supersedes one above it.

0 commit comments

Comments
 (0)