CMake не может найти Protobuf `protobuf_generate_cpp`

С помощью

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)

Я получаю сообщение об ошибке Unknown CMake command "protobuf_generate_cpp", Если я проверяю папку установки Protobuff, есть файл CMake <istall path>/cmake/protobuf-module.cmake который содержит определение функции.

CMake    version: 3.10.2
Protobuf version: 3.6.1

В чем здесь проблема?

0 ответов

Похоже, API-интерфейс cmake немного изменился. Попробуйте изменить это на

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

Это напрямую добавит сгенерированные файлы в исходный список цели. Посмотрите на protobuf_generate функция в protobuf-config.cmake для новых опций.

Существующие ответы помогли мне, но я упустил много объяснений того, что происходит.

find_package может работать в режиме MODULE или CONFIG. В режиме МОДУЛЬ ищет Find\<package\>.cmake(обычно принадлежит cmake). В режиме CONFIG он ищет \<package\>Config.cmake (предоставляется посылкой).

Буферы cmake и протокола могут обеспечить реализацию для 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)

Использование подсказки PATHS переводит cmake в режим CONFIG, так что он будет использовать предоставленную protobuf реализацию, если сможет найти модуль Config.cmake.

В этом случае protobuf_generate_cpp() поступает из config.cmake, который требует:

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")

Поскольку, как упоминает @HaxtraZ, модуль конфигурации содержит:

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

Это не требуется при использовании МОДУЛЯ FindProtobuf и поэтому не документировано там.

Хотя это не совсем его вина, cmake мог предупредить о возможном конфликте. Если подняли это здесь:

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

Я также сообщил о путанице, вызванной отсутствием документации по проекту буферов протокола здесь:

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

Примечание. По умолчанию в некоторых установках Linux (по крайней мере, CentOS7 и Debian9) обычно буферы протокола создаются с помощью configure/make, а не cmake, который вообще не устанавливает файлы конфигурации cmake. Итак, find_package(protobuf 3.5.0 REQUIRED) будет работать, но find_package(protobuf 3.5.0 REQUIRED PATH I/only/ Should/to/help) завершится ошибкой.

Тебе нужно protobuf_MODULE_COMPATIBLE.

Я использую CMake3.14. Последние 3 строкиprotobuf-config.cmake является:

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

а также protobuf_generate_cpp() определяется в protobuf-module.cmake.

Итак, чтобы protobuf_generate_cpp(), люди должны обратиться protobuf_MODULE_COMPATIBLE в их CMakeLists.txt:

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")

Не забудьте очистить ранее созданные файлы кеша cmake, а затем снова вызвать cmake.

Другие вопросы по тегам