在 CMAKE 中为库目标生成 protobuf 文件

Generate protobuf files for a library target in CMAKE

在以下项目结构中:

root/
├─ CMakeLists.txt
├─ protocol/
│  ├─ msg.proto
│  ├─ CMakeLists.txt
├─ app/
│  ├─ main.cpp
│  ├─ CMakeLists.txt

我可以生成 protobuf 文件。但是,一旦将 app 目标添加到项目中,配置步骤就会失败,因为不再生成 protobuf 文件。

root CMakeLists.txt:

cmake_minimum_required(VERSION 3.18.4) 
project(
  root
  VERSION 0.1
  LANGUAGES CXX
)

add_subdirectory(protocol)
add_subdirectory(app) 

协议CMakeLists.txt:

add_library(protocol)
target_include_directories(protocol
  PUBLIC
  .
  ${CMAKE_CURRENT_BINARY_DIR}
  ${Protobuf_INCLUDE_DIRS}
)
find_package(Protobuf REQUIRED)
set(PROTO_SOURCES msg.proto)
protobuf_generate_cpp(LIB_SOURCES LIB_HEADERS ${PROTO_SOURCES} )
target_link_libraries(protocol ${Protobuf_LIBRARIES})
target_sources(protocol
  PUBLIC
  ${LIB_HEADERS}
  PRIVATE
  ${LIB_SOURCES}
)

应用CMakeLists.txt:

add_library(app)
target_link_libraries(app PUBLIC protocol)
target_include_directories(app PUBLIC .)
target_sources(app
  PRIVATE
  main.cpp
)

我的理解是,我必须以某种方式告诉 CMAKE 依赖关系,但据我所知 target_link_libraries 应该准确地告诉它。

我可以采取的另一个步骤是告诉 app 目标 protocol 库中的 headers 是在构建时生成的,因此它们可以在依赖目标编译之前生成.怎么做到的?

许多其他问题都引用了类似的问题,但我发现 none 考虑到了库依赖性。


更新:

${LIB_HEADERS}PUBLIC 移动到 PRIVATE 后:

add_library(protocol)
target_include_directories(protocol
  PUBLIC
  .
  ${CMAKE_CURRENT_BINARY_DIR}
  ${Protobuf_INCLUDE_DIRS}
)
find_package(Protobuf REQUIRED)
set(PROTO_SOURCES msg.proto)
protobuf_generate_cpp(LIB_SOURCES LIB_HEADERS ${PROTO_SOURCES} )
target_link_libraries(protocol ${Protobuf_LIBRARIES})
target_sources(protocol
  PRIVATE
  ${LIB_HEADERS}
  ${LIB_SOURCES}
)

配置步骤成功,msg.pb.h文件生成到buildprotocol子文件夹中;但是 make 失败并出现以下错误:

main.cpp:29:10: fatal error: protocol/msg.pb.h: No such file or directory
   29 | #include "protocol/msg.pb.h"
      |   

那么在此设置中如何从目标 protocol 提供 headers?

基于@Tsyvarev 的帮助: 将 ${LIB_HEADERS}PUBLIC 移动到 PRIVATE 后,现在生成了 protobuf 文件。

使它们可以通过包含的库访问

#include "protocol/msg.pb.h"

${CMAKE_BINARY_DIR}需要在target_include_directories中改成${CMAKE_CURRENT_BINARY_DIR}

如果我的代码直接取消了 protobuf headers:

#include "msg.pb.h"

${CMAKE_CURRENT_BINARY_DIR} 需要在那里。


因为:

  • ${CMAKE_CURRENT_BINARY_DIR}代表子模块二进制目录(protocol项目
  • ${CMAKE_CURRENT_BINARY_DIR}代表项目二进制目录(protocol项目