-
Notifications
You must be signed in to change notification settings - Fork 428
Document use of the build plugin #2176
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
Changes from 1 commit
6cb362c
9e70d5c
5df133f
299f6b8
9b9c1ad
3d2e229
5a33c78
7c0d31d
03aafc5
31dfa48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -4,8 +4,6 @@ Learn how to generate stubs for gRPC Swift from a service defined using the Prot | |||||||||||||
|
||||||||||||||
## Overview | ||||||||||||||
|
||||||||||||||
### Using protoc | ||||||||||||||
|
||||||||||||||
If you've used Protocol Buffers before then generating gRPC Swift stubs should be simple. If you're | ||||||||||||||
unfamiliar with Protocol Buffers then you should get comfortable with the concepts before | ||||||||||||||
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 | |||||||||||||
> `protoc-gen-grpc-swift` only generates gRPC stubs, it doesn't generate messages. You must use | ||||||||||||||
> `protoc-gen-swift` to generate messages in addition to gRPC Stubs. | ||||||||||||||
|
||||||||||||||
To generate gRPC stubs for your `.proto` files you must run the `protoc` command with | ||||||||||||||
The protoc plugin can be used from the command line directly, passed to `protoc`, or | ||||||||||||||
you can make use of a convenience which adds the stub generation to the Swift build graph. | ||||||||||||||
The automatic gRPC Swift stub generation makes use of a [Swift Package Manager build plugin]( | ||||||||||||||
https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) to use the | ||||||||||||||
`.proto` files as inputs to the build graph, input them into `protoc` using `protoc-gen-grpc-swift` | ||||||||||||||
and `protoc-gen-swift` as needed, and make the resulting gRPC Swift stubs available to code | ||||||||||||||
against without committing them as source. The build plugin may be invoked either from the command line or from Xcode. | ||||||||||||||
|
||||||||||||||
### Using protoc | ||||||||||||||
|
||||||||||||||
To generate gRPC stubs for your `.proto` files directly you must run the `protoc` command with | ||||||||||||||
the `--grpc-swift_out=<DIRECTORY>` option: | ||||||||||||||
|
||||||||||||||
```console | ||||||||||||||
|
@@ -69,7 +77,7 @@ allows you to specify a mapping from `.proto` files to the Swift module they are | |||||||||||||
allows the code generator to add appropriate imports to your generated stubs. This is described in | ||||||||||||||
more detail in the [SwiftProtobuf documentation](https://github.com/apple/swift-protobuf/blob/main/Documentation/PLUGIN.md). | ||||||||||||||
|
||||||||||||||
#### Building the plugin | ||||||||||||||
#### Building the protoc plugin | ||||||||||||||
|
||||||||||||||
> The version of `protoc-gen-grpc-swift` you use mustn't be newer than the version of | ||||||||||||||
> the `grpc-swift-protobuf` you're using. | ||||||||||||||
|
@@ -83,3 +91,83 @@ swift build --product protoc-gen-grpc-swift | |||||||||||||
|
||||||||||||||
This command will build the plugin into `.build/debug` directory. You can get the full path using | ||||||||||||||
`swift build --show-bin-path`. | ||||||||||||||
|
||||||||||||||
## Using the build plugin | ||||||||||||||
|
||||||||||||||
The build plugin (`GRPCProtobufGenerator`) is a great choice for convenient dynamic code generation, however it does come with some limitations. | ||||||||||||||
Because it generates the gRPC Swift stubs as part of the build it has the requirement that `protoc` must be guaranteed | ||||||||||||||
to be available at compile time. Also because of a limitation of Swift Package Manager build plugins, the plugin | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "must" and "guaranteed" are both requirements, let's get rid of one
Suggested change
|
||||||||||||||
will only be invoked when applied to the source contained in a leaf package, so it is not useful for generating code for | ||||||||||||||
library authors. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't actually true. The reason you can't use this build plugin in non-leaf packages is that it forces an implicit build time dependency on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, thanks for pointing that out! I'll have to refresh my knowledge of the docs. |
||||||||||||||
|
||||||||||||||
The build plugin will detect `.proto` files in the source tree and perform one invocation of `protoc` for each file | ||||||||||||||
(caching results and performing the generation as necessary). | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to write in the active voice, e.g. "The build plugin detects |
||||||||||||||
|
||||||||||||||
### Adoption | ||||||||||||||
Swift Package Manager build plugins must be adopted on a per-target basis, you can do this by modifying your | ||||||||||||||
package manifest (`Package.swift` file). You will need to declare the `grpc-swift-protobuf` package as a package | ||||||||||||||
dependency and then add the plugin to any desired targets. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: active voice "You must adopt Swift Package Manager build plugins on a per-target basis by modifying your package manifest (Package.swift file). To do this, declare the |
||||||||||||||
|
||||||||||||||
For example, to make use of the plugin for generating gRPC Swift stubs as part of the | ||||||||||||||
`plugin-adopter` target: | ||||||||||||||
```swift | ||||||||||||||
targets: [ | ||||||||||||||
.executableTarget( | ||||||||||||||
name: "plugin-adopter", | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: use an example name that gives more of hint as to where it could / should be used, e.g "echo-server" |
||||||||||||||
dependencies: [ | ||||||||||||||
// ... | ||||||||||||||
], | ||||||||||||||
plugins: [ | ||||||||||||||
.plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf") | ||||||||||||||
] | ||||||||||||||
) | ||||||||||||||
] | ||||||||||||||
``` | ||||||||||||||
Once this is done you need to ensure that that the `.proto` files to be used for generation | ||||||||||||||
are included in the target's source directory (below relevant the `Source` directory) and that you have | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no directory named
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to make reference to the |
||||||||||||||
defined at least one configuration file. | ||||||||||||||
|
||||||||||||||
### Configuration | ||||||||||||||
|
||||||||||||||
The build plugin requires a configuration file to be present in a directory which encloses all `.proto` files | ||||||||||||||
(in the same directory or a parent). | ||||||||||||||
Configuration files are JSON which tells the build plugin about the options which will be used in the | ||||||||||||||
invocations of `protoc`. Configuration files must be named `grpc-swift-proto-generator-config.json` | ||||||||||||||
and have the following format: | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Active voice: "You must provide a configuration file in the directory which encloses all |
||||||||||||||
```json | ||||||||||||||
{ | ||||||||||||||
"generate": { | ||||||||||||||
"clients": true, | ||||||||||||||
"servers": true, | ||||||||||||||
"messages": true, | ||||||||||||||
}, | ||||||||||||||
"generatedSource": { | ||||||||||||||
"accessLevelOnImports": false, | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forgot to mention that this change never actually got made, the config is still using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||
"accessLevel": "internal", | ||||||||||||||
} | ||||||||||||||
"protoc": { | ||||||||||||||
"executablePath": "/opt/homebrew/bin/protoc" | ||||||||||||||
"importPaths": [ | ||||||||||||||
"../directory_1", | ||||||||||||||
], | ||||||||||||||
}, | ||||||||||||||
} | ||||||||||||||
``` | ||||||||||||||
|
||||||||||||||
The options do not need to be specified and each have default values. | ||||||||||||||
|
||||||||||||||
| Name | Possible Values | Default | Description | | ||||||||||||||
|----------------------------------------|--------------------------------------------|--------------------------------------|----------------------------------------------------------| | ||||||||||||||
| `generate.servers` | `true`, `false` | `True` | Generate server stubs | | ||||||||||||||
| `generate.clients` | `true`, `false` | `True` | Generate client stubs | | ||||||||||||||
| `generate.messages` | `true`, `false` | `True` | Generate message stubs | | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels | | ||||||||||||||
| `generatedSource.accessLevel` | `public`, `package`, `internal` | `internal` | Access level for generated stubs | | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we're describing JSON, these should be strings
Suggested change
|
||||||||||||||
| `protoc.executablePath` | N/A | N/A (attempted discovery) | Path to the `protoc` executable | | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it's JSON the default is
Suggested change
|
||||||||||||||
| `protoc.importPaths` | N/A | Directory containing the config file | Access level for generated stubs | | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The description is wrong here. Also like above we put the default as |
||||||||||||||
|
||||||||||||||
Many of these map to `protoc-gen-grpc-swift` and `protoc-gen-swift` options. | ||||||||||||||
|
||||||||||||||
If you require greater flexibility you may specify more than one configuration file. | ||||||||||||||
Configuration files apply to all `.proto` files equal to or below it in the file hierarchy. A configuration file | ||||||||||||||
lower in the file hierarchy supersedes one above it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should pull this further up (so that it's the second paragraph) and make it more concise. We can then expand in each section. I'd like it so that the overview is like a landing page; you're giving the reader a brief introduction and then giving them a choice (manual generation with protoc vs. automated with build plugin.)
To that end it might be worth swapping the two around and having the build plugin first (progressive disclosure?).