1

I am trying to just do a simple example for protobuf and I am having trouble linking. I haven't found anything worthwhile on here.

For starters, I have a very barebones .proto file

tempproj.proto

 package tempproj;
 message name
 {
     required string first = 1;
     required string last = 2;
 }

I am building it via:

$ protoc --cpp_out=. tempproj.proto

It is generating tempproj.pb.h and tempproj.pb.cc. I am assuming the generated code is correct.

I then have a file, main.cpp, which is barebones as well

 #include "tempproj.bh.h"

 int main(int argc, char** argv)
 {
      return 0;
 }

I then compile it via:

 $ g++ -std=gnu++14 -m64 -lprotobuf main.cpp tempproj.pb.cc

And the output is

 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o: in function `protobuf_tempproj_2eproto::protobuf_AssignDescriptors()':
 tempproj.pb.cc:(.text+0xf6): 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**)'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o: in function `protobuf_tempproj_2eproto::AddDescriptorsImpl()':
 tempproj.pb.cc:(.text+0x1a5): undefined reference to `google::protobuf::MessageFactory::InternalRegisterGeneratedFile(char const*, void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&))'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o: in function `tempproj::name::SerializeWithCachedSizes(google::protobuf::io::CodedOutputStream*) const':
 tempproj.pb.cc:(.text+0xcb9): 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*)'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: tempproj.pb.cc:(.text+0xd24): 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*)'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o: in function `google::protobuf::internal::GetEmptyStringAlreadyInited[abi:cxx11]()':
 tempproj.pb.cc:(.text._ZN6google8protobuf8internal27GetEmptyStringAlreadyInitedB5cxx11Ev[_ZN6google8protobuf8internal27GetEmptyStringAlreadyInitedB5cxx11Ev]+0x5): undefined reference to `google::protobuf::internal::fixed_address_empty_string[abi:cxx11]'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o: in function `google::protobuf::internal::WireFormatLite::ReadString(google::protobuf::io::CodedInputStream*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)':
 tempproj.pb.cc:(.text._ZN6google8protobuf8internal14WireFormatLite10ReadStringEPNS0_2io16CodedInputStreamEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN6google8protobuf8internal14WireFormatLite10ReadStringEPNS0_2io16CodedInputStreamEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x1f): undefined reference to `google::protobuf::internal::WireFormatLite::ReadBytes(google::protobuf::io::CodedInputStream*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o: in function `google::protobuf::internal::WireFormatLite::WriteStringToArray(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*)':
 tempproj.pb.cc:(.text._ZN6google8protobuf8internal14WireFormatLite18WriteStringToArrayEiRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPh[_ZN6google8protobuf8internal14WireFormatLite18WriteStringToArrayEiRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPh]+0x39): undefined reference to `google::protobuf::io::CodedOutputStream::WriteStringWithSizeToArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*)'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o:(.rodata._ZTVN8tempproj4nameE[_ZTVN8tempproj4nameE]+0x20): undefined reference to `google::protobuf::Message::GetTypeName[abi:cxx11]() const'
 /opt/rh/gcc-toolset-11/root/usr/bin/ld: /tmp/ccj7rSmF.o:(.rodata._ZTVN8tempproj4nameE[_ZTVN8tempproj4nameE]+0x58): undefined reference to `google::protobuf::Message::InitializationErrorString[abi:cxx11]() const'
 collect2: error: ld returned 1 exit status

The paths are in normal places /usr/include for headers /usr/lib64 for libs.

Even when I explicitly set the lib path a la

 $ g++ -std=gnu++14 -m64 -L/usr/lib64 -lprotobuf main.cpp tempproj.pb.cc

I get the same results. I am rather stumped at this point.

FWIW I am using EL8, gcc-toolkit-11 (g++ 11.2.1)

edit: found the fix I believe: build with -D_GLIBCXX_USE_CXX11_ABI=0 (https://gcc.gnu.org/gcc-5/changes.html#libstdcxx)

basil
  • 690
  • 2
  • 11
  • 30
  • This is a common gotcha. Put `-lprotobuf` at the end of the command line, after the files that need it. – Botje Jul 13 '23 at 22:26
  • @Botje maybe I am misunderstanding you: `$ g++ -std=gnu++14 -m64 main.cpp tempproj.pb.cc -lprotobuf` produces the same results for me unfortunately – basil Jul 13 '23 at 22:35
  • How did you acquire libprotobuf? Is it possible it was compiled without the C++11 ABI? – Botje Jul 13 '23 at 22:39
  • I installed it via yum (`protobuf`, `protobuf-compiler`, `protobuf-devel` packages) – basil Jul 13 '23 at 22:46
  • that is not detailed enough, i'm afraid. What does `nm /usr/lib64/libprotobuf.so | grep GetTypeName` say? Possibly with `nm -D`. – Botje Jul 13 '23 at 23:00
  • Had to use `-D`: `000000000019cf40 T _ZNK6google8protobuf7Message11GetTypeNameEv 00000000001abeb0 W` `_ZNK6google8protobuf8internal12MapEntryImplINS0_27Struct_FieldsEntry_DoNotUseENS0_7MessageESsNS0_5ValueELNS1_14WireFormatLite9FieldTypeE9ELS7_11ELi0EE11GetTypeNameEv` – basil Jul 13 '23 at 23:18
  • 1
    Yup. there's your problem. The symbol name is missing the cxx11 ABI tag, which means this library was not compiled as C++11, which means you cannot use it together with code that does (eg yours.) – Botje Jul 13 '23 at 23:25
  • Damnit. Ok. Thanks for the help – basil Jul 14 '23 at 00:05
  • @Botje this doesn't seem to work for pre-c++11 code (i.e. building with e.g. `-std=c++03` as well. what is a workaround for this? – basil Jul 14 '23 at 13:06
  • Make sure everything is built using the same compiler version and same compiler flags – Botje Jul 14 '23 at 13:39
  • @Botje once again, thanks for the help. posted an edit with a fix that worked for me – basil Jul 14 '23 at 19:06
  • That just moves the problem but is sufficient for some use cases, yes. – Botje Jul 15 '23 at 10:54

0 Answers0