在 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文件生成到build
的protocol
子文件夹中;但是 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
项目
在以下项目结构中:
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文件生成到build
的protocol
子文件夹中;但是 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
项目