Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake can't find Protobuf `protobuf_generate_cpp`

Using

find_package(Protobuf REQUIRED
    PATHS ${PROTOBUF_SEARCH_PATH}
)

if (NOT ${Protobuf_FOUND})
    message( FATAL_ERROR "Could not find Protobuf!" )
endif()    

protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS Foo.proto)

I am getting an error message Unknown CMake command "protobuf_generate_cpp". If I check install folder of Protobuff, there is a CMake file <istall path>/cmake/protobuf-module.cmake which contains the function definition.

CMake    version: 3.10.2
Protobuf version: 3.6.1

What is the problem here?

like image 450
carobnodrvo Avatar asked Sep 27 '18 09:09

carobnodrvo


3 Answers

Looks like the cmake API has changed a bit. Try changing it to

protobuf_generate(
 LANGUAGE cpp
 TARGET <YOUR_TARGET_NAME> 
 PROTOS Foo.proto)

This will directly add the generated files to the target's source list. Have a look in at the protobuf_generate function in protobuf-config.cmake for the new options.

like image 55
Andrew Avatar answered Nov 06 '22 18:11

Andrew


The existing answers helped me but miss a lot of explanation of what is going on.

find_package can work in MODULE mode or CONFIG mode. In MODULE mode it searches for Find\<package\>.cmake (typically owned by cmake). In CONFIG mode it searches for \<package\>Config.cmake (provided by the package).

Both cmake and protocol buffers can provide an implementation for protobuf_generate_cpp():

>grep -ri 'function(PROTOBUF_GENERATE_CPP' /opt/cmake-3.18.1/ 
/opt/cmake-3.18.1/share/cmake-3.18/Modules/FindProtobuf.cmake:function(PROTOBUF_GENERATE_CPP SRCS HDRS)
>grep -ri 'function(PROTOBUF_GENERATE_CPP' /opt/protobuf-3.5.0/
/opt/protobuf-3.5.0/lib64/cmake/protobuf/protobuf-module.cmake:function(PROTOBUF_GENERATE_CPP SRCS HDRS)

Using the PATHS hint puts cmake into CONFIG mode so that it will use the protobuf provided implementation if it can find a Config.cmake module.

In this case protobuf_generate_cpp() comes from config.cmake which requires:

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")

Because as @HaxtraZ mentions the config module contains:

if(protobuf_MODULE_COMPATIBLE)
   include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
endif()

This is not required if using the FindProtobuf MODULE and is thus not documented there.

Though it is not really its fault cmake could warn about the possible conflict. If have raised this here:

https://gitlab.kitware.com/cmake/cmake/-/issues/21228

I have also reported the confusion caused by the missing documentation to the protocol buffers project here:

https://github.com/protocolbuffers/protobuf/issues/7912

Note: The default on some Linux installations (at least CentOS7 and Debian9) is typically to have protocol buffers produced using configure/make rather than cmake which does not install the cmake config files at all. So find_package(protobuf 3.5.0 REQUIRED) will work but find_package(protobuf 3.5.0 REQUIRED PATH I/only/wanted/to/help) will fail.

like image 5
Bruce Adams Avatar answered Nov 06 '22 17:11

Bruce Adams


You need protobuf_MODULE_COMPATIBLE.

I'm using CMake3.14. The last 3 lines of protobuf-config.cmake is:

if(protobuf_MODULE_COMPATIBLE)
  include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
endif()

and protobuf_generate_cpp() is defined in protobuf-module.cmake.

So, in order to protobuf_generate_cpp(), people have to turn protobuf_MODULE_COMPATIBLE on in their CMakeLists.txt:

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")

Remember clean your previously generate cmake cache files then call cmake again.

like image 4
ChrisZZ Avatar answered Nov 06 '22 18:11

ChrisZZ