Compiling Protocol Buffers
1. Generating Code with protoc
Example: Generate Go + gRPC code
protoc \
--proto_path=proto \
--go_out=gen --go_opt=paths=source_relative \
--go-grpc_out=gen --go-grpc_opt=paths=source_relative \
proto/user/v1/user.proto
| Flag | Purpose |
|---|---|
--proto_path / -I | Search root for imports |
--<lang>_out | Output dir for that language |
--<lang>_opt | Plugin-specific options |
2. Specifying Output Directory
| Pattern | Example |
|---|---|
| Per-language dir | --go_out=gen/go --java_out=gen/java |
| Source-relative | --go_opt=paths=source_relative |
| Import-relative | --go_opt=paths=import (default) |
3. Setting Import Paths
| Flag | Purpose |
|---|---|
-I=proto | Local protos root |
-I=third_party/googleapis | Vendored google APIs |
Multiple -I | Searched in order |
4. Generating Multiple Language Outputs
Example: Multi-language generation
protoc -I proto \
--go_out=gen/go --go-grpc_out=gen/go \
--python_out=gen/python --grpc_python_out=gen/python \
--java_out=gen/java --grpc-java_out=gen/java \
proto/**/*.proto
| Tip | Detail |
|---|---|
| Single source of truth | Keep .proto in dedicated repo or monorepo path |
| Publish artifacts | Push generated SDKs to language registries |
5. Using Generation Plugins
| Plugin | Output |
|---|---|
| protoc-gen-go | Go messages |
| protoc-gen-go-grpc | Go gRPC stubs |
| protoc-gen-grpc-gateway | REST gateway |
| protoc-gen-openapiv2 | OpenAPI spec |
| ts-proto | TypeScript |
| protoc-gen-validate | Validation methods |
6. Generating gRPC Service Code
| Language | Service Output |
|---|---|
| Go | *_grpc.pb.go with UnimplementedXServer |
| Python | *_pb2_grpc.py with add_XServicer_to_server |
| Java | XGrpc.java with ImplBase |
7. Generating Message Code Only
| Scenario | Flag |
|---|---|
| Just messages | Omit --<lang>-grpc_out |
| Just gRPC stubs | Use both plugins, ship messages from upstream module |
8. Setting Module Paths
| Option | Use |
|---|---|
--go_opt=module=example.com/api | Strip prefix in output paths |
option go_package = "example.com/api/user/v1;userv1"; | Per-file override |
9. Using Buf for Compilation
Example: Generate with Buf
buf generate # uses buf.gen.yaml
buf lint # style check
buf breaking --against '.git#branch=main'
| Advantage over protoc | Detail |
|---|---|
| No local plugins | Remote plugins from buf.build |
| Built-in lint & breaking | Enforces best practices |
| Deterministic deps | Module + lock file |
10. Automating Generation with Makefiles
Example: Makefile target
PROTOS := $(shell find proto -name '*.proto')
gen: $(PROTOS)
buf generate
.PHONY: gen lint
lint:
buf lint && buf breaking --against '.git#branch=main'
| CI Step | Command |
|---|---|
| Generate | make gen |
| Check drift | git diff --exit-code gen/ |
| Lint & breaking | make lint |