c++ - CMake如何收集自动生成的源文件和头文件
问题描述
首先介绍一下上下文,我试图解耦一个包含 protobuf 定义以及使用 proto 的实体的 repo。我想创建一个仅包含 protobuf 定义和脚本的存储库,这些定义和脚本以不同的语言导出生成的类,以便由使用它们的其他项目导入。
在 c++ 中生成 protobuf 类实际上非常简单(几行 python 脚本),但之后就变得棘手了。您最终会得到一组杂乱无章的源文件。我想使用 CMake 收集所有文件并生成库。文件结构应如下所示:
/root
/proto-package-1
foo.pb.h
foo.pb.cc
/proto-package-2
/proto-package-3
bar.pb.h
bar.pb.cc
bazz.pb.h
bazz.pb.cc
我在 CMake 中有点菜鸟,但我读过在 CMakeLists.txt 文件中明确列出所有源文件是一种很好的做法。但我想让这个 c++ 库的生成完全自动化。这是违反此规则的充分理由吗?什么 CMake 命令可以帮助我?
cmake_minimum_required (VERSION 3.5)
project ("CMakeProject1")
set(TARGET_NAME CMakeProject1)
# Include sub-projects.
include_directories(${CMAKE_SOURCE_DIR})
add_library(${TARGET_NAME} STATIC
${CMAKE_SOURCE_DIR}/root/proto-package-1/foo.pb.h
${CMAKE_SOURCE_DIR}/root/proto-package-1/foo.pb.cc
//This is not going to cut it. Cannot add a proto and auto-generate.
)
解决方案
您还可以在 cmake 中生成它们并创建生成文件的列表
# Get list of .proto files
file(GLOB_RECURSE proto_files RELATIVE ${PROJECT_SOURCE_DIR} "*.proto")
## Get Protobuf include dirs
get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
foreach(dir IN LISTS protobuf_dirs)
if ("${dir}" MATCHES "BUILD_INTERFACE")
message(STATUS "Adding proto path: ${dir}")
list(APPEND PROTO_DIRS "--proto_path=${dir}")
endif()
endforeach()
# Generate Protobuf cpp sources
set(PROTO_HDRS)
set(PROTO_SRCS)
foreach(PROTO_FILE IN LISTS proto_files)
#message(STATUS "protoc proto(cc): ${PROTO_FILE}")
get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY)
get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h)
set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc)
#message(STATUS "protoc hdr: ${PROTO_HDR}")
#message(STATUS "protoc src: ${PROTO_SRC}")
add_custom_command(
OUTPUT ${PROTO_SRC} ${PROTO_HDR}
COMMAND protobuf::protoc
"--proto_path=${PROJECT_SOURCE_DIR}"
${PROTO_DIRS}
"--cpp_out=${PROJECT_BINARY_DIR}"
${PROTO_FILE}
DEPENDS ${PROTO_FILE} protobuf::protoc
COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}"
VERBATIM)
list(APPEND PROTO_HDRS ${PROTO_HDR})
list(APPEND PROTO_SRCS ${PROTO_SRC})
endforeach()
# [optional] Create a library of all generated C++ files
add_library(${PROJECT_NAME}_proto ${PROTO_SRCS} ${PROTO_HDRS})
set_target_properties(${PROJECT_NAME}_proto PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD 11)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD_REQUIRED ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_EXTENSIONS OFF)
target_include_directories(${PROJECT_NAME}_proto PRIVATE
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
$<TARGET_PROPERTY:protobuf::libprotobuf,INTERFACE_INCLUDE_DIRECTORIES>
)
target_link_libraries(${PROJECT_NAME}_proto PRIVATE protobuf::libprotobuf)
推荐阅读
- null - event.target.getAttribute("name") 有时为空?
- android - 收到后台通知时不显示直接回复(推送通知)
- laravel - Laravel 密码验证规则有错误
- python - 发送图像时出现 Python 套接字错误。无法解码字节/意外 EOF
- python - Visual Studio Code,带有 Jupyter 小部件的交互式 matplotlib 图 - Python?
- javascript - 如何在没有钩子的情况下更新按钮点击查询
- javascript - 加载时如何跳过渲染 React 功能组件的元素?
- python - 如何比较和合并 2 个具有不同实例数的 dfs 并从第一个中的第二个 df 中获取一列?
- python - randrange() 的空范围 (1,1,0)
- java - Mule JaxB 解组无法解析 ArrayList