I am doing a build on a 32bit SLES10 machine. Using GCC 3.4.2
Here is a sample error
`.L8245' referenced in section `.rodata' of CMakeFiles/myproj.dir/c++/util/MyObj.o: defined in discarded section
`.gnu.linkonce.t._ZN5boost9re_detail9reg_grep2INS0_21grep_search_predicateIPKcSaIcEEES4_cNS_12regex_traitsIcEES5_S5_EEjT_T0_SA_RKNS_14reg_expressionIT1_T2_T3_EEjT4_' of CMakeFiles/myproj.dir/c++/util/MyObj.o
This is typically due to 2 different .cpp's being compiled with different compiler switches - but also using the same templates. The generated template instantiations may differ in what they define/reference, and if the instantiation that is selected doesn't define/refer to the exact same symbols as the ones that got discarded you may get this error.
Validate that all your .cpp's are compiled with the exact same compiler switches and defines. If this isn't possible, reorder the .obj files on the linker commandline, in particular try to move the .obj files mentioned in the error message to the end or beginning of the .obj file list.
EDIT:
Also, if you're linking against prebuilt c++ libraries, see if you can duplicate the compiler switches used for building these libraries.
This may be due to using a newer version of binutils. binutils version 2.15 treated this as a non-fatal error, but later versions of binutils changed and so the link started failing. See https://bugzilla.redhat.com/show_bug.cgi?id=191618 for a similar report.
In my case, I was able to get things to link once more by explicitly using binutils 2.16.1, instead of binutils 2.17.
Related
Situation:
I am using CI to compile a Windows version of my project using CMake and MSVC
It errors out right at the end complaining of two missing symbols (__std_system_error_allocate_message and __std_system_error_deallocate_message)
When I replicate the build process on my own computer, the build finishes fine and the artifacts run without errors.
Searching for these symbols on Google yields no clues as to which libraries they are supposed to be defined in.
Which leads to my question:
Is it possible to see where the MSVC linker is finding a particular symbol?
I was able to find instructions to look at what symbols are defined in a particular library, but this project is linking dozens of libraries, and the ones I have searched so far do not define the symbol. I think this approach is prone to errors as I might miss a library without knowing it.
#Richard Critten pointed me on the right path, the problem was due to having different versions of the MSVC toolchain on each system. GitLab's CI runners were using build tools version 16.2.3.0 while I was using a more recent 16.6.1.0. Uninstalling that and installing 16.2.3 from this page reproduced the error. Recompiling a dependency I had previously compiled with the newer toolchain then resolved the error on both systems.
There is a project that has a prebuilt dependencies (a bunch of static libs), all these libraries have debug info sections generated in default toolchain format - DWARF-4. I'm trying to compile my sources with -gdwarf-5, but linker fails to link final loadable binary:
ld.lld: error: linking module flags 'Dwarf Version': IDs have conflicting values ('i32 4' from foo/bar/baz.cc with 'i32 5' from ld-temp.o)
Is there any way to convince linker to continue even if different TU use different DWARF versions? After some googling I've found this ticket https://reviews.llvm.org/D52952, where the same issue was reported as warning, which makes me think that there might be some chances to suppress it.
P.S. All above is about LLVM toolchain from Android NDK r20 (claims to be LLVM 8), linker is lld.
P.S.S. I have no chance to recompile dependencies, that is why I'm looking for a way to allow different DWARF versions in final binary.
The NDK defaults to passing -Wl,--fatal-warnings to the linker because the most common type of linker warning is that something isn't defined, which means your app is broken. More warnings have been added to the linkers over the years, and some (and I believe this is the case here) are fairly innocuous.
Unfortunately, as far as I know there's no way to control the fatal warnings on a per-warning basis like you can with -Werror=warning-name with the compiler. If you're okay with disabling all of the fatal linker warnings, you can disable that feature with -Wl,--no-fatal-warnings (add it to your ldflags). If you're using ndk-build you can do this on a per-module basis with LOCAL_DISABLE_FATAL_LINKER_WARNINGS := true.
I have followed instructions to build GCC from source. The only modifications I made for the configure were:
using a binary suffix of -5.4 so that I can use the compiler as g++-5.4 for instance.
setting --configure-multilib because it wouldn't run otherwise.
I'm doing this for testing some of my code by compiling it with various different compilers. On this Centos 7 system I've got the system gcc (4.8.2) as well as clang (also compiled from source) running, and now I'd like to see 5.4 working.
Based on these instructions, inside the source code I've put these statements to make the linker happy.
#define _GLIBCXX_USE_CXX11_ABI 0
Now that the executables compile and link, I'm getting this when I run them...
/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by <program name>)
I can't quite tell here but I do know enough to see that the actual symlink /usr/lib64/libstdc++.so.6 links to the older one (/usr/lib64/libstdc++.so.6.0.19), and the one built as part of GCC 5.4 lives somewhere else (/usr/local/lib64/libstdc++.so.6.0.21). This would indicate that this program I built using 5.4 is looking at the right (old) stdlib shared lib, so something else is amiss.
The new compiler is generating code which expects to be linked to the newer libstdc++, rather than the system one. The linker finds that this expectation is not met, so it throws an error.
To fix this you will have to ensure that the correct path is being used to find and link libstdc++. There are a few options:
Use the -rpath linker option. This option adds a path to the directories to be used during dynamic linking. As it is a linker option, you pass it through using -Wl,<option> when invoking the compiler, for example:
g++ ... -Wl,-rpath=/usr/local/lib64 .... You may also need to add the path using the -L option.
Set environment variable LD_LIBRARY_PATH at runtime
See also: compiler-libstdc-version-vs-system-version
Since you are using Centos, you may also want to check out the devtoolset collection, which allows a parallel installation of newer GCC toolsets.
This would indicate that this program I built using 5.4 is looking at the right (old) stdlib shared lib
... as far as I can see, that is the wrong library, isn't it? Because it the program is built with the new g++ version, it should be using the new libstdc++, i.e. the one in /usr/local/lib64/libstdc++.so.6.0.21.
So then you might need to prepend that path to LD_LIBRARY_PATH to be able to load the program.
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.
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.