Trouble linking C++ with Xcode 5 - c++

So I have this legacy project, which I am trying to bring to iOS 7 and Xcode 5. And by legacy, I mean real legacy. Like 2004 legacy.
Anyhow, I am trying to build this thing, and it spits out a few libraries, including some common third party libs. When linking, I get errors like these:
Undefined symbols for architecture ${arch}:
"google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)"
Upon examination with nm, the old (arm only) binary library still included in the project contains this:
U __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE
00000a8c T __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE
00002b28 S __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE.eh</code>
The new library (universal), created when I run the project through Xcode 5 (and thus, clang/llvm) contains this:
U __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE
00000514 T __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE
00000b2c S __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE.eh
To me, it looks like the parameters are missing in the mangled name.
Is this normal and I need to look somewhere else?
Or if this is the problem: Any idea how to solve it?
EDIT: I mixed up OLD and NEW. I left the original post unchanged

The old, arm only libary seems to indicate:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)
Which has all the hallmarks of being compiled with libstdc++.
The new universal library indicates:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::io::CodedOutputStream*)
This has all the hallmarks of being compiled with libc++
Your link error indicates that there is a problem finding:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)
This would be the case if the code linking to the library was compiled using libstdc++ and, because your new universal library is compiled using libc++ the code will not link.
You have to compile everything with the same libc++/libstdc++ support, you cannot mix and match as they will refuse to link. Make sure that every element in your project is compiled using the same C++ Standard Library and the link error should be resolved.
In general, demangling the symbols (using c++filt) allows you to see the proper signatures, and in the case of this code, once you start seeing std::__1:: in the symbols, it indicates that the library was compiled using libc++, and when you see the link failing with unadorned std:: symbols (i.e. without the inner __1::), then it indicates that the item performing the linking is using libstdc++.

Are you perhaps mixing and matching SDKs or compilers? Name mangling might differ between compilers. The only other thing I know that might affect name mangling is the 'extern "C"' keyword, but that usually turns it off completely, so I don't think that's it.
So, if the old code was still built with GCC 2.x and your new code is clang-built, they probably just mangle differently.
Does the error message really say $(arch) ? Not a particular architecture? If it gave a concrete architecture, I'd expect that you have one project that builds e.g. for arm5 and arm6, linking in a library that only has one of these architectures. Then it usually complains about the symbols in that library not being available, I think.

Related

undefined reference to std::__cxx11::basic_string when linking to boost [duplicate]

I use c++11, but also some libraries that are not configured for it, and need some type conversion. In particular I need a way to convert std::__cxx11::string to regular std::string, but googling I can't find a way to do this and putting (string) in front does not work.
If I do not convert I get linker errors like this:
undefined reference to `H5::CompType::insertMember(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, H5::DataType const&) const'
Is it possible that you are using GCC 5?
If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.
Source: GCC 5 Release Notes/Dual ABI
Defining the following macro before including any standard library headers should fix your problem: #define _GLIBCXX_USE_CXX11_ABI 0
If you can recompile all incompatible libs you use, do it with compiler option
-D_GLIBCXX_USE_CXX11_ABI=1
and then rebuild your project. If you can't do so, add to your project's makefile compiler option
-D_GLIBCXX_USE_CXX11_ABI=0
The define
#define _GLIBCXX_USE_CXX11_ABI 0/1
is also good but you probably need to add it to all your files while compiler option do it for all files at once.
When I had similar issue it's happened because my lib was build using clang++, and it's linked to libstdc++.so by default on my system. While app binary was build using clang and linked with -lc++ option.
Easiest way to check dependencies is to perform ldd libName.so
To fix it you should use the same library on in app and library.
Easiest way. Build library using clang++ and compile app using clang++. Without extra linking options on both steps. Default stdlib will be used.
Build library with -stdlib=c++ and compile app with -lc++. In this case both library and app will use libc++.so.
Build library without extra options and link binary to -lstdc++. In this case both library and app will use libstdc++.so.
Answers here mostly focus on short way to fix it, but if that does not help, I'll give some steps to check, that helped me (Linux only):
If the linker errors happen when linking other libraries, build those libs with debug symbols ("-g" GCC flag)
List the symbols in the library and grep the symbols that linker complains about (enter the commands in command line):
nm lib_your_problem_library.a | grep functionNameLinkerComplainsAbout
If you got the method signature, proceed to the next step, if you got no symbols instead, mostlikely you stripped off all the symbols from the library and that is why linker can't find them when linking the library. Rebuild the library without stripping ALL the symbols, you can strip debug (strip -S option) symbols if you need.
Use a c++ demangler to understand the method signature, for example, this one
Compare the method signature in the library that you just got with the one you are using in code (check header file as well), if they are different, use the proper header or the proper library or whatever other way you now know to fix it
I got this, the only way I found to fix this was to update all of mingw-64 (I did this using pacman on msys2 for your information).
For me -D_GLIBCXX_USE_CXX11_ABI=0 didn't help.
It works after I linked to C++ libs version instead of gnustl.
I had a similar issue recently while trying to link with the pre-built binaries of hdf5 version 1.10.5 on Ubuntu 16.04. None of the solutions suggested here worked for me, and I was using g++ version 9.1. I found that the best solution is to build the hdf5 library from source. Do not use the pre-built binaries since these were built using gcc 4.9! Instead, download the source code archives from the hdf website for your particular distribution and build the library. It is very easy.
You will also need the compression libraries zlib and szip from here and here, respectively, if you do not already have them on your system.
In my case, I was having a similar problem:
/usr/bin/ld: Bank.cpp:(.text+0x19c): undefined reference to 'Account::SetBank(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: error: ld returned 1 exit status
After some researches, I realized that the problem was being generated by the way that Visual Studio Code was compiling the Bank.cpp file. So, to solve that, I just prompted the follow command in order to compile the c++ file sucessful:
g++ Bank.cpp Account.cpp -o Bank
With the command above, It was able to linkage correctly the Header, Implementations and Main c++ files.
OBS: My g++ version: 9.3.0 on Ubuntu 20.04
I've encountered similar problems
It turns out my project was using gcc 7 and g++ 9 and tried to link together object files compiled by those two and it all messed up.
Make sure you use the same compiler versions in all your project.

G++ new ABI problems

I got a problem with the new ABI introduced for C++11 in GCC. After upgrading to GCC 5.3 my project does no longer compile. The error messages I get are simple:
undefined reference to `tokenize(std::__cxx11::basic_string' ...more characters
or
undefined reference to `extract(std::string const&)'
So, it looks like I messed something up and GCC is unable to decide whether I want the old ABI or the new one (the __cxx11:: part is missing from some error messages, and present in others)?
I tried several solutions to resolve the issue:
passing -D_GLIBCXX_USE_CXX11_ABI=0 to GCC,
passing -D_GLIBCXX_USE_CXX11_ABI=1 to GCC,
setting the macro directly in source code,
setting the abi_tag attribute on the declarations GCC complained about when passed the -Wabi-tag flag,
Unfortunately, neither of them worked (i.e. allowed the code to compile). The one thing I know is that only functions returning std::string or taking it as a parameter fail to link. Which is to be expected, given what I read about the problem on the Internet. I was unable to reproduce the issue in a simple, example program to present it here.
Is there any obvious solution to my problem, that I am missing?
This error indicates that you're linking to some code or library that has not been recompiled by gcc 5.3, and was compiled by an earlier version of gcc, using the earlier version of the ABI.
If you are linking with some external libraries, besides the standard C++ library, those external libraries need to be recompiled (and reinstalled).
If you are not linking with any external libraries, and you are only linking together your own code, some of your source modules must not've been recompiled yet. Recompile everything. Make sure to wipe all existing object modules, with make clean, or the equivalent for whatever build system you're using.

Using boost library with different compiler version

I compiled boost 1.54 with gcc version 4.6.3( in 3.2.0-29-generic #46-Ubuntu ).
Then, I developed my library using this boost library. Since I don't want to recompile boost every time I change my library, I added compiled static libraries of boost to my git repo.
Now, I am trying to compile my library in a different machine with different version compiler (tried with gcc 4.4 and gcc 4.7). My library compiles fine, but when it comes to linking it is printing following errors.
`.text._ZN5boost16exception_detail10bad_alloc_D2Ev' referenced in section `.text._ZN5boost16exception_detail10bad_alloc_D1Ev[boost::exception_detail::bad_alloc_::~bad_alloc_()]' of ../external/lib/linux/64/libboost_thread.a(thread.o): defined in discarded section `.text._ZN5boost16exception_detail10bad_alloc_D2Ev[_ZN5boost16exception_detail10bad_alloc_D5Ev]' of ../external/lib/linux/64/libboost_thread.a(thread.o)
`.text._ZN5boost16exception_detail14bad_exception_D2Ev' referenced in section `.text._ZN5boost16exception_detail14bad_exception_D1Ev[boost::exception_detail::bad_exception_::~bad_exception_()]' of ../external/lib/linux/64/libboost_thread.a(thread.o): defined in discarded section `.text._ZN5boost16exception_detail14bad_exception_D2Ev[_ZN5boost16exception_detail14bad_exception_D5Ev]' of ../external/lib/linux/64/libboost_thread.a(thread.o)
`.text._ZN5boost16exception_detail19error_info_injectorINS_21thread_resource_errorEED2Ev' referenced in section `.text._ZN5boost16exception_detail19error_info_injectorINS_21thread_resource_errorEED1Ev[boost::exception_detail::error_info_injector<boost::thread_resource_error>::~error_info_injector()]' of ../external/lib/linux/64/libboost_thread.a(thread.o): defined in discarded section `.text._ZN5boost16exception_detail19error_info_injectorINS_21thread_resource_errorEED2Ev[_ZN5boost16exception_detail19error_info_injectorINS_21thread_resource_errorEED5Ev]' of ../external/lib/linux/64/libboost_thread.a(thread.o)
`.text._ZN5boost16exception_detail19error_info_injectorINS_10lock_errorEED2Ev' referenced in section `.text._ZN5boost16exception_detail19error_info_injectorINS_10lock_errorEED1Ev[boost::exception_detail::error_info_injector<boost::lock_error>::~error_info_injector()]' of ../external/lib/linux/64/libboost_thread.a(thread.o): defined in discarded section `.text._ZN5boost16exception_detail19error_info_injectorINS_10lock_errorEED2Ev[_ZN5boost16exception_detail19error_info_injectorINS_10lock_errorEED5Ev]' of ../external/lib/linux/64/libboost_thread.a(thread.o)
`.text._ZN5boost16exception_detail19error_info_injectorINS_15condition_errorEED2Ev' referenced in section `.text._ZN5boost16exception_detail19error_info_injectorINS_15condition_errorEED1Ev[boost::exception_detail::error_info_injector<boost::condition_error>::~error_info_injector()]' of ../external/lib/linux/64/libboost_thread.a(thread.o): defined in discarded section `.text._ZN5boost16exception_detail19error_info_injectorINS_15condition_errorEED2Ev[_ZN5boost16exception_detail19error_info_injectorINS_15condition_errorEED5Ev]' of ../external/lib/linux/64/libboost_thread.a(thread.o)
collect2: ld returned 1 exit status
make[2]: *** [libHazelcastClientShared_64.so] Error 1
make[1]: *** [CMakeFiles/HazelcastClientShared_64.dir/all] Error 2
make: *** [all] Error 2
PS: I tried to compile with a different machine with same compiler version also. (gcc version 4.6.3 and Centos 6.4)
The c++ ABI is not gauranteed to be consistent across different compiler versions. This affects the c++ name mangling and could cause the linker errors you are seeing. You have to use the same version of gcc for all libs.
The best would be to keep your whole system on the latest supported version of gcc. If your users really require different compilers then you can supply different versions of your library - one for each compiler you want to support.
Linking with libraries compiled with different compilers is not gauranteed to work. This is true for both static and shared/dynamic c++ libs.
Also have a look at:
Have a look at Unusual C++ linker error - 'Defined in discarded section'
It seems that the accepted answer to that question was also to compile all the libraries with the same version of GCC.
Boost is riddled with conditional compilation blocks based on the availability or support of different features by the compiler. See their macro list. Different compilers (or versions) have different levels of support for different standard features (or extensions). The Boost libraries are a mix of code that tailors to the least common denominator (when it doesn't "hurt" the code), compiler-specific workarounds, and conditional use of features that, when supported, can provide a clear benefit.
I am very inclined to believe that this is what is causing the issue. When you first compiled to code for a particular compiler and platform, certain switches were turned on and others turned off depending on what that platform supported, leading to a binary library that only really works for that platform. Then, when you tried to compiler your code on another platform, different switches were turned on/off within the boost headers, leading to incompatibilities at link-time.
Long story short, you cannot do what you are trying to do, at least, not without quite a bit of work. One solution would be to figure out what boost macros (from the list I linked to) are turned on or off on the least capable platform, and then, manually define those macros in your code to enforce an identical compilation on all platforms. But this could be labour-intensive.
Boost has very good and wide-spread distribution (of binaries too). So, I wouldn't worry too much about being able to install the boost binaries on different platforms.

Which libraries do I need to link against with MinGW for an object file built with Clang?

I'm using an object file built with Clang. But no matter what library arguments I pass to ld.exe, it seems to always spit back unresolved references, stuff like memcpy, Standard library, stuff, and implementation stuff like _cxa_atexit.
What libraries (and in what order?) do I need to pass to the MinGW linker to get it to link my object file into an executable?
Edit:
I changed the triple from "i686-pc-mingw" to "i686-pc-mingw32" and it solved most of the problems- Clang does the old D3D9 trick of "Silently fail when the input is clearly wrong and there's no way the output could be correct". But I'm left with just two unresolved externals- it's some std::_Hash_impl for float and double, with no change. The program is just "Hello, World!". Curiously, neither clang++.exe nor g++.exe have a problem with compiling the source, but if I compile it using the Clang C++ API to .o, and then pass it back to MinGW, I get the unresolved externals.
In general, it's not a good idea to use different toolchains when building a binary. It is entirely possible that the different tools' ideas of names of symbols won't match up.
Still, trying to answer your actual quesiton:
-lstdc would be a minimum requirement and -lstdc++ if it's C++ code. without knowing what your code does, it's impossible to say if you need more of them.

mixing compiler

I am wondering if it is possible to link a c++ program compiled with gcc4.2 with a shared c++ library that is compiled in a later version like gcc4.5.
I've tried to do this, but have run into some different kind of problems.
When compiling the shared library gcc5.3 I get a message saying:
*"malloc: error for object 0x7fff707d2500: pointer being freed was not allocated
set a breakpoint in malloc_error_break to debug"*.
If I try to compile the shared library with gcc4.6 I get really strange behaviour. The std::stringstream class is not working correctly. The resulting string is empty after writing to the stream.
Is it possible to do this? Or am I trying something that is impossible? I was hoping that this was possible since I'm linking the lib dynamically. Btw I'm running on MacOSX.
BR
Beginning with gcc 3.0, g++ follows the Itanium ABI, so in theory there should be no problem. However, g++ 4.2 has CXXABI_1.3.1 whereas g++ 4.5 has CXXABI_1.3.4 (see here). Therefore I'd be careful. One does not bump up revision numbers if there are no differences.
Further, the glibc++ has gone through 5 revisions between those versions, which may be one reason why you see std::stringstream do funny things.
Lastly, there exist many config options (such as for example making strings fully dynamic or not) which affect the behaviour and compatibility of the standard library directly. Given two (random, unknown) builds, you cannot even know that they have the same config options.
In my experience the ABI compatibility means that C++ libraries can link to each-other without problems.
However, because C++ uses so many inline functions this doesn't mean much.
If the Standard C++ Library used all inline functions or used all library functions then you could use code compiled with older versions of GCC with newer versions.
But it doesn't. The library mixes inline and external library code. This means that if something is changed in std::string, or std::vector or locales or whatever, then the inlined code from the old GCC is out of sync with the library code linked from the new GCC.