--xxx_out flag that does not correspond to a built-in language causes protoc to invoke an external plugin.
Plugin naming convention
Plugins follow a strict naming convention:protoc-gen-<name>. When you pass --foo_out=DST_DIR to protoc, it looks for an executable named protoc-gen-foo on $PATH (or at the path specified with --plugin=protoc-gen-foo=/path/to/binary).
Plugin protocol
protoc communicates with plugins over stdin and stdout using a well-defined binary protocol. No network or file system is used—plugins are simple executables.protoc parses and validates the .proto files
Before invoking any plugin, protoc fully parses all input
.proto files, resolves imports, and performs semantic validation.protoc serializes a CodeGeneratorRequest
protoc builds a
google.protobuf.compiler.CodeGeneratorRequest message containing the parsed FileDescriptorProto objects for all input files, the list of files to generate, and any options string passed via --foo_out=OPT:DST_DIR.protoc forks the plugin and writes the request to stdin
protoc forks the plugin executable and writes the serialized
CodeGeneratorRequest to the plugin’s stdin as a length-prefixed binary protobuf message.The plugin reads the request, generates code, and writes a CodeGeneratorResponse
The plugin reads the request from stdin, generates output files, and writes a serialized
google.protobuf.compiler.CodeGeneratorResponse message to its stdout. Each file in the response has a name (relative path) and content (file content as a string).Key message types
Both messages are defined ingoogle/protobuf/compiler/plugin.proto, which ships with protobuf.
Passing options to plugins
You can pass an options string to a plugin using theOPT:DST_DIR syntax:
request.parameter.
Writing a custom plugin
You can write a plugin in any language that can read from stdin and write to stdout. The simplest approach is to use an existing protobuf library to deserialize theCodeGeneratorRequest and serialize the CodeGeneratorResponse.
Below is a minimal Python plugin skeleton that generates a .txt file listing all messages in each .proto file:
protoc-gen-msglist, make it executable, and place it on $PATH:
Popular third-party plugins
protoc-gen-go
Official Go plugin. Install with
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest.protoc-gen-go-grpc
Go gRPC service stubs. Install with
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest.grpc_cpp_plugin
C++ gRPC service stubs, shipped with gRPC. Invoke via
--grpc_out with --plugin=protoc-gen-grpc=$(which grpc_cpp_plugin).protoc-gen-validate
Field-level validation rules for multiple languages. Part of the
bufbuild/protoc-gen-validate project.protoc-gen-openapi
Generates OpenAPI v3 specs from proto service definitions. Part of
google/gnostic.buf
An all-in-one protobuf toolchain that wraps protoc and manages plugins via
buf.gen.yaml configuration.