Generating-stubs.md 8.5 KB

Generating stubs

Learn how to generate stubs for gRPC Swift from a service defined using the Protocol Buffers IDL.

Overview

There are two approaches to generating stubs from Protocol Buffers:

  1. With the Swift Package Manager build plugin, or
  2. With the Protocol Buffers compiler (protoc).

The following sections describe how and when to use each.

Using the Swift Package Manager build plugin

You can generate stubs at build time by using GRPCSwiftPlugin which is a build plugin for the Swift Package Manager. Using it means that you don't have to manage the generation of stubs with separate tooling, or check the generated stubs into your source repository.

The build plugin will generate gRPC stubs for you by building protoc-gen-grpc-swift (more details in the following section) for you and invoking protoc. Because of the implicit dependency on protoc being made available by the system GRPCSwiftPlugin isn't suitable for use in:

  • Library packages, or
  • Environments where protoc isn't available.

GRPCSwiftPlugin only generates gRPC stubs, it doesn't generate messages. You must generate messages in addition to the gRPC Stubs. The Swift Protobuf project provides an equivalent build plugin, SwiftProtobufPlugin, for this.

Configuring the build plugin

You can configure which stubs GRPCSwiftPlugin generates and how via a configuration file. This must be called grpc-swift-config.json and can be placed anywhere in the source directory for your target.

A config file for the plugin is made up of a number of protoc invocations. Each invocation describes the inputs to protoc as well as any options.

The following is a list of options which can be applied to each invocation object:

  • protoFiles, an array of strings where each string is the path to an input .proto file relative to grpc-swift-config.json.
  • visibility, a string describing the access level of the generated stub (must be one of "public", "internal", or "package"). If not specified then stubs are generated as internal.
  • server, a boolean indicating whether server stubs should be generated. Defaults to true if not specified.
  • client, a boolean indicating whether client stubs should be generated. Defaults to true if not specified.
  • _V2, a boolean indicated whether the generated stubs should be for v2.x. Defaults to false if not specified.

The GRPCSwiftPlugin build plugin is currently shared between gRPC Swift v1.x and v2.x. To generate stubs for v2.x you must set _V2 to true in your config.

This option will be deprecated and removed once v2.x has been released.

Finding protoc

The build plugin requires a copy of the protoc binary to be available. To resolve which copy of the binary to use, GRPCSwiftPlugin will look at the following in order:

  1. The exact path specified in the protocPath property in grpc-swift-config.json, if present.
  2. The exact path specified in the PROTOC_PATH environment variable, if set.
  3. The first protoc binary found in your PATH environment variable.

Using the build plugin from Xcode

Xcode doesn't have access to your PATH so in order to use GRPCSwiftPlugin with Xcode you must either set protocPath in your grpc-swift-config.json or explicitly set PROTOC_PATH when opening Xcode.

You can do this by running:

env PROTOC_PATH=/path/to/protoc xed /path/to/your-project

Note that Xcode must not be open before running this command.

Example configuration

We recommend putting your config and .proto files in a directory called Protos within your target. Here's an example package structure:

MyPackage
├── Package.swift
└── Sources
    └── MyTarget
        └── Protos
            ├── foo
            │   └── bar
            │       ├── baz.proto
            │       └── buzz.proto
            └── grpc-swift-config.json

If you wanted the generated stubs from baz.proto to be public, and to only generate a client for buzz.proto then the grpc-swift-config could look like this:

{
  "invocations": [
    {
      "_V2": true,
      "protoFiles": ["foo/bar/baz.proto"],
      "visibility": "public"
    },
    {
      "_V2": true,
      "protoFiles": ["foo/bar/buzz.proto"],
      "server": false
    }
  ]
}

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 is a great place to start.

gRPC Swift provides protoc-gen-grpc-swift, a program which is a plugin for the Protocol Buffers compiler, protoc.

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 --grpc-swift_out=<DIRECTORY> option:

protoc --grpc-swift_out=. my-service.proto

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:

protoc --plugin=/path/to/protoc-gen-grpc-swift --grpc-swift_out=. my-service.proto

You can also specify various option the protoc-gen-grpc-swift via protoc using the --grpc-swift_opt argument:

protoc --grpc-swift_opt=<OPTION_NAME>=<OPTION_VALUE> --grpc-swift_out=.

You can specify multiple options by passing the --grpc-swift_opt argument multiple times:

protoc \
  --grpc-swift_opt=<OPTION_NAME1>=<OPTION_VALUE1> \
  --grpc-swift_opt=<OPTION_NAME2>=<OPTION_VALUE2> \
  --grpc-swift_out=.

Generator options

Name Possible Values Default Description
_V2 True, False False Whether stubs are generated for gRPC Swift v2.x
Visibility Public, Package, Internal Internal Access level for generated stubs
Server True, False True Generate server stubs
Client True, False True Generate client stubs
FileNaming FullPath, PathToUnderscore, DropPath FullPath How generated source files should be named. (See below.)
ProtoPathModuleMappings Path to module map .asciipb file. (See below.)
AccessLevelOnImports True, False True Whether imports should have explicit access levels.

The protoc-gen-grpc-swift binary is currently shared between gRPC Swift v1.x and v2.x. To generate stubs for v2.x you must specify _V2=True.

This option will be deprecated and removed once v2.x has been released.

The FileNaming option has three possible values, for an input of foo/bar/baz.proto the following output file will be generated:

  • FullPath: foo/bar/baz.grpc.swift.
  • PathToUnderscore: foo_bar_baz.grpc.swift
  • DropPath: baz.grpc.swift

The code generator assumes all inputs are generated into the same module, ProtoPathModuleMappings allows you to specify a mapping from .proto files to the Swift module they are generated in. This allows the code generator to add appropriate imports to your generated stubs. This is described in more detail in the SwiftProtobuf documentation.

Building the plugin

The version of protoc-gen-grpc-swift you use mustn't be newer than the version of the grpc-swift you're using.

If your package depends on grpc-swift then you can get a copy of protoc-gen-grpc-swift by building it directly:

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.