Skip to content
Latchkey

protoc: Generate Code From .proto Files in CI

protoc compiles .proto files into generated code; -I sets the import root and --<lang>_out picks the target language and output directory.

protoc is the reference Protocol Buffers compiler. In CI the two things that break first are the import path (-I) and whether the language plugin is on PATH.

What it does

protoc parses .proto files, resolves their import statements against the directories given by -I/--proto_path, and writes generated code through a per-language output flag like --cpp_out, --python_out, or a plugin flag such as --go_out. Each .proto filename you pass must be reachable under one of the -I roots.

Common usage

Terminal
protoc -I proto --python_out=gen proto/api/v1/user.proto
# Go via the protoc-gen-go plugin (must be on PATH)
protoc -I proto --go_out=gen --go_opt=paths=source_relative \
  proto/api/v1/user.proto
# multiple files at once
protoc -I proto --go_out=gen proto/api/v1/*.proto

Flags and options

FlagWhat it does
-I <dir> / --proto_path=<dir>Import root; repeatable. Imports resolve relative to these
--<lang>_out=<dir>Output dir for a built-in language (cpp, java, python, etc.)
--go_out=<dir>Invoke the protoc-gen-go plugin and write Go to <dir>
--go_opt=paths=source_relativeLay out Go files mirroring the .proto tree
--plugin=protoc-gen-X=<path>Point at a plugin binary not found on PATH
--descriptor_set_out=<file>Emit a compiled FileDescriptorSet instead of code
--versionPrint the protoc version (libprotoc 3.x / 4.x / 5.x)

In CI

Pin the protoc version in the job; generated output differs between major releases and a floating apt-get install protobuf-compiler can silently change it. Commit generated code or regenerate and diff, but be consistent: a version bump that reformats output looks like a spurious failure otherwise.

Common errors in CI

"<file>: File not found." or "Import "x.proto" was not found or had errors." means the import root is wrong; the path after import must be reachable under a -I dir, not relative to the importing file. "Missing output directives." means you passed .proto files but no --*_out flag. "<file>: File does not reside within any path specified using --proto_path" means the file you named is outside every -I root; add the right -I.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →