【问题标题】:CMake can't find Protobuf `protobuf_generate_cpp`CMake 找不到 Protobuf `protobuf_generate_cpp`
【发布时间】:2019-03-03 03:45:27
【问题描述】:

使用

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

这里有什么问题?

【问题讨论】:

  • find_package() 调用期间读取的是ProtobufConfig.cmake 文件。 CMake 将包含此文件的目录存储在 Protobuf_DIR 缓存变量中。您可以在构建目录中的CMakeCache.txt 文件中找到此变量的值。检查: 1. 找到正确的文件ProtobufConfig.cmake(根据Protobuf_DIR 变量)。 2.给定文件包含protobuf_generate_cpp函数的定义。

标签: cmake protocol-buffers protobuf-c


【解决方案1】:

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

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

这会将生成的文件直接添加到目标的源列表中。 查看protobuf-config.cmake 中的protobuf_generate 函数以了解新选项。

【讨论】:

  • 这方面的文档在哪里?官方 CMake 文档仅列出了 protobuf_generate_cpp 和 protobuf_generate_python,即使是最新版本。
  • 我也很想看看这方面的文档。这是目前互联网上唯一提到这一点的地方。
  • @scatter 查看我的回答 cmake 的 FindProtobuf 不提供此 API。它来自没有很好记录的协议缓冲区。
【解决方案2】:

你需要protobuf_MODULE_COMPATIBLE

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

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

protobuf_generate_cpp()protobuf-module.cmake 中定义。

所以,为了protobuf_generate_cpp(),人们必须在他们的 CMakeLists.txt 中打开protobuf_MODULE_COMPATIBLE

set(protobuf_MODULE_COMPATIBLE ON CACHE BOOL "")

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

【讨论】:

    【解决方案3】:

    现有的answers 帮助了我,但错过了很多关于发生了什么的解释。

    find_package 可以工作在 MODULE 模式或 CONFIG 模式。 在 MODULE 模式下,它会搜索 Find\&lt;package\&gt;.cmake(通常由 cmake 拥有)。 在 CONFIG 模式下,它会搜索 \&lt;package\&gt;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 模式,这样如果它可以找到 Config.cmake 模块,它将使用 protobuf 提供的实现。

    在这种情况下,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 MODULE,则不需要,因此此处未记录。

    虽然这不是它的错,但 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/wanted/to/help) 会失败。

    【讨论】:

    • 不幸的是,使用CONFIG 模式并设置此布尔变量不起作用(至少在 Windows 上)
    猜你喜欢
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 2021-02-02
    相关资源
    最近更新 更多