【发布时间】:2021-02-19 10:38:04
【问题描述】:
我正在尝试在rocksdb的源代码中直接使用gRPC
LogAndApplyClient log_and_apply_client(grpc::CreateChannel(
secondary, grpc::InsecureChannelCredentials()));
log_and_apply_client 是我编写的一个基本类,用于进行 rpcs 调用,它依赖于 Protobuf 生成的 Stub Code。我直接将它添加到rocksdb的源代码中。
为了解决 grpc 依赖关系,我使用 gRPC 提供的 CMakeLists 示例将依赖关系添加到 Rocksdb 的 CMakeLists.txt 文件中。 我在 Ubuntu18.04 中安装了 gRPC 和 protobuf,这就是我添加到 Rocksdb 的 CMakeLists 中的内容。 这样基本就找到了grpc和protobuf的安装了
# This branch assumes that gRPC and all its dependencies are already installed
# on this system, so they can be located by find_package().
# Find Protobuf installation
# Looks for protobuf-config.cmake file installed by Protobuf's cmake installation.
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${Protobuf_VERSION}")
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
set(_REFLECTION gRPC::grpc++_reflection)
if(CMAKE_CROSSCOMPILING)
find_program(_PROTOBUF_PROTOC protoc)
else()
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
endif()
# Find gRPC installation
# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
set(_GRPC_GRPCPP gRPC::grpc++)
if(CMAKE_CROSSCOMPILING)
find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
else()
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
endif()
用grpc、protobuf链接rocksdb
add_library(${ROCKSDB_STATIC_LIB} STATIC ${SOURCES})
target_link_libraries(${ROCKSDB_STATIC_LIB} PRIVATE
${THIRDPARTY_LIBS} ${SYSTEM_LIBS}
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF}
)
Rocksdb 编译正常,没有错误,但是当我尝试使用编译后的 Rocksdb 库时,它给了我一堆未定义的引用。
mnt/sdb/my_rocksdb/librocksdb.a(version_set.cc.o): In function `__static_initialization_and_destruction_0(int, int)':
/mnt/sdb/my_rocksdb/db/version_set.cc:4325: undefined reference to `grpc::InsecureChannelCredentials()'
/mnt/sdb/my_rocksdb/db/version_set.cc:4324: undefined reference to `grpc::CreateChannel(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<grpc::ChannelCredentials> const&)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::Response::_InternalParse(char const*, google::protobuf::internal::ParseContext*)':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:468: undefined reference to `google::protobuf::internal::UnknownFieldParse(unsigned long, google::protobuf::UnknownFieldSet*, char const*, google::protobuf::internal::ParseContext*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::Response::_InternalSerialize(unsigned char*, google::protobuf::io::EpsCopyOutputStream*) const':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:497: undefined reference to `google::protobuf::UnknownFieldSet::default_instance()'
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:497: undefined reference to `google::protobuf::internal::WireFormat::InternalSerializeUnknownFieldsToArray(google::protobuf::UnknownFieldSet const&, unsigned char*, google::protobuf::io::EpsCopyOutputStream*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::Response::ByteSizeLong() const':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:519: undefined reference to `google::protobuf::internal::ComputeUnknownFieldsSize(google::protobuf::internal::InternalMetadata const&, unsigned long, google::protobuf::internal::CachedSize*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::Response::MergeFrom(google::protobuf::Message const&)':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:534: undefined reference to `google::protobuf::internal::ReflectionOps::Merge(google::protobuf::Message const&, google::protobuf::Message*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::EditLists_EditList_VersionEdit::_InternalParse(char const*, google::protobuf::internal::ParseContext*)':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:705: undefined reference to `google::protobuf::internal::UnknownFieldParse(unsigned long, google::protobuf::UnknownFieldSet*, char const*, google::protobuf::internal::ParseContext*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::EditLists_EditList_VersionEdit::_InternalSerialize(unsigned char*, google::protobuf::io::EpsCopyOutputStream*) const':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:744: undefined reference to `google::protobuf::UnknownFieldSet::default_instance()'
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:744: undefined reference to `google::protobuf::internal::WireFormat::InternalSerializeUnknownFieldsToArray(google::protobuf::UnknownFieldSet const&, unsigned char*, google::protobuf::io::EpsCopyOutputStream*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::EditLists::MergeFrom(google::protobuf::Message const&)':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:1206: undefined reference to `google::protobuf::internal::ReflectionOps::Merge(google::protobuf::Message const&, google::protobuf::Message*)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::NewFile_FileMetaData_FileDescriptor::_InternalParse(char const*, google::protobuf::internal::ParseContext*)':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.cc:1378: undefined reference to `google::protobuf::internal::UnknownFieldParse(unsigned long, google::protobuf::UnknownFieldSet*, char const*, google::protobuf::internal::ParseContext*)'
/root/local/include/google/protobuf/unknown_field_set.h:312: undefined reference to `google::protobuf::UnknownFieldSet::ClearFallback()'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `google::protobuf::Message::Message()':
/root/local/include/google/protobuf/message.h:230: undefined reference to `vtable for google::protobuf::Message'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `google::protobuf::Message::Message(google::protobuf::Arena*)':
/root/local/include/google/protobuf/message.h:362: undefined reference to `vtable for google::protobuf::Message'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::Response::GetMetadataStatic()':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.h:207: undefined reference to `google::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const*, bool)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::EditLists_EditList_VersionEdit::GetMetadataStatic()':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.h:344: undefined reference to `google::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const*, bool)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::EditLists_EditList::GetMetadataStatic()':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.h:510: undefined reference to `google::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const*, bool)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o): In function `logapply::EditLists::GetMetadataStatic()':
/mnt/sdb/my_rocksdb/rubble/logAndApply/logAndApply.pb.h:658: undefined reference to `google::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const*, bool)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o):(.data.rel.ro._ZTVN8logapply20NewFile_FileMetaDataE[_ZTVN8logapply20NewFile_FileMetaDataE]+0x98): undefined reference to `google::protobuf::Message::SpaceUsedLong() const'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o):(.data.rel.ro._ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE[_ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE]+0x20): undefined reference to `google::protobuf::Message::GetTypeName[abi:cxx11]() const'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o):(.data.rel.ro._ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE[_ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE]+0x48): undefined reference to `google::protobuf::Message::InitializationErrorString[abi:cxx11]() const'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o):(.data.rel.ro._ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE[_ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE]+0x50): undefined reference to `google::protobuf::Message::CheckTypeAndMergeFrom(google::protobuf::MessageLite const&)'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o):(.data.rel.ro._ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE[_ZTVN8logapply35NewFile_FileMetaData_FileDescriptorE]+0x90): undefined reference to `google::protobuf::Message::DiscardUnknownFields()'
(.data.rel.ro._ZTIN8logapply20NewFile_FileMetaDataE[_ZTIN8logapply20NewFile_FileMetaDataE]+0x10): undefined reference to `typeinfo for google::protobuf::Message'
/mnt/sdb/my_rocksdb/librocksdb.a(logAndApply.pb.cc.o):(.data.rel.ro._ZTIN8logapply35NewFile_FileMetaData_FileDescriptorE[_ZTIN8logapply35NewFile_FileMetaData_FileDescriptorE]+0x10): more undefined references to `typeinfo for google::protobuf::Message' follow
collect2: error: ld returned 1 exit status
CMakeFiles/primary_server.dir/build.make:143: recipe for target 'primary_server' failed
make[2]: *** [primary_server] Error 1
CMakeFiles/Makefile2:98: recipe for target 'CMakeFiles/primary_server.dir/all' failed
make[1]: *** [CMakeFiles/primary_server.dir/all] Error 2
Makefile:102: recipe for target 'all' failed
make: *** [all] Error 2
这是我为使用rocksdb 库对象的客户端程序编写的CMakeLists 文件
# Proto file
get_filename_component(kv_proto "../protos/keyvaluestore.proto" ABSOLUTE)
get_filename_component(kv_proto_path "${kv_proto}" PATH)
# Generated sources
set(kv_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.pb.cc")
set(kv_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.pb.h")
set(kv_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.grpc.pb.cc")
set(kv_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.grpc.pb.h")
add_custom_command(
OUTPUT "${kv_proto_srcs}" "${kv_proto_hdrs}" "${kv_grpc_srcs}" "${kv_grpc_hdrs}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${kv_proto_path}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${kv_proto}"
DEPENDS "${kv_proto}")
# Include generated *.pb.h files
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories(/mnt/sdb/my_rocksdb/include)
link_directories(/mnt/sdb/my_rocksdb)
# kv_grpc_proto
add_library(kv_grpc_proto
${kv_grpc_srcs}
${kv_grpc_hdrs}
${kv_proto_srcs}
${kv_proto_hdrs})
target_link_libraries(kv_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF}
)
# Targets greeter_[async_](client|server)
foreach(_target
kv_store_client
primary_server
)
add_executable(${_target} "${_target}.cc")
target_link_libraries(${_target}
kv_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF}
liblog_and_apply_grpc_proto.a
librocksdb.a
)
endforeach()
我对 cmake 不太熟悉,当我尝试将依赖项添加到 RocksDB 的源代码中时,我想我没有做对,我真的有点卡在这个问题上,所以任何建议都会是赞赏!
【问题讨论】:
-
您似乎使用
make实用程序构建您的项目。如果这是真的,那么在调用make时添加VERBOSE=1选项。这样,它将打印传递给链接器的所有选项。检查grpc和protobuf库是否在这些选项中。 -
@Tsyvarev 感谢您的评论。这是我在指定
VERBOSE=1后得到的结果 看起来它没有找到库,但我仍然不确定为什么以及如何修复它 -
Building CXX object CMakeFiles/rocksdb.dir/db/version_set.cc.o /usr/bin/c++ -DCARES_STATICLIB -DGFLAGS=1 -DGFLAGS_IS_A_DLL=0 -I/mnt/sdb/my_rocksdb -I/mnt/sdb/my_rocksdb/include -I/mnt/sdb/my_rocksdb/third-party/folly -isystem /root/local/include -W -Wextra -Wall -Wno-unused-parameter -Wno-unused-variable -Woverloaded-virtual -Wnon-virtual-dtor -Wno-missing-field-initializers -Wno-strict-aliasing -march=native -Werror -fno-builtin-memcmp -g -DROCKSDB_USE_RTTI -std=gnu++11 -o CMakeFiles/rocksdb.dir/db/version_set.cc.o -c /mnt/sdb/my_rocksdb/db/version_set.cc -
等待.. 这会找到库吗?我的
protoc和grpc安装在/root/local/下,输出显示-isystem /root/local/include。不确定它是否找到了 lib.. -
不,这不是您需要检查的命令行。您需要检查 linker 命令行(这会导致“未定义引用”错误),而不是 compiler 命令行。