CMake 找不到 Protobuf `protobuf_generate_cpp`

car*_*rvo 5 cmake protocol-buffers protobuf-c

使用

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)
Run Code Online (Sandbox Code Playgroud)

我收到一条错误消息Unknown CMake command "protobuf_generate_cpp"。如果我检查 Protobuff 的安装文件夹,有一个<istall path>/cmake/protobuf-module.cmake包含函数定义的 CMake 文件。

CMake    version: 3.10.2
Protobuf version: 3.6.1
Run Code Online (Sandbox Code Playgroud)

这里有什么问题?

And*_*rew 10

看起来 cmake API 发生了一些变化。尝试将其更改为

protobuf_generate(
 LANGUAGE cpp
 TARGET <YOUR_TARGET_NAME> 
 PROTOS Foo.proto)
Run Code Online (Sandbox Code Playgroud)

这将直接将生成的文件添加到目标的源列表中。查看新选项的protobuf_generate功能protobuf-config.cmake

  • 这方面的文档在哪里?官方 CMake 文档只列出了 protobuf_generate_cpp 和 protobuf_generate_python,即使是最新版本。 (12认同)
  • 我知道已经晚了@scatter,但是protocolbuffers终于在9月份写了一些[文档](https://github.com/protocolbuffers/protobuf/blob/e1faf09604d26cc6803970815f91225b220175d4/docs/cmake_protobuf_generate.md) (3认同)

Bru*_*ams 8

现有的答案对我有帮助,但错过了很多对正在发生的事情的解释。

find_package可以工作在MODULE模式或CONFIG模式。在 MODULE 模式下,它进行搜索Find\<package\>.cmake(通常由 cmake 拥有)。在 CONFIG 模式下它会搜索\<package\>Config.cmake(由包提供)。

cmake 和 protocol buffers 都可以提供以下实现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)
Run Code Online (Sandbox Code Playgroud)

使用 PATHS 提示将 cmake 置于 CONFIG 模式,这样如果它可以找到 Config.cmake 模块,它将使用 protobuf 提供的实现。

在这种情况下,protobuf_generate_cpp() 来自 config.cmake,它需要:

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")
Run Code Online (Sandbox Code Playgroud)

因为正如 @HaxtraZ 提到的,配置模块包含:

if(protobuf_MODULE_COMPATIBLE)
   include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
endif()
Run Code Online (Sandbox Code Playgroud)

如果使用FindProtobuf MODULE,则不需要这样做,因此没有记录在案。

尽管这并不是它的错,但 cmake 可以警告可能发生的冲突。如果在这里提出这个问题:

https://gitlab.kitware.com/cmake/cmake/issues/21228
Run Code Online (Sandbox Code Playgroud)

我还向协议缓冲区项目报告了由于缺少文档而造成的混乱:

https://github.com/protocolbuffers/protobuf/issues/7912
Run Code Online (Sandbox Code Playgroud)

注意:某些 Linux 安装(至少 CentOS7 和 Debian9)上的默认设置通常是使用 configure/make 而不是 cmake 生成协议缓冲区,后者根本不安装 cmake 配置文件。因此 find_package(protobuf 3.5.0 REQUIRED) 可以工作,但 find_package(protobuf 3.5.0 REQUIRED PATH I/only/wanted/to/help) 将失败。


Hax*_*raZ 7

你需要protobuf_MODULE_COMPATIBLE

我使用的是CMake3.14。最后3行protobuf-config.cmake是:

if(protobuf_MODULE_COMPATIBLE)
  include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
endif()
Run Code Online (Sandbox Code Playgroud)

protobuf_generate_cpp()定义在protobuf-module.cmake.

因此,为了做到这一点protobuf_generate_cpp(),人们必须protobuf_MODULE_COMPATIBLE在他们的 CMakeLists.txt 中打开:

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")
Run Code Online (Sandbox Code Playgroud)

请记住清理之前生成的 cmake 缓存文件,然后再次调用 cmake。