Skip to main content
protoc is the Protocol Buffers compiler. It reads .proto files and generates source code in your target language, handling imports, option resolution, and plugin dispatch.

Installation

See the installation guide for platform-specific instructions. In brief:
  • Pre-built binary: Download protoc-$VERSION-$PLATFORM.zip from the GitHub releases page. Each zip contains the protoc binary and the standard .proto files distributed with protobuf.
  • Build from source: Follow the C++ build instructions to compile protoc from source using Bazel.
  • Package managers: On Windows, vcpkg install protobuf installs protoc alongside the runtime.
The protoc binary version and the generated code version must match for C++. See the cross-version runtime guarantee for details.

Basic usage

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR path/to/file.proto
You can compile multiple .proto files in a single invocation:
protoc --proto_path=protos --cpp_out=gen \
  protos/foo/foo.proto \
  protos/bar/bar.proto

Output flags

Each --LANG_out flag instructs protoc to generate code for that language. Multiple output flags can be combined in a single invocation.
protoc --proto_path=protos --cpp_out=gen protos/hello.proto
# Generates: gen/hello.pb.h and gen/hello.pb.cc

Passing options to an output flag

Some language generators accept options using the --LANG_out=OPT=VALUE:DST_DIR syntax:
# Enable gRPC service code for C++
protoc --proto_path=protos \
  --cpp_out=gen/cpp \
  --grpc_out=gen/cpp \
  --plugin=protoc-gen-grpc=$(which grpc_cpp_plugin) \
  protos/service.proto

Import paths

The --proto_path flag (short form: -I) specifies directories that protoc will search when resolving import statements. You can specify multiple import paths:
protoc \
  --proto_path=protos \
  --proto_path=/usr/local/include \
  --proto_path=$(GOPATH)/src \
  --cpp_out=gen \
  protos/myapp/service.proto
The well-known types (e.g., google/protobuf/timestamp.proto) are bundled with the protoc release. If you installed protoc from a zip package, add the include/ directory inside the zip to your --proto_path:
protoc \
  --proto_path=protos \
  --proto_path=/usr/local/include \
  --cpp_out=gen \
  protos/myapp/service.proto

Plugin invocation

protoc has a plugin system that allows third-party code generators to be invoked as if they were built-in. Any --xxx_out flag that does not correspond to a built-in language triggers plugin lookup.

Plugin discovery

By default, protoc searches $PATH for an executable named protoc-gen-xxx, where xxx matches the flag name:
# protoc will look for `protoc-gen-go` on $PATH
protoc --proto_path=protos --go_out=gen protos/hello.proto

Explicit plugin path

Use --plugin to provide an explicit path instead of relying on $PATH:
protoc \
  --proto_path=protos \
  --plugin=protoc-gen-go=/usr/local/bin/protoc-gen-go \
  --go_out=gen \
  protos/hello.proto
See Plugins for details on how plugins work and how to write your own.

Descriptor set output

protoc can serialize the parsed .proto files into a binary FileDescriptorSet without generating any language-specific code. This is useful for runtime reflection, gRPC service discovery, and tooling.
protoc \
  --proto_path=protos \
  --descriptor_set_out=myapp.pb \
  protos/myapp/service.proto
To include all imported files in the descriptor set (not just the files listed on the command line), add --include_imports:
protoc \
  --proto_path=protos \
  --descriptor_set_out=myapp.pb \
  --include_imports \
  protos/myapp/service.proto
To include source info (line numbers and comments) in the descriptor set:
protoc \
  --proto_path=protos \
  --descriptor_set_out=myapp.pb \
  --include_imports \
  --include_source_info \
  protos/myapp/service.proto

All flags reference

FlagDescription
--proto_path=PATH / -I PATHAdd a directory to the import search path. Specify multiple times for multiple paths.
--cpp_out=DST_DIRGenerate C++ header and source files.
--java_out=DST_DIRGenerate Java source files.
--python_out=DST_DIRGenerate Python source files.
--csharp_out=DST_DIRGenerate C# source files.
--ruby_out=DST_DIRGenerate Ruby source files.
--php_out=DST_DIRGenerate PHP source files.
--objc_out=DST_DIRGenerate Objective-C source files.
--rust_out=DST_DIRGenerate Rust source files.
--plugin=EXESpecify a plugin executable, or protoc-gen-NAME=PATH to name it explicitly.
--descriptor_set_out=FILEWrite a FileDescriptorSet (containing all input files) to the given file.
--include_importsInclude all imported files in the --descriptor_set_out output.
--include_source_infoInclude source info (line numbers, comments) in the --descriptor_set_out output.
--encode=MESSAGE_TYPERead a text-format message from stdin and write it in binary to stdout.
--decode=MESSAGE_TYPERead a binary message from stdin and write it in text format to stdout.
--versionPrint the protoc version and exit.
--help / -hPrint usage information.

Build docs developers (and LLMs) love