Skip to content

Commit dc63f44

Browse files
authored
Add more documentation about code generation (#83)
Motivation: Users (especially new ones) often have issues with generating code. This package provide a number of ways to do this but doesn't do a good job of explaining the pros and cons of each method or how to use each of them. Modifications: - Split up the generating stubs doc into four parts: one article for each method explaining how to use that approach. For the build plugin and protoc the content was more or less directly moves from the existing doc. - Reprurpose the existing generating stubs doc to explain the pros and cons of each approach to make it easier for users to decide. Result: Better docs
1 parent 328f01e commit dc63f44

File tree

5 files changed

+382
-174
lines changed

5 files changed

+382
-174
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Code generation with protoc
2+
3+
This article describes how to use the Swift Package Manager build plugin to
4+
generate gRPC Swift and Swift Protobuf code from your Protocol Buffers `.proto` files.
5+
6+
## Overview
7+
8+
If you've used Protocol Buffers before then generating gRPC Swift stubs should be simple. If you're
9+
unfamiliar with Protocol Buffers then you should get comfortable with the concepts before
10+
continuing; the [Protocol Buffers website](https://protobuf.dev/) is a great place to start.
11+
12+
If you haven't installed `protoc` yet refer to <doc:Installing-protoc> for
13+
instructions.
14+
15+
## Using protoc
16+
17+
The [`grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf) package provides
18+
`protoc-gen-grpc-swift-2`, a program which is a plugin for the Protocol Buffers compiler, `protoc`.
19+
To generate gRPC stubs for your `.proto` files directly you must run the `protoc` command with
20+
the `--grpc-swift-2_out=<DIRECTORY>` option:
21+
22+
```console
23+
protoc --grpc-swift-2_out=. my-service.proto
24+
```
25+
26+
> `protoc-gen-grpc-swift-2` only generates gRPC stubs, it doesn't generate messages. You must use
27+
> `protoc-gen-swift` to generate messages in addition to gRPC Stubs.
28+
29+
The presence of `--grpc-swift-2_out` tells `protoc` to use the `protoc-gen-grpc-swift-2` plugin. By
30+
default it'll look for the plugin in your `PATH`. You can also specify the path to the plugin
31+
explicitly:
32+
33+
```console
34+
protoc --plugin=/path/to/protoc-gen-grpc-swift-2 --grpc-swift-2_out=. my-service.proto
35+
```
36+
37+
You can specify various options to `protoc-gen-grpc-swift-2` via `protoc` using
38+
the `--grpc-swift-2_opt` argument:
39+
40+
```console
41+
protoc --grpc-swift-2_opt=<OPTION_NAME>=<OPTION_VALUE> --grpc-swift-2_out=.
42+
```
43+
44+
You can specify multiple options by repeating the `--grpc-swift-2_opt` argument:
45+
46+
```console
47+
protoc \
48+
--grpc-swift-2_opt=<OPTION_NAME1>=<OPTION_VALUE1> \
49+
--grpc-swift-2_opt=<OPTION_NAME2>=<OPTION_VALUE2> \
50+
--grpc-swift-2_out=.
51+
```
52+
53+
### Generator options
54+
55+
| Name | Possible Values | Default | Description |
56+
|---------------------------|---------------------------------------------|-----------------|----------------------------------------------------------|
57+
| `Visibility` | `Public`, `Package`, `Internal` | `Internal` | Access level for generated stubs |
58+
| `Server` | `True`, `False` | `True` | Generate server stubs |
59+
| `Client` | `True`, `False` | `True` | Generate client stubs |
60+
| `FileNaming` | `FullPath`, `PathToUnderscores`, `DropPath` | `FullPath` | How generated source files should be named. † |
61+
| `ProtoPathModuleMappings` | | | Path to module map `.asciipb` file. ‡ |
62+
| `UseAccessLevelOnImports` | `True`, `False` | `False` | Whether imports should have explicit access levels. |
63+
| `GRPCModuleName` | | `GRPCCore` | The name of the `GRPCCore` module. |
64+
| `GRPCProtobufModuleName` | | `GRPCProtobuf` | The name of the `GRPCProtobuf` module. |
65+
| `SwiftProtobufModuleName` | | `SwiftProtobuf` | The name of the `SwiftProtobuf` module. |
66+
| `Availability` | String, in the form `OS Version` | | Platform availability to use in generated code. § |
67+
68+
† The `FileNaming` option has three possible values, for an input of `foo/bar/baz.proto` the following
69+
output file will be generated:
70+
- `FullPath`: `foo/bar/baz.grpc.swift`.
71+
- `PathToUnderscores`: `foo_bar_baz.grpc.swift`
72+
- `DropPath`: `baz.grpc.swift`
73+
74+
‡ The code generator assumes all inputs are generated into the same module, `ProtoPathModuleMappings`
75+
allows you to specify a mapping from `.proto` files to the Swift module they are generated in. This
76+
allows the code generator to add appropriate imports to your generated stubs. This is described in
77+
more detail in the [SwiftProtobuf documentation](https://github.com/apple/swift-protobuf/blob/main/Documentation/PLUGIN.md).
78+
79+
§ If unspecified the following availability is used: macOS 15, iOS 18, tvOS 18,
80+
watchOS 11, visionOS 2. The `Availability` option may be specified multiple
81+
times, where each value is a space delimited pair of platform and version, e.g.
82+
`Availability=macOS 15.0`.
83+
84+
### Building the protoc plugin
85+
86+
> The version of `protoc-gen-grpc-swift-2` you use mustn't be newer than the version of
87+
> the `grpc-swift-protobuf` you're using.
88+
89+
If your package depends on `grpc-swift-protobuf` then you can get a copy of `protoc-gen-grpc-swift-2`
90+
by building it directly:
91+
92+
```console
93+
swift build --product protoc-gen-grpc-swift-2
94+
```
95+
96+
This command will build the plugin into `.build/debug` directory. You can get the full path using
97+
`swift build --show-bin-path`.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Code generation with the build plugin
2+
3+
This article describes how to use `protoc` to generate stubs for gRPC Swift and
4+
Swift Protobuf from your Protocol Buffers `.proto` files.
5+
6+
## Overview
7+
8+
The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient
9+
dynamic code generation, however it does come with some limitations. Because it
10+
generates the gRPC Swift stubs as part of the build it has the requirement that
11+
`protoc` must be available at compile time. This requirement means it is not a
12+
good fit for library authors who do not have direct control over this.
13+
14+
To learn more about other options for code generation see <doc:Generating-stubs>.
15+
16+
The build plugin works by detecting `.proto` files in the source tree and
17+
invokes `protoc` once for each file (caching results and performing the
18+
generation as necessary).
19+
20+
If you haven't installed `protoc` yet refer to <doc:Installing-protoc> for
21+
instructions.
22+
23+
### Adoption
24+
25+
You must adopt Swift Package Manager build plugins on a per-target basis by
26+
modifying your package manifest (`Package.swift` file). To do this, declare the
27+
`grpc-swift-protobuf` package as a dependency and add the plugin to your desired
28+
targets.
29+
30+
For example, to make use of the plugin for generating gRPC Swift stubs as part
31+
of the `echo-server` target:
32+
33+
```swift
34+
targets: [
35+
.executableTarget(
36+
name: "echo-server",
37+
dependencies: [
38+
// ...
39+
],
40+
plugins: [
41+
.plugin(
42+
name: "GRPCProtobufGenerator",
43+
package: "grpc-swift-protobuf"
44+
)
45+
]
46+
)
47+
]
48+
```
49+
50+
Once this is done you need to ensure that the `.proto` files to be used for
51+
generation are included in the target's source directory and that you have
52+
defined a configuration file.
53+
54+
## Configuration
55+
56+
You must provide a configuration file named
57+
`grpc-swift-proto-generator-config.json` in the directory which encloses all
58+
`.proto` files (in the same directory as the files or a parent directory). The
59+
configuration file tells the build plugin about the options used for `protoc`
60+
invocations.
61+
62+
> Warning:
63+
> The name of the config file is important and must match exactly, the
64+
> plugin won't be applied if it can't find the config file.
65+
66+
You can use the following as a starting point for your configuration:
67+
68+
```json
69+
{
70+
"generate": {
71+
"clients": true,
72+
"servers": true,
73+
"messages": true
74+
}
75+
}
76+
```
77+
78+
By default clients, servers, and messages will be generated with the `internal`
79+
access level.
80+
81+
The full structure of the config file looks like this:
82+
83+
```json
84+
{
85+
"generate": {
86+
"clients": true,
87+
"servers": true,
88+
"messages": true
89+
},
90+
"generatedSource": {
91+
"accessLevelOnImports": false,
92+
"accessLevel": "internal"
93+
},
94+
"protoc": {
95+
"executablePath": "/opt/homebrew/bin/protoc",
96+
"importPaths": [
97+
"../directory_1"
98+
]
99+
}
100+
}
101+
```
102+
103+
Each of the options are described below:
104+
105+
| Name | Possible Values | Default | Description |
106+
|----------------------------------------|--------------------------------------------|--------------|-----------------------------------------------------|
107+
| `generate.servers` | `true`, `false` | `true` | Generate server stubs |
108+
| `generate.clients` | `true`, `false` | `true` | Generate client stubs |
109+
| `generate.messages` | `true`, `false` | `true` | Generate message stubs |
110+
| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels |
111+
| `generatedSource.accessLevel` | `"public"`, `"package"`, `"internal"` | `"internal"` | Access level for generated stubs |
112+
| `protoc.executablePath` | N/A | `null`| Path to the `protoc` executable |
113+
| `protoc.importPaths` | N/A | `null`| Import paths passed to `protoc` |
114+
115+
† The Swift Package Manager build plugin infrastructure will attempt to discover
116+
the executable's location if you don't provide one.
117+
118+
‡ If you don't provide any import paths then the path to the configuration file
119+
will be used on a per-source-file basis.
120+
121+
Many of these options map to `protoc-gen-grpc-swift-2` and `protoc-gen-swift`
122+
options.
123+
124+
If you require greater flexibility you may specify more than one configuration
125+
file. Configuration files apply to all `.proto` files equal to or below it in
126+
the file hierarchy. A configuration file lower in the file hierarchy supersedes
127+
one above it.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Code generation with generate-grpc-code-from-protos
2+
3+
This article describes how to use the `generate-grpc-code-from-protos` Swift
4+
Package Manager command plugin to generate gRPC Swift and Swift Protobuf code
5+
from your Protocol Buffers `.proto` files.
6+
7+
This plugin is particularly useful for:
8+
9+
- **Manual, on-demand code generation:** When you prefer to explicitly generate
10+
code rather than relying on a build tool plugin.
11+
- **Libraries:** For Swift packages intended as libraries, where generated
12+
source code should be checked into your repository to avoid external `protoc`
13+
dependencies for your library's consumers.
14+
15+
If you haven't installed `protoc` yet refer to <doc:Installing-protoc> for
16+
instructions.
17+
18+
## Adding the Plugin to Your Package
19+
20+
To use `generate-grpc-code-from-protos` your package needs to depend on
21+
`grpc-swift-protobuf`. You **don't** need to add a dependency on each target
22+
like you would for the build plugin.
23+
24+
## Basic Usage
25+
26+
Once your package depends on `grpc-swift-protobuf` you can invoke it using:
27+
28+
```sh
29+
swift package generate-grpc-code-from-protos path/to/YourService.proto path/to/YourMessages.proto
30+
```
31+
32+
If you've organised your protos within a single directory then you can
33+
pass the path of the directory as an argument instead, the plugin will find
34+
all `.proto` files nested within that directory:
35+
36+
```sh
37+
swift package generate-grpc-code-from-protos Protos
38+
```
39+
40+
By default the plugin generates code for gRPC servers, clients, and Protobuf
41+
messages into the current working directory. To change where the code is
42+
generated you can specify the `--output-path` option:
43+
44+
45+
```sh
46+
swift package generate-grpc-code-from-protos --output-path Sources/Generated -- Protos
47+
```
48+
49+
> Important: The "`--`" separates options and inputs passed to the plugin.
50+
>
51+
> Everything after "`--`" is treated as an input (a `.proto` file or a
52+
> directory), everything before "`--`" is treated as an option with a value or
53+
> a flag. If there is no "`--`" then all arguments are treated as input.
54+
55+
You should now have a basic understanding of how to use the plugin. You can
56+
configure how the code is generated via a number of options, a few commonly used
57+
ones are:
58+
- `--no-client` disables client code generation,
59+
- `--no-server` disables server code generation,
60+
- `--no-messages` disables message code generation,
61+
- `--access-level <access>` specifies the access level of the generated code,
62+
(`<access>` must be one of "internal", "package", or "public").
63+
64+
You can read about other options by referring to the `--help` text:
65+
66+
```sh
67+
swift package generate-grpc-code-from-protos --help
68+
```
69+
70+
### Permissions
71+
72+
Swift Package Manager command plugins require permission to create files. You'll
73+
be prompted to give `generate-grpc-code-from-protos` permission when running it.
74+
To avoid being prompted you can grant permissions ahead of time by specifying
75+
`--allow-writing-to-package-directory` to the `swift package` command. For
76+
example:
77+
78+
```sh
79+
swift package --allow-writing-to-package-directory generate-grpc-code-from-protos Protos
80+
```

0 commit comments

Comments
 (0)