在使用CMake对protobuf工程进行编译的过程中,首先根据教程将Protobuf库和头文件添加到目录中。
期间遇到Protobuf2和3 版本切换 的问题,根据另一个教程让CMake去找Conda中安装的Protobuf2的库。
但执行make时依然报错:
[100%] Linking CXX executable receive_test
CMakeFiles/receive_test.dir/lib/protocol/cone.pb.cc.o:(.data.rel.ro._ZTVN9ConeProto5ConesE[_ZTVN9ConeProto5ConesE]+0x40):对‘google::protobuf::MessageLite::InitializationErrorString[abi:cxx11]() const’未定义的引用
CMakeFiles/receive_test.dir/lib/protocol/cone.pb.cc.o:(.data.rel.ro._ZTVN9ConeProto4ConeE[_ZTVN9ConeProto4ConeE]+0x40):对‘google::protobuf::MessageLite::InitializationErrorString[abi:cxx11]() const’未定义的引用
CMakeFiles/receive_test.dir/lib/protocol/freespace.pb.cc.o:(.data.rel.ro._ZTVN14FreeSpaceProto9FreeSpaceE[_ZTVN14FreeSpaceProto9FreeSpaceE]+0x40):对‘google::protobuf::MessageLite::InitializationErrorString[abi:cxx11]() const’未定义的引用
CMakeFiles/receive_test.dir/lib/protocol/lane.pb.cc.o:(.data.rel.ro._ZTVN9LaneProto5LinesE[_ZTVN9LaneProto5LinesE]+0x40):对‘google::protobuf::MessageLite::InitializationErrorString[abi:cxx11]() const’未定义的引用
CMakeFiles/receive_test.dir/lib/protocol/lane.pb.cc.o:(.data.rel.ro._ZTVN9LaneProto4LineE[_ZTVN9LaneProto4LineE]+0x40):对‘google::protobuf::MessageLite::InitializationErrorString[abi:cxx11]() const’未定义的引用
CMakeFiles/receive_test.dir/lib/protocol/lane.pb.cc.o:(.data.rel.ro._ZTVN9LaneProto9StopLinesE[_ZTVN9LaneProto9StopLinesE]+0x40): 跟着更多未定义的参考到 google::protobuf::MessageLite::InitializationErrorString[abi:cxx11]() const
collect2: error: ld returned 1 exit status
CMakeFiles/receive_test.dir/build.make:305: recipe for target 'receive_test' failed
make[2]: *** [receive_test] Error 1
CMakeFiles/Makefile2:99: recipe for target 'CMakeFiles/receive_test.dir/all' failed
make[1]: *** [CMakeFiles/receive_test.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
后来根据stackoverflow上的问答得知,这是由于Protobuf2编译器版本较老(GCC 4.x),与当前编译器版本不匹配导致的。解决方法有两种:
- 重新用GCC 5编译libprotobuf(但可能存在问题,有些应用不支持GCC 5)
- 在编译选项中加入:
-D_GLIBCXX_USE_CXX11_ABI=0
采用第二种方法后最终成功编译程序。CMakeLists.txt如下:
# cmake version
cmake_minimum_required(VERSION 3.0)
project(receive_test)
set(CMAKE_CXX_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0")
set(CMAKE_BUILD_TYPE "Debug")
# set(CMAKE_LIBRARY_PATH "/home/yuyize/miniconda")
set(CMAKE_PREFIX_PATH "/home/yuyize/miniconda3/envs/proto2")
find_package(Threads)
find_package(Protobuf REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib ${Protobuf_INCLUDE_DIR})
#build proto
# set(PROTOC_CMD ${CMAKE_CURRENT_SOURCE_DIR}/lib/protocol/raw/protoc)
set(PROTO_OUT "${CMAKE_CURRENT_SOURCE_DIR}/lib/protocol")
set(PROTO_RAW "${CMAKE_CURRENT_SOURCE_DIR}/lib/protocol/raw")
file(GLOB PROTO_FILES ${PROTO_RAW}/*.proto)
file(GLOB_RECURSE adas_protocol "${CMAKE_CURRENT_SOURCE_DIR}/lib/protocol/*.pb.*")
add_custom_target(build-protocol)
add_custom_command(
TARGET build-protocol
PRE_BUILD
COMMAND protoc
ARGS -I ${PROTO_RAW}
--cpp_out=${PROTO_OUT}
${PROTO_FILES}
)
# build program
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
add_subdirectory(lib)
aux_source_directory(. DIR_SRCS)
add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${DIR_SRCS} ${adas_protocol})
target_link_libraries(${PROJECT_NAME} network_receiver zmq ${CMAKE_THREAD_LIBS_INIT} ${PROTOBUF_LIBRARIES})