CMake不与Google Protobuf合作

时间:2016-12-08 15:36:38

标签: c++ cmake protocol-buffers

无法使用CMake链接protobuf库。我的CMakeLists是

cmake_minimum_required(VERSION 3.6)
project(addressbook)

set(CMAKE_CXX_STANDARD 11)
set(PROJECT_NAME addressbook)

ADD_SUBDIRECTORY(proto)

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
ADD_EXECUTABLE(main main.cpp)
TARGET_LINK_LIBRARIES(main proto ${PROTOBUF_LIBRARY})

并在proto子目录中有另一个CMakeLists.txt(这样就可以在github repo https://github.com/shaochuan/cmake-protobuf-example中完成)

INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER message.proto)
ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC})

但我的IDE仍会输出像

这样的行
  

CMakeFiles / main.dir / main.cpp.o:在函数main': /home/camille/ClionProjects/protobuf/main.cpp:42: undefined reference to中google :: protobuf :: internal :: VerifyVersion(int,int,char const *)'   /home/camille/ClionProjects/protobuf/main.cpp:49:未定义的引用   到tutorial::AddressBook::AddressBook()' /home/camille/ClionProjects/protobuf/main.cpp:54: undefined reference to google :: protobuf :: Message :: ParseFromIstream(std :: istream *)'

我的错误在哪里?我如何使它工作?

4 个答案:

答案 0 :(得分:4)

您的程序无法链接,因为${PROTOBUF_LIBRARY}在您的顶级CMakeLists.txt范围内为空。发生这种情况是因为调用add_subdirectory会创建子范围,而Protobuf_XXX设置的find_package(Protobuf REQUIRED)变量仅在该子范围内。

解决此问题的一种好方法是将以下内容添加到proto/CMakeLists.txt

target_link_libraries(proto INTERFACE ${Protobuf_LIBRARIES})

这会指示链接到proto的目标也链接到${Protobuf_LIBRARIES}。现在,您可以在顶级target_link_libraries中简化CMakeLists.txt

target_link_libraries(addressbook proto)

另外,你也可以使用例如。

target_link_libraries(${PROJECT_NAME} INTERFACE ... )

${PROJECT_NAME}解析为您在project(...)文件中的CMakeLists.txt语句中设置的任何内容。

最后,请注意,此链接指向Protobuf_LIBRARIES而不是PROTOBUF_LIBRARYProtobuf_LIBRARIES包括Protocol Buffers库和依赖的Pthreads库。

答案 1 :(得分:2)

您需要传递给target_link_libraries的变量是Protobuf_LIBRARIES。请参阅documentation

答案 2 :(得分:0)

注意变量名称案例:使用CMake 3.6及更高版本,FindProtobuf模块输入和输出变量全部从PROTOBUF_重命名为Protobuf_(参见release notes) ,因此使用Protobuf_可以使用CMake 3.6,但是使用早期版本的未定义引用会失败。

为了安全起见,要么使用旧式

target_link_libraries(${PROJECT_NAME} INTERFACE ${PROTOBUF_LIBRARIES}))

或强迫每个人至少使用CMake 3.6

cmake_minimum_required(VERSION 3.6)

此外,Kitware cmake问题跟踪器中有一个resolved bug report,其中包含有关如何诊断此类问题的更多信息。

答案 3 :(得分:-1)

cmakeList.txt:

cmake_minimum_required(版本3.12) 项目(protobuf)

SET(CMAKE_CXX_FLAGS“ -g -Wall -Werror -std = c ++ 11”)

设置(CMAKE_CXX_STANDARD 11)

INCLUDE(FindProtobuf)

FIND_PACKAGE(需要Protobuf)

INCLUDE_DIRECTORIES($ {PROTOBUF_INCLUDE_DIR})

PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER地址簿.proto) ADD_LIBRARY(proto2 $ {PROTO_HEADER} $ {PROTO_SRC}) TARGET_LINK_LIBRARIES(proto2)

INCLUDE_DIRECTORIES($ {CMAKE_CURRENT_BINARY_DIR})

add_executable(protobuf main.cpp)

TARGET_LINK_LIBRARIES(protobuf proto2 $ {PROTOBUF_LIBRARY})