The buf.gen.yaml
file defines a local plugin template, and is used by the buf generate
command to generate code for
the language(s) of your choice. This file is often used with a module (or another
input), and is typically placed next to your buf.work.yaml
file:
.
├── buf.gen.yaml
├── buf.work.yaml
├── acme
│  └── pet
│ └── v1
│  └── pet.proto
├── buf.lock
└── buf.yaml
An example of the buf.gen.yaml
file used to generate Go/gRPC stubs is shown below:
version: v1
plugins:
- plugin: go
out: gen/proto/go
opt: paths=source_relative
- plugin: buf.build/grpc/go:v1.2.0
out: gen/proto/go
opt:
- paths=source_relative
- require_unimplemented_servers=false
version
The version
key is required, and defines the current configuration version. The only accepted values are v1beta1
and v1
.
plugins
Each entry in the buf.gen.yaml
plugins
key is a protoc
plugin configuration, which is a program that generates
code by interacting with the compiled representation of your module.
plugin
plugin
is required.
Local Plugins:
To execute a locally installed plugin, specify the plugin name via the plugin
field. All protoc
plugins begin with
the protoc-gen-
prefix.
By default, a protoc-gen-<name>
program is expected to be on your PATH
so that it can be discovered and executed by
buf
. This can be overridden with the path option shown below.
Remote Plugins:
The plugin
field can specify a remotely executed plugin (<remote>/<owner>/<plugin-name>:<plugin-version>
or
<remote>/<owner>/<plugin-name>
). If a remotely executed plugin omits the <plugin-version>
, the latest version will
be used. If a <plugin-version>
is specified, the optional revision can be specified to pin an exact
revision of a plugin version.
out
The out
of a plugin is required, and controls where the generated files are deposited for a given plugin. Although
absolute paths are supported, this configuration is traditionally a relative output directory that depends on where
buf generate
is run. For example, running buf generate
from the root of the tree
shown above would result in a new
gen/proto/go
directory within the same root:
buf generate
tree
.
├── acme
│  └── pet
│ └── v1
│  └── pet.proto
├── gen
│  └── proto
│ └── go
│  └── ...
├── buf.gen.yaml
├── buf.lock
└── buf.yaml
opt
The opt
of a plugin is optional, and specifies one or more protoc
plugin options for each plugin independently.
In the buf.gen.yaml
example above, this is relevant for both protoc-gen-go
and protoc-gen-go-grpc
. As you can see,
you can provide options as either a single string or a list of strings.
path
The path
of a plugin is optional, and overrides the default location and explicitly specify where to locate the
protoc
plugin. For example, if another custom plugin called protoc-gen-foo
is not located on your PATH
, but is
found at bin/proto/protoc-gen-foo
, you can refer to it like this:
version: v1
plugins:
- plugin: foo
out: gen/foo
path: bin/proto/protoc-gen-foo
The path can include some arguments. If the path has more than one element, the first is the plugin binary and the
others are optional additional arguments to pass to the binary. For example, you can run the version of protoc-gen-go
that matches the google.golang.org/protobuf
specified by go.mod
by:
version: v1
plugins:
- plugin: go
path: ["go", "run", "google.golang.org/protobuf/cmd/protoc-gen-go"]
out: gen/proto
opt: paths=source_relative
This field only works with local plugins.
revision
The revision
is optional and may be used along with the plugin
field to pin an exact version of a remote plugin.
In most cases, it is recommended to omit the revision
, in which case the latest revision of the plugin will be used
(automatically pulling in the latest bug fixes).
Below is an example of using the revision to target an exact version of a plugin:
version: v1
plugins:
- plugin: buf.build/protocolbuffers/go:v1.28.1
revision: 1
out: gen/proto/go
opt: paths=source_relative
strategy
Your strategy
of a plugin is optional, and specifies the generation strategy
for buf generate
to use. For
example, we can add a strategy
to one of the plugins in the configuration shown above like this:
version: v1
plugins:
- plugin: go
out: gen/proto/go
opt: paths=source_relative
- plugin: go-grpc
out: gen/proto/go
opt:
- paths=source_relative
- require_unimplemented_servers=false
strategy: directory
There are two options:
directory
(default for local plugins)
This results in buf
splitting the input files by directory and making separate plugin invocations in parallel. That's
roughly the concurrent equivalent of this operation:
$ for dir in $(find . -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq); do
protoc -I . $(find "${dir}" -name '*.proto')
done
Almost every protoc
plugin either requires this, so this is the recommended strategy
. The directory
strategy is
used by default if omitted for local plugins. Remote plugins use all
for every invocation.
all
This results in buf
making a single plugin invocation with all input files, which is roughly equivalent to this:
$ protoc -I . $(find . -name '*.proto')
This is needed for certain plugins that expect all files to be given at once. It is also used for remote plugin generation to improve code generation performance.
protoc_path
The protoc_path
of a plugin is optional and only applies to the code generators that are built-in to protoc
.
Normally, a plugin is a separate executable whose binary name is like protoc-gen-<name>
. But for a handful of plugins,
the executable used is protoc
itself. The following plugins result in invoking protoc
instead of a dedicated plugin
binary:
cpp
csharp
java
js
(before v21)kotlin
(after v3.17)objc
php
pyi
python
ruby
Normally for the above plugins, buf
will execute the protoc
binary that is found in your $PATH
. But this
configuration option lets you point to a specific binary. This is particularly useful if you need to support a specific
version of protoc
, which could differ from the version in $PATH
. For example, you can run a specific version of
protoc
instead of the protoc
installed in $PATH
by:
version: v1
plugins:
- plugin: go
revision: 1
out: gen/proto/go
protoc_path: /path/to/specific/version/bin/protoc
managed
The managed
key is used to configure managed mode and is an advanced feature. A
complete example of the managed
configuration with the protoc-gen-go
plugin is shown below:
version: v1
managed:
enabled: true
cc_enable_arenas: false
java_multiple_files: false
java_package_prefix: com
java_string_check_utf8: false
optimize_for: CODE_SIZE
go_package_prefix:
default: github.com/acme/weather/private/gen/proto/go
except:
- buf.build/googleapis/googleapis
override:
buf.build/acme/weather: github.com/acme/weather/gen/proto/go
override:
JAVA_PACKAGE:
acme/weather/v1/weather.proto: "org"
plugins:
- plugin: go
out: gen/proto/go
opt: paths=source_relative
enabled
The enabled
key is required if any other managed
keys are set. Setting enabled
equal to true
enables
managed mode according to
default behavior.
cc_enable_arenas
The cc_enable_arenas
key is optional, and controls what the
cc_enable_arenas
value is set to in all of the files contained within the generation target input. The only accepted values are false
and true
.
java_multiple_files
The java_multiple_files
key is optional, and controls what the
java_multiple_files
value is set to in all of the files contained within the generation target input. The only accepted values are false
and true
.
java_package_prefix
The java_package_prefix
key is optional, and controls what the
java_package
prefix value is set to in all of the files contained within the generation target input. By default, the value is com
.
java_string_check_utf8
The java_string_check_utf8
key is optional, and controls what the
java_string_check_utf8
value is set to in all of the files contained within the generation target input. The only accepted values are false
and true
.
optimize_for
The optimize_for
key is optional, and controls what the
optimize_for
value is set to in all of the files contained within the generation target input. The only accepted values are SPEED
,
CODE_SIZE
and LITE_RUNTIME
. If omitted, the default value, SPEED
, is used.
go_package_prefix
The go_package_prefix
key is optional, and controls what the
go_package
value is set to in all the files contained within the generation target input.
default
The default
key is required if the go_package_prefix
key is set. The default
value is used as a prefix for the
go_package
value set in each of the files. The default
value must be a relative filepath that must not jump
context from the current directory, that is they must be subdirectories relative to the current working directory. As an
example, ../external
is invalid.
In the configuration example shown above, the github.com/acme/weather/gen/proto/go
prefix is joined with the given
Protobuf file's relative path from the module root. In the buf.build/acme/weather
module's case, the
acme/weather/v1/weather.proto
file would have this go_package
set:
syntax = "proto3";
package acme.weather.v1;
option go_package = "github.com/acme/weather/gen/proto/go/acme/weather/v1;weatherv1";
If the Protobuf file's package declaration conforms to the
PACKAGE_VERSION_SUFFIX
lint rule, the final two path elements are concatenated and included after the;
element in thego_package
result. The above example generates a Go package with a package declaration equal toweatherv1
, which enables you to import Go definitions from a variety of generated packages that would otherwise collide (a lot of Protobuf packages contain thev1
suffix).
except
The except
key is optional, and removes certain modules from the go_package
file option override behavior. The
except
values must be valid module names.
There are situations where you may want to enable managed mode for the go_package
option in most of your Protobuf files, but not necessarily for all of your Protobuf files. This is particularly
relevant for the buf.build/googleapis/googleapis
module, which points its go_package
value to an
external repository. Popular libraries, such as
grpc-go depend on these go_package
values, so it's important that managed mode does
not overwrite them.
override
The override
key is optional, and overrides the go_package
file option value used for specific modules. The
override
keys must be valid module names. Additionally, the corresponding override
values must be a valid
Go import path and must not jump context from the current directory. As an
example, ../external
is invalid.
This setting is used for workspace environments, where you have a module that imports
from another module in the same workspace, and you need to generate the Go code for each module in different
directories. This is particularly relevant for repositories that decouple their private API definitions from their
public API definitions (as is the case for buf
).
override
This is a list of per-file overrides for each modifier. In the example provided above, an override for
acme/weather/v1/weather.proto
is set for the java_package_prefix
modifier to be org
instead of com
. This sets
org
as the package prefix for only the specific acme/weather/v1/weather.proto
file and not for the rest of
the module.