diff --git a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md index 80c983184..88c2108a9 100644 --- a/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md +++ b/Sources/GRPCCore/Documentation.docc/Articles/Generating-stubs.md @@ -4,25 +4,109 @@ 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. -The [`grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf) package provides -`protoc-gen-grpc-swift`, a program which is a plugin for the Protocol Buffers compiler, `protoc`. +You can use the `protoc` plugin from the command line directly, or you can make use of a + [Swift Package Manager build plugin](https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) +convenience which adds the stub generation to the Swift build graph. +You may use the build plugin either from the command line or from Xcode. + +## 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 available +at compile time. This requirement means it is not a good fit for library authors who do not have +direct control over this. + +The build plugin detects `.proto` files in the source tree and invokes `protoc` once for each file +(caching results and performing the generation as necessary). + +### Adoption +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 grpc-swift-protobuf package as a dependency and add the plugin +to your desired targets. + +For example, to make use of the plugin for generating gRPC Swift stubs as part of the +`echo-server` target: +```swift +targets: [ + .executableTarget( + name: "echo-server", + dependencies: [ + // ... + ], + plugins: [ + .plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf") + ] + ) + ] +``` +Once this is done you need to ensure that the `.proto` files to be used for generation +are included in the target's source directory and that you have defined at least one configuration file. + +### Configuration + +You must provide a configuration file in the directory which encloses all `.proto` files (in the same directory or a parent). +Configuration files, written in JSON, tell the build plugin about the options used for `protoc` invocations. +You must name the file `grpc-swift-proto-generator-config.json` and structure it in the following format: +```json +{ + "generate": { + "clients": true, + "servers": true, + "messages": true, + }, + "generatedSource": { + "accessLevelOnImports": false, + "accessLevel": "internal", + } + "protoc": { + "executablePath": "/opt/homebrew/bin/protoc" + "importPaths": [ + "../directory_1", + ], + }, +} +``` -> `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. +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 | +| `generatedSource.accessLevelOnImports` | `true`, `false` | `false` | Whether imports should have explicit access levels | +| `generatedSource.accessLevel` | `"public"`, `"package"`, `"internal"` | `"internal"` | Access level for generated stubs | +| `protoc.executablePath` | N/A | `null`† | Path to the `protoc` executable | +| `protoc.importPaths` | N/A | `null`‡ | Import paths passed to `protoc` | + +† The Swift Package Manager build plugin infrastructure will attempt to discover the executable's location if you don't provide one. -To generate gRPC stubs for your `.proto` files you must run the `protoc` command with +‡ If you don't provide any import paths then the path to the configuration file will be used on a per-source-file basis. + +Many of these options 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. + +### Using protoc + +The [`grpc-swift-protobuf`](https://github.com/grpc/grpc-swift-protobuf) package provides +`protoc-gen-grpc-swift`, a program which is a plugin for the Protocol Buffers compiler, `protoc`. +To generate gRPC stubs for your `.proto` files directly you must run the `protoc` command with the `--grpc-swift_out=` option: ```console protoc --grpc-swift_out=. my-service.proto ``` +> `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. + The presence of `--grpc-swift_out` tells `protoc` to use the `protoc-gen-grpc-swift` plugin. By default it'll look for the plugin in your `PATH`. You can also specify the path to the plugin explicitly: @@ -69,7 +153,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.