docs/cmake_protobuf_generate.md
protobuf_generateThis document explains how to use the function protobuf_generate which is
provided by protobuf's CMake module.
In the same directory that called find_package(protobuf CONFIG) and any of its
subdirectories, the CMake function protobuf_generate is made available by
protobuf-generate.cmake. It can be used to
automatically generate source files from .proto schema files at build time.
Let us see how protobuf_generate can be used to generate and compile the
source files of a proto schema whenever an object target called proto-objects
is built.
Given the following directory structure:
proto/helloworld/helloworld.protoCMakeLists.txtwhere helloworld.proto is a protobuf schema file and CMakeLists.txt
contains:
find_package(protobuf CONFIG REQUIRED)
add_library(proto-objects OBJECT "${CMAKE_CURRENT_LIST_DIR}/proto/helloworld/helloworld.proto")
target_link_libraries(proto-objects PUBLIC protobuf::libprotobuf)
set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
protobuf_generate(
TARGET proto-objects
IMPORT_DIRS "${CMAKE_CURRENT_LIST_DIR}/proto"
PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
Building the target proto-objects will generate the files:
${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.h${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.ccand (depending on the build system) output:
[build] [1/2] Running cpp protocol buffer compiler on /proto/helloworld/helloworld.proto
[build] [2/2] Building CXX object /build/generated/helloworld/helloworld.pb.cc.o
protobuf_generate can also be customized to invoke plugins like gRPC's
grpc_cpp_plugin. Given the same directory structure as in the
basic example and let CMakeLists.txt contain:
find_package(gRPC CONFIG REQUIRED)
add_library(proto-objects OBJECT "${CMAKE_CURRENT_LIST_DIR}/proto/helloworld/helloworld.proto")
target_link_libraries(proto-objects PUBLIC protobuf::libprotobuf gRPC::grpc++)
set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
set(PROTO_IMPORT_DIRS "${CMAKE_CURRENT_LIST_DIR}/proto")
target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
protobuf_generate(
TARGET proto-objects
IMPORT_DIRS ${PROTO_IMPORT_DIRS}
PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
protobuf_generate(
TARGET proto-objects
LANGUAGE grpc
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
PLUGIN "protoc-gen-grpc=\$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
IMPORT_DIRS ${PROTO_IMPORT_DIRS}
PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
Then building proto-objects will generate and compile:
${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.h${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.cc${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.grpc.pb.h${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.grpc.pb.ccAnd protoc will automatically be re-run whenever the schema files change and
proto-objects is built.
Since protobuf's generated source files are unsuited for jumbo/unity builds it is recommended to exclude them from such builds which can be achieved by adjusting their properties:
protobuf_generate(
OUT_VAR PROTO_GENERATED_FILES
...)
set_source_files_properties(${PROTO_GENERATED_FILES} PROPERTIES SKIP_UNITY_BUILD_INCLUSION on)
For each source file ending in proto of the argument provided to TARGET or
each file provided through PROTOS, protobuf_generate will set up a
add_custom_command
which depends on protobuf::protoc and the proto files. It declares the
generated source files as OUTPUT which means that any target that depends on
them will automatically cause the custom command to execute when it is brought
up to date. The command itself is made up of the arguments for protoc, like
the output directory, the schema files, the language to generate for, the
plugins to use, etc.
Arguments accepted by protobuf_generate.
Flag arguments:
APPEND_PATH — A flag that causes the base path of all proto schema files
to be added to IMPORT_DIRS.Single-value arguments:
LANGUAGE — A single value: cpp or python. Determines what kind of source
files are being generated.OUT_VAR — Name of a CMake variable that will be filled with the paths to
the generated source files.EXPORT_MACRO — Name of a macro that is applied to all generated Protobuf
message classes and extern variables. It can, for example, be used to
declare DLL exports.PROTOC_EXE — Command name, path, or CMake executable used to run protoc
commands. Defaults to protobuf::protoc.PROTOC_OUT_DIR — Output directory of generated source files. Defaults to
CMAKE_CURRENT_BINARY_DIR.PLUGIN — An optional plugin executable. This could, for example, be the
path to grpc_cpp_plugin.PLUGIN_OPTIONS — Additional options provided to the plugin, such as
generate_mock_code=true for the gRPC cpp plugin.DEPENDENCIES — Arguments forwarded to the DEPENDS of the underlying
add_custom_command invocation.TARGET — CMake target that will have the generated files added as sources.Multi-value arguments:
PROTOS — List of proto schema files. If omitted, then every source file
ending in proto of TARGET will be used.IMPORT_DIRS — A common parent directory for the schema files. For example,
if the schema file is proto/helloworld/helloworld.proto and the import
directory proto/ then the generated files are
${PROTOC_OUT_DIR}/helloworld/helloworld.pb.h and
${PROTOC_OUT_DIR}/helloworld/helloworld.pb.cc.GENERATE_EXTENSIONS — If LANGUAGE is omitted then this must be set to the
extensions that protoc generates.PROTOC_OPTIONS — Additional arguments that are forwarded to protoc.