CMake不适用于Google Protobuf [英] CMake doesn't work with Google Protobuf
问题描述
无法使用CMake链接protobuf库。我的CMakeLists
cmake_minimum_required(版本3.6)
项目(地址簿)
set( CMAKE_CXX_STANDARD 11)
设置(PROJECT_NAME地址簿)
ADD_SUBDIRECTORY(原型)
INCLUDE_DIRECTORIES($ {CMAKE_CURRENT_BINARY_DIR})
ADD_EXECUTABLE(main main.cpp)
TARGET_LINK_LIBRARIES(主协议$ {PROTOBUF_LIBRARY})
,在proto子目录中还有另一个CMakeLists .txt(以这种方式在github repo https://github.com/shaochuan/cmake中完成-protobuf-example )
INCLUDE(FindProtobuf)
在该
FIND_PACKAGE(需要Protobuf)
INCLUDE_DIRECTORIES($ {PROTOBUF_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER message.proto)
ADD_LIBRARY(proto $ {PROTO_HEADER} $ {PROTO_SRC})
$ p $ c> $ p>
但是我的IDE仍然输出很多行,例如
CMakeFiles / main.dir / main.cpp.o:在函数
main'中:
google :: protobuf :: internal :: VerifyVersion(int,int,char const *)'
/home/camille/ClionProjects/protobuf/main.cpp:42:未定义的引用
到
/home/camille/ClionProjects/protobuf/main.cpp :49:未定义引用
到tutorial :: AddressBook :: AddressBook()'
google :: protobuf :: Message :: ParseFromIstream(std :: istream *)'
/home/camille/ClionProjects/protobuf/main.cpp:54:未定义引用
到
我的错误在哪里?我如何使它起作用?
解决方案您的程序由于
$ {PROTOBUF_LIBRARY}而无法链接
在顶层CMakeLists.txt
的范围内为空。发生这种情况是因为调用add_subdirectory
创建了一个子作用域,并且Protobuf_XXX
变量由find_package(需要Protobuf)
仅在该子范围内。
一种解决此问题的好方法是在
中添加以下内容proto / CMakeLists.txt
:target_link_libraries(proto INTERFACE $ {Protobuf_LIBRARIES})
这指示链接到
proto
的目标也链接到$ {Protobuf_LIBRARIES}
。现在,您可以在顶级CMakeLists.txt
中简化target_link_libraries
:target_link_libraries(地址簿原型)
旁注,您也可以使用例如
target_link_libraries($ {PROJECT_NAME} INTERFACE ...)
$ {PROJECT_NAME}
解析为您在<$ c中设置的任何内容$ c> project(...)CMakeLists.txt
文件中的语句。
最后,请注意,它链接到
Protobuf_LIBRARIES
而不是PROTOBUF_LIBRARY
。Protobuf_LIBRARIES
包括协议缓冲区库和从属Pthreads库。Unable to link protobuf library using CMake. My CMakeLists is
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})
and in proto subdirectory there is another CMakeLists.txt (that way it is done in 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})
But my IDE still outputs buch of lines like
CMakeFiles/main.dir/main.cpp.o: In function
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: undefined reference totutorial::AddressBook::AddressBook()' /home/camille/ClionProjects/protobuf/main.cpp:54: undefined reference to
google::protobuf::Message::ParseFromIstream(std::istream*)'Where is my mistake? How do I make it work?
解决方案Your program fails to link because
${PROTOBUF_LIBRARY}
is empty in the scope of your top-levelCMakeLists.txt
. This happens because callingadd_subdirectory
creates a child scope, and theProtobuf_XXX
variables set byfind_package(Protobuf REQUIRED)
are only in that child scope.A good way to fix this is to add the following to
proto/CMakeLists.txt
:target_link_libraries(proto INTERFACE ${Protobuf_LIBRARIES})
This instructs targets that link to
proto
to also link to${Protobuf_LIBRARIES}
. Now you can simplifytarget_link_libraries
in your top-levelCMakeLists.txt
:target_link_libraries(addressbook proto)
On a side note, you could also use e.g.
target_link_libraries(${PROJECT_NAME} INTERFACE ... )
${PROJECT_NAME}
resolves to whatever you have set in theproject(...)
statement in thatCMakeLists.txt
file.Finally, note that this links to
Protobuf_LIBRARIES
instead ofPROTOBUF_LIBRARY
.Protobuf_LIBRARIES
includes both the Protocol Buffers libraries and the dependent Pthreads library.这篇关于CMake不适用于Google Protobuf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!