对谷歌protobuf

时间:2018-02-21 16:49:24

标签: c++ cmake google-protocol-buffer

好吧,我在尝试理解如何编译包含Google的protobuf生成的代码的库时遇到了一些问题。这是我的CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)

set (CMAKE_CXX_STANDARD 11)

include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/sandbox
    /usr
)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/libraries)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/executables)
SET(COMPILE_FLAGS "-I/usr/local/include -pthread ")
SET(LINK_FLAGS "-L/usr/local/lib -lprotobuf -pthread -lpthread")
SET( CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}" )
SET( CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${LINK_FLAGS}" )

add_library(
    protoAddress
    SHARED
    ${CMAKE_CURRENT_SOURCE_DIR}/sandbox/addressbook.pb.cc
)


add_executable(prueba sandbox/testProto.cpp)
target_link_libraries(prueba protoAddress)

addressbook.pb.cc是在Google的例子中使用带有--cpp_out的protoc命令时生成的源代码:

syntax = "proto2";

package tutorial;

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

我尝试制作可执行文件的测试与使用google解释如何使用c ++的示例相同:

#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
  cout << "Enter person ID number: ";
  int id;
  cin >> id;
  person->set_id(id);
  cin.ignore(256, '\n');

  cout << "Enter name: ";
  getline(cin, *person->mutable_name());

  cout << "Enter email address (blank for none): ";
  string email;
  getline(cin, email);
  if (!email.empty()) {
    person->set_email(email);
  }

  while (true) {
    cout << "Enter a phone number (or leave blank to finish): ";
    string number;
    getline(cin, number);
    if (number.empty()) {
      break;
    }

    tutorial::Person::PhoneNumber* phone_number = person->add_phones();
    phone_number->set_number(number);

    cout << "Is this a mobile, home, or work phone? ";
    string type;
    getline(cin, type);
    if (type == "mobile") {
      phone_number->set_type(tutorial::Person::MOBILE);
    } else if (type == "home") {
      phone_number->set_type(tutorial::Person::HOME);
    } else if (type == "work") {
      phone_number->set_type(tutorial::Person::WORK);
    } else {
      cout << "Unknown phone type.  Using default." << endl;
    }
  }
}

// Main function:  Reads the entire address book from a file,
//   adds one person based on user input, then writes it back out to the same
//   file.
int main(int argc, char* argv[]) {
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (argc != 2) {
    cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
    return -1;
  }

  tutorial::AddressBook address_book;

  {
    // Read the existing address book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!input) {
      cout << argv[1] << ": File not found.  Creating a new file." << endl;
    } else if (!address_book.ParseFromIstream(&input)) {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  // Add an address.
  PromptForAddress(address_book.add_people());

  {
    // Write the new address book back to disk.
    fstream output(argv[1], ios::out | ios::trunc | ios::binary);
    if (!address_book.SerializeToOstream(&output)) {
      cerr << "Failed to write address book." << endl;
      return -1;
    }
  }

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

在尝试制作这个CMakeLists后,我收到了很多错误,主要来自未定义的引用:

    -- Configuring done
-- Generating done
-- Build files have been written to: /home/jverdeguer/Documents/workspace/protobuf/build
[ 25%] Building CXX object CMakeFiles/protoAddress.dir/sandbox/addressbook.pb.cc.o
[ 50%] Linking CXX shared library ../libraries/libprotoAddress.so
[ 50%] Built target protoAddress
[ 75%] Building CXX object CMakeFiles/prueba.dir/sandbox/testProto.cpp.o
[100%] Linking CXX executable ../executables/prueba
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `main':
testProto.cpp:(.text+0x2f6): undefined reference to `google::protobuf::internal::VerifyVersion(int, int, char const*)'
testProto.cpp:(.text+0x3f0): undefined reference to `google::protobuf::Message::ParseFromIstream(std::istream*)'
testProto.cpp:(.text+0x4b1): undefined reference to `google::protobuf::Message::SerializeToOstream(std::ostream*) const'
testProto.cpp:(.text+0x502): undefined reference to `google::protobuf::ShutdownProtobufLibrary()'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::Arena::AllocHook(std::type_info const*, unsigned long) const':
testProto.cpp:(.text._ZNK6google8protobuf5Arena9AllocHookEPKSt9type_infom[_ZNK6google8protobuf5Arena9AllocHookEPKSt9type_infom]+0x3d): undefined reference to `google::protobuf::Arena::OnArenaAllocation(std::type_info const*, unsigned long)const'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::internal::ArenaStringPtr::CreateInstanceNoArena(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const*)':
testProto.cpp:(.text._ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x4b): undefined reference to `google::protobuf::internal::LogMessage::LogMessage(google::protobuf::LogLevel, char const*, int)'
testProto.cpp:(.text._ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x61): undefined reference to `google::protobuf::internal::LogMessage::operator<<(char const*)'
testProto.cpp:(.text._ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x79): undefined reference to `google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)'
testProto.cpp:(.text._ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x8d): undefined reference to `google::protobuf::internal::LogMessage::~LogMessage()'
testProto.cpp:(.text._ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN6google8protobuf8internal14ArenaStringPtr21CreateInstanceNoArenaEPKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0xdc): undefined reference to `google::protobuf::internal::LogMessage::~LogMessage()'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::internal::GetEmptyStringAlreadyInited[abi:cxx11]()':
testProto.cpp:(.text._ZN6google8protobuf8internal27GetEmptyStringAlreadyInitedB5cxx11Ev[_ZN6google8protobuf8internal27GetEmptyStringAlreadyInitedB5cxx11Ev]+0x5): undefined reference to `google::protobuf::internal::fixed_address_empty_string[abi:cxx11]'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::RepeatedPtrField<tutorial::Person_PhoneNumber>::TypeHandler::Type* google::protobuf::internal::RepeatedPtrFieldBase::Add<google::protobuf::RepeatedPtrField<tutorial::Person_PhoneNumber>::TypeHandler>(google::protobuf::RepeatedPtrField<tutorial::Person_PhoneNumber>::TypeHandler::Type*)':
testProto.cpp:(.text._ZN6google8protobuf8internal20RepeatedPtrFieldBase3AddINS0_16RepeatedPtrFieldIN8tutorial18Person_PhoneNumberEE11TypeHandlerEEEPNT_4TypeESB_[_ZN6google8protobuf8internal20RepeatedPtrFieldBase3AddINS0_16RepeatedPtrFieldIN8tutorial18Person_PhoneNumberEE11TypeHandlerEEEPNT_4TypeESB_]+0x95): undefined reference to `google::protobuf::internal::RepeatedPtrFieldBase::Reserve(int)'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::RepeatedPtrField<tutorial::Person>::TypeHandler::Type* google::protobuf::internal::RepeatedPtrFieldBase::Add<google::protobuf::RepeatedPtrField<tutorial::Person>::TypeHandler>(google::protobuf::RepeatedPtrField<tutorial::Person>::TypeHandler::Type*)':
testProto.cpp:(.text._ZN6google8protobuf8internal20RepeatedPtrFieldBase3AddINS0_16RepeatedPtrFieldIN8tutorial6PersonEE11TypeHandlerEEEPNT_4TypeESB_[_ZN6google8protobuf8internal20RepeatedPtrFieldBase3AddINS0_16RepeatedPtrFieldIN8tutorial6PersonEE11TypeHandlerEEEPNT_4TypeESB_]+0x95): undefined reference to `google::protobuf::internal::RepeatedPtrFieldBase::Reserve(int)'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::internal::GenericTypeHandler<tutorial::Person_PhoneNumber>::New(google::protobuf::Arena*)':
testProto.cpp:(.text._ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial18Person_PhoneNumberEE3NewEPNS0_5ArenaE[_ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial18Person_PhoneNumberEE3NewEPNS0_5ArenaE]+0xb6): undefined reference to `google::protobuf::internal::ArenaImpl::AllocateAligned(unsigned long)'
testProto.cpp:(.text._ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial18Person_PhoneNumberEE3NewEPNS0_5ArenaE[_ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial18Person_PhoneNumberEE3NewEPNS0_5ArenaE]+0xd3): undefined reference to `google::protobuf::internal::ArenaImpl::AllocateAlignedAndAddCleanup(unsigned long, void (*)(void*))'
CMakeFiles/prueba.dir/sandbox/testProto.cpp.o: In function `google::protobuf::internal::GenericTypeHandler<tutorial::Person>::New(google::protobuf::Arena*)':
testProto.cpp:(.text._ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial6PersonEE3NewEPNS0_5ArenaE[_ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial6PersonEE3NewEPNS0_5ArenaE]+0xb6): undefined reference to `google::protobuf::internal::ArenaImpl::AllocateAligned(unsigned long)'
testProto.cpp:(.text._ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial6PersonEE3NewEPNS0_5ArenaE[_ZN6google8protobuf8internal18GenericTypeHandlerIN8tutorial6PersonEE3NewEPNS0_5ArenaE]+0xd3): undefined reference to `google::protobuf::internal::ArenaImpl::AllocateAlignedAndAddCleanup(unsigned long, void (*)(void*))'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::RegisterAllTypes(google::protobuf::Metadata const*, int)'
../libraries/libprotoAddress.so: undefined reference to `vtable for google::protobuf::Closure'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::io::CodedOutputStream::WriteStringWithSizeToArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormatLite::WriteEnum(int, int, google::protobuf::io::CodedOutputStream*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, google::protobuf::io::CodedOutputStream*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::io::CodedInputStream::ReadVarintSizeAsIntFallback()'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::InitProtobufDefaults()'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormatLite::WriteInt32(int, int, google::protobuf::io::CodedOutputStream*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::Message::CheckTypeAndMergeFrom(google::protobuf::MessageLite const&)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::GoogleOnceInitImpl(long*, google::protobuf::Closure*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::io::CodedInputStream::ReadTagFallback(unsigned int)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormatLite::ReadBytes(google::protobuf::io::CodedInputStream*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::Message::GetTypeName[abi:cxx11]() const'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::Message::InitializationErrorString[abi:cxx11]() const'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormat::SerializeUnknownFields(google::protobuf::UnknownFieldSet const&, google::protobuf::io::CodedOutputStream*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::Message::DiscardUnknownFields()'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::UnknownFieldSet::AddVarint(int, unsigned long)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::MessageLite::SerializeWithCachedSizesToArray(unsigned char*) const'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(int, google::protobuf::MessageLite const&, google::protobuf::io::CodedOutputStream*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormatLite::VerifyUtf8String(char const*, int, google::protobuf::internal::WireFormatLite::Operation, char const*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::OnShutdownDestroyMessage(void const*)'
../libraries/libprotoAddress.so: undefined reference to `vtable for google::protobuf::internal::FunctionClosure0'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::DescriptorPool::InternalAddGeneratedFile(void const*, int)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::ReflectionOps::Merge(google::protobuf::Message const&, google::protobuf::Message*)'
../libraries/libprotoAddress.so: undefined reference to `vtable for google::protobuf::MessageLite'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::FunctionClosure0::~FunctionClosure0()'
../libraries/libprotoAddress.so: undefined reference to `typeinfo for google::protobuf::Message'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::UnknownFieldSet::default_instance()'
../libraries/libprotoAddress.so: undefined reference to `vtable for google::protobuf::Message'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::UnknownFieldSet::MergeFrom(google::protobuf::UnknownFieldSet const&)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::UnknownFieldSet::ClearFallback()'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::io::CodedInputStream::IncrementRecursionDepthAndPushLimit(int)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(google::protobuf::UnknownFieldSet const&, unsigned char*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(google::protobuf::UnknownFieldSet const&)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::Message::SpaceUsedLong() const'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::io::CodedInputStream::ReadVarint32Fallback(unsigned int)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::RepeatedPtrFieldBase::InternalExtend(int)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::WireFormat::SkipField(google::protobuf::io::CodedInputStream*, unsigned int, google::protobuf::UnknownFieldSet*)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::MessageFactory::InternalRegisterGeneratedFile(char const*, void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&))'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::internal::AssignDescriptors(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, google::protobuf::internal::MigrationSchema const*, google::protobuf::Message const* const*, unsigned int const*, google::protobuf::MessageFactory*, google::protobuf::Metadata*, google::protobuf::EnumDescriptor const**, google::protobuf::ServiceDescriptor const**)'
../libraries/libprotoAddress.so: undefined reference to `google::protobuf::io::CodedInputStream::DecrementRecursionDepthAndPopLimit(int)'
collect2: error: ld returned 1 exit status
CMakeFiles/prueba.dir/build.make:95: recipe for target '../executables/prueba' failed
make[2]: *** [../executables/prueba] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/prueba.dir/all' failed
make[1]: *** [CMakeFiles/prueba.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

与谷歌图书馆链接时似乎很明显有问题,但我看不出有什么问题或者如何解决它

仅供参考:我运行的是Linux Mint 18&#39; Sonya&#39;并使用默认选项从github安装protoc包。

任何人都可以帮我解决这些错误并解释发生了什么吗?如果您觉得需要更多信息,请随时提出。提前谢谢。

编辑: 我更新了我的cmakelists,现在它可以工作,但我不明白为什么。我接下来列出新的CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)

set (CMAKE_CXX_STANDARD 11)

include(FindProtobuf)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIR})
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/sandbox
    /usr
)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/libraries)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/executables)
SET(COMPILE_FLAGS "-I/usr/local/include -pthread ")
SET(LINK_FLAGS "-L/usr/local/lib -lprotobuf -pthread -lpthread")
SET( CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}" )
SET( CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${LINK_FLAGS}" )

add_library(
    protoAddress
    SHARED
    ${CMAKE_CURRENT_SOURCE_DIR}/sandbox/addressbook.pb.cc
)


add_executable(prueba sandbox/testProto.cpp)
target_link_libraries(prueba protoAddress ${PROTOBUF_LIBRARY})

我理解为什么我需要这个库,但不知道Cmake如何找到它并给我一个链接两个库的链接。

0 个答案:

没有答案