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
FlagPurpose
--proto_path / -ISearch root for imports
--<lang>_outOutput dir for that language
--<lang>_optPlugin-specific options

2. Specifying Output Directory

PatternExample
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

FlagPurpose
-I=protoLocal protos root
-I=third_party/googleapisVendored google APIs
Multiple -ISearched 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
TipDetail
Single source of truthKeep .proto in dedicated repo or monorepo path
Publish artifactsPush generated SDKs to language registries

5. Using Generation Plugins

PluginOutput
protoc-gen-goGo messages
protoc-gen-go-grpcGo gRPC stubs
protoc-gen-grpc-gatewayREST gateway
protoc-gen-openapiv2OpenAPI spec
ts-protoTypeScript
protoc-gen-validateValidation methods

6. Generating gRPC Service Code

LanguageService Output
Go*_grpc.pb.go with UnimplementedXServer
Python*_pb2_grpc.py with add_XServicer_to_server
JavaXGrpc.java with ImplBase

7. Generating Message Code Only

ScenarioFlag
Just messagesOmit --<lang>-grpc_out
Just gRPC stubsUse both plugins, ship messages from upstream module

8. Setting Module Paths

OptionUse
--go_opt=module=example.com/apiStrip 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 protocDetail
No local pluginsRemote plugins from buf.build
Built-in lint & breakingEnforces best practices
Deterministic depsModule + 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 StepCommand
Generatemake gen
Check driftgit diff --exit-code gen/
Lint & breakingmake lint