好吧,我在尝试理解如何编译包含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如何找到它并给我一个链接两个库的链接。