我想用protobuf
从某些cmake/make
定义中构建一个c ++静态库。
我创建了一个自定义COMMAND
,将protobuf
编译为c++
,并将其设置为对我的静态库的PRE_BUILD
依赖项。
project(mylib)
set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto_definitions")
file(GLOB PROTO_FILES "${PROTO_PATH}/*.proto")
foreach(PROTO_FILE in ${PROTO_FILES})
string(REGEX REPLACE "[.]proto$" ".pb.cc" OUTPUT_SOURCE ${PROTO_FILE})
list(APPEND OUTPUT_SOURCES ${OUTPUT_SOURCE})
endforeach()
add_custom_command(TARGET ${PROJECT_NAME}
PRE_BUILD
COMMAND protoc --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/compiled_proto ${PROTO_FILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "some comment")
add_library(${PROJECT_NAME} STATIC ${OUTPUT_SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
运行cmake时出现以下错误:
CMake错误:无法确定目标“ mylib”的链接语言
不管出现此错误,都会生成makefile,但是当我制作mylib时,它不会触发任何原型编译
答案 0 :(得分:2)
CMake更原生的方法是添加带有OUTPUT
签名的自定义命令以生成.cc
文件,然后将它们用作库的源。这样,他们CMake将知道它们是什么以及如何生产它们:
project(mylib)
set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto_definitions")
file(GLOB PROTO_FILES "${PROTO_PATH}/*.proto")
foreach(PROTO_FILE in ${PROTO_FILES})
string(REGEX REPLACE "[.]proto$" ".pb.cc" OUTPUT_SOURCE ${PROTO_FILE})
list(APPEND OUTPUT_SOURCES ${OUTPUT_SOURCE})
endforeach()
add_custom_command(OUTPUT ${OUTPUT_SOURCES}
COMMAND protoc --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/compiled_proto ${PROTO_FILES}
DEPENDS ${PROTO_FILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "some comment")
add_library(${PROJECT_NAME} STATIC ${OUTPUT_SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
这样,将有一个命令读取所有.proto
文件并生成所有.cc
文件-这意味着,如果.proto
文件中的任何一个发生更改,所有.cc
个文件将重新生成。我不熟悉Protobuffers,所以我不知道这是否理智。如果它们是独立的,则最好为每个输出文件引入一个add_custom_command
。
另外,给定要传递给protocc
的参数,您可能必须修改OUTPUT_SOURCES
中的路径以正确指向生成的文件。
还要注意,CMake带有一个FindProtobuf模块,该模块定义了一个protobuf_generate_cpp()
命令,因此您可能想使用它而不是手工编码Protobuf支持。
答案 1 :(得分:0)
评论上面的答案:cmake foreach中没有in
,花了我一些时间来解决。
在研究了他的回答后(非常感谢!),我总结了一个对我有用的方法,它有以下特点:
我的项目结构是:
这是我的 CMakeListx.txt:
set(PROTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../proto")
set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/hwpb")
file(GLOB PROTO_FILES "${PROTO_DIR}/*.proto")
foreach(PROTO_FILE ${PROTO_FILES})
get_filename_component (FILENAME ${PROTO_FILE} NAME_WLE)
set(PROTO_SRC "${OUTPUT_DIR}/${FILENAME}.pb.cc")
set(PROTO_HDR "${OUTPUT_DIR}/${FILENAME}.pb.h")
set(GRPC_SRC "${OUTPUT_DIR}/${FILENAME}.grpc.pb.cc")
set(GRPC_HDR "${OUTPUT_DIR}/${FILENAME}.grpc.pb.h")
add_custom_command(
OUTPUT "${PROTO_SRC}" "${PROTO_HDR}" "${GRPC_SRC}" "${GRPC_HDR}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --plugin=protoc-gen-grpc=${_GRPC_CPP_PLUGIN_EXECUTABLE}
--cpp_out="${OUTPUT_DIR}" --grpc_out="${OUTPUT_DIR}"
-I"${PROTO_DIR}" "${PROTO_FILE}"
DEPENDS ${PROTO_FILE}
)
list(APPEND OUTPUT_SOURCES ${PROTO_SRC} ${GRPC_HDR})
endforeach()
add_library(hwpb ${OUTPUT_SOURCES})
target_link_libraries(hwpb ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF})
target_include_directories(hwpb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})