Search code examples
cmakeprotocol-buffersgrpcgrpc-c++

How to I use the cmake command protobuf_generate when installing protobuf through FetchContent?


I am writing a client/server with gRPC. To generate the client/server protobuf code, I need to run the cmake command protobuf_generate. If I install protobuf beforehand, I have access to the command protobuf_generate. However, if I try to install protobuf with FetchContent:

cmake_minimum_required(VERSION 3.16)
project(ProtoObjects)

include(FetchContent)
set(FETCHCONTENT_QUIET OFF)
FetchContent_Declare(
  gRPC
  GIT_REPOSITORY https://github.com/grpc/grpc
  GIT_TAG        v1.49.2
  )
FetchContent_Declare(
    Protobuf
    GIT_REPOSITORY https://github.com/protocolbuffers/protobuf
    GIT_TAG        v21.12 
    SOURCE_SUBDIR  cmake
)
FetchContent_MakeAvailable(gRPC Protobuf)

add_library(
    proto-objects
        PUBLIC
            grpc++
)

target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_GENERATED_DIR}>")

protobuf_generate(
    TARGET proto-objects
    IMPORT_DIRS ${PROTO_IMPORT_DIRS}
    PROTOC_OUT_DIR ${PROTO_GENERATED_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_GENERATED_DIR}"
)

I get the error:

Unknown CMake command "protobuf_generate".

How can I fix this error?


Solution

  • In Protobuf version 21.12 and before the function protobuf_generate is defined in the protobuf-config.cmake script which is created upon installation. Thus the function can be used only with already installed Protobuf, but not with the one included with FetchContent.

    In the master (after that pull request) the function protobuf_generate is defined in the script cmake/protobuf-generate.cmake, so that script can be included even in the build tree (after FetchContent):

    ...
    FetchContent_MakeAvailable(Protobuf)
    
    # Get source directory of the Protobuf
    FetchContent_GetProperties(Protobuf SOURCE_DIR Protobuf_SOURCE_DIR)
    # Include the script which defines 'protobuf_generate'
    include(${Protobuf_SOURCE_DIR}/cmake/protobuf-generate.cmake)
    
    ...
    protobuf_generate(...)