Who determine GLIBCXX_version when build a binary using g++? - c++

I am building an self-made shared library using G++ 4.9.3 on Centos 6.8.
This library uses boost::interprocess::file_lock and version of boost is 1.41.0.
I am not working on multiple environment.. I just use a device and I've never changed build environment after I built the library.
When I build library, g++ build it well. But when I run it by linking with an binary, it shows
"./a.out: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by ./libmylib.so)".
So, I checked which versions supported by the libstdc++ and it show it doesn't support GLIBCXX upper than 3.4.13.
GLIBCXX_3.4.13 is the latest version of /usr/lib64/libstdc++.so.6 supports.
Even though I am working on a device and its libstdc++ doesn't support GLIBCXX_3.4.15, the library build from my device requires GLIBCXX_3.4.15.
And another binaries doesn't require GLIBCXX_3.4.15 even if I use same compiler(g++4.9.3). They just work well.
How can the library notice it should use GLIBCXX_3.4.15?
Is it differed by source code?
Does compiler tell the library such as "you require to use GLIBCXX_3.4.15 because you use some special grammar in your code"?
I want know who determine which version of GLIBCXX to use for a binary.

It depends on the version of GCC, the compiler flags, and the source code. Symbols such as GLIBCXX_3.4.15 are only referenced if a specific feature is used in a program. The list of features for this particular symbol version is rather large. You can get a sense of what features are relevant using this command (which you have to run against the newer libstdc++, i.e. the one that comes with GCC 4.9):
$ readelf -sW libstdc++.so.6 | awk '/#GLIBCXX_3.4.15/{print $8}' \
| sort -u \
| c++filt
If you want to run your program with the unmodified libstdc++.so.6 version that comes with Red Hat Enterprise Linux or CentOS, you can use Developer Toolset (which is also available as a supported part of Red Hat Enterprise Linux. Developer Toolset avoids dependencies on newer symbol versions by using the old (C++98 era) C++ ABI and providing statically linked copies of functions which are not part of the system libstdc++ version for the particular target operating system version.

Related

Versions of GLIBC

I have created c++ application in Ubuntu machine. I have copied binary to Centos machine. Got error:
/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
I decided to check which versions of glibc I have in my machines with help of ldd --version command:
Ubuntu: 2.23
Centos6.9: 2.12
Why CentOS cmplains regarding GLIBCXX_3.4.21, while Ubuntu owns glibc version 2.23?
The symbols like GLIBCXX_3.4.21 are generated by the compiler to mark which version of the C++ library that the compilation was used with (in particular, non-inline functions called from header-files & template functions). This is the libstdc++ library, not glibc.
The version that you are looking for is your libstdc++ - and this is one of the interesting problems with C++, the template library tends to change every now and again, so a function may be declared as unsigned int func(), and later someone decides to change it to size_t func(). No difference in 32-bit machines, but for 64-bit machines it DOES make a difference, and using the "wrong" version will lead to problems with the size of the return value.
There are a few different solutions (and this is not a complete list):
Make sure you use the same version of libstdc++ on both machines.
Compile the code on the target machine.
Use static libstdc++
This a great - I used the -static option in the link and it solved by problem also.

Relationship between GLIBCXX(libstdc++.so.6) and gcc version

[Situation]
I'm developing a c++ library. I had a issue with the GLIBCXX version.
Before, I developed on version machine GLIBCXX_3.4.22.
But my library is not working on the target machine which has GLIBCXX_3.4.19.
So, I downgraded gcc version from 5.2.x to 4.8.x and GLIBCXX version from 3.4.22 to 3.4.19.
It successfully ran on the target machine.
But my development machine(ubuntu) boot fails because other libraries can't find GLIBCXX 3.4.22 version which is already linked to that version.
So, I re-installed GLIBCXX 3.4.22 but gcc version is still 4.8.5.
[Question]
Does my library compiled on gcc-4.8.5 not use GLIBCXX_3.4.22 version? Is it fine to develop on this environment (gcc 4.8.5, GLIBCXX_3.4.22)?
What is the relationship between gcc(compile) version and GLIBCXX(GLIBC) version on the linux machine.
Where can I check the correct version compatibility mapping information between gcc and GLIBCXX(GLIBC)?
libstdc++ (which is where the GLIBCXX_* versioned symbols are from) has been ABI compatible from GCC 3.4.0 to now.
Your library will use the latest symbol versions from libstdc++ at the time of compile. The compiler version does not matter, except
GCC 5.1 added C++11 support with a "dual ABI" in libstdc++. Code compiled in C++11 mode will use symbols with the [abi:cxx11] tag, and that may not interoperate with code compiled without C++11 (whether from an older compiler without C++11 support, or a newer compiler set to use an older standard).
https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
If you need to build binaries that run on older systems, I would recommend setting up an older distribution inside a container and building in there, with all old libraries. This way, nothing newer from your development system can leak into them.

GCC upgrade - GMP version causing issues

I'm trying to update GCC on a particular linux machine I have, to a version for which there is no package available.
I run the configure script and it complains about the version of GMP:
# ../gcc/configure
checking build system type... i686-pc-linux-gnu
[snip]
checking for the correct version of gmp.h... no
configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.
Try the --with-gmp, --with-mpfr and/or --with-mpc options to specify
their locations. Source code for these libraries can be found at
their respective hosting sites as well as at
ftp://gcc.gnu.org/pub/gcc/infrastructure/. See also
http://gcc.gnu.org/install/prerequisites.html for additional info. If
you obtained GMP, MPFR and/or MPC from a vendor distribution package,
make sure that you have installed both the libraries and the header
files. They may be located in separate packages.
However, when I check gmp.h it shows:
/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */
#define __GNU_MP_VERSION 4
#define __GNU_MP_VERSION_MINOR 2
#define __GNU_MP_VERSION_PATCHLEVEL 1
and RPM reports the following:
# rpm -q --qf "%{VERSION}\n" gmp
4.2.1
# rpm -q --qf "%{VERSION}\n" gmp-devel
4.2.1
so both library and headers seem to be of a correct version to me (confusingly, the numbering of the .so file for libgmp seems to have exactly nothing to do with the version number... that is showing as
libgmp.so -> libgmp.so.3.4.1
Does anyone know why this might be failing? Those are the only two gmp packages installed on this machine and they are in standard /usr/include and /usr/lib locations, so they should be on the search path already.
Please read Installing GCC:
The difficult way, which is not recommended, is to download the sources for GMP, MPFR and MPC, then configure and install each of them in non-standard locations, then configure GCC with --with-gmp=/some/silly/path/gmp --with-mpfr=/some/silly/path/mpfr --with-mpc=/some/silly/path/mpc, then be forced to set LD_LIBRARY_PATH=/some/silly/path/gmp:/some/silly/path/mpfr:/some/silly/path/mpc/lib in your environment forever. This is silly and causes major problems for anyone who doesn't understand how dynamic linkers find libraries at runtime. Do not do this. If building GCC fails when using any of the --with-gmp or --with-mpfr or --with-mpc options then you probably shouldn't be using them.
Just run ./contrib/download_prerequisites and save yourself a lot of time and pain.
Turns out that "Building GCC requires GMP 4.2+" is insufficiently detailed. Digging into configure, it's actually checking:
#if GCC_GMP_VERSION < GCC_GMP_VERSION_NUM(4,2,3)
choke me
#endif
i.e. GMP 4.2 .3 or greater, so my 4.2.1 wasn't cutting it.

Pyinstaller GLIBC_2.15 not found

Generated an executable on Linux 32-bit Ubuntu 11 and tested it on a 32-bit Ubuntu 10 and it failed with a "GLIBC_2.15" not found.
Cyrhon FAQ section says:
Under Linux, I get runtime dynamic linker errors, related to libc. What should I do? The executable that PyInstaller builds is not
fully static, in that it still depends on the system libc. Under
Linux, the ABI of GLIBC is backward compatible, but not forward
compatible. So if you link against a newer GLIBC, you can't run the
resulting executable on an older system. The supplied binary
bootloader should work with older GLIBC. However, the libpython.so and
other dynamic libraries still depends on the newer GLIBC. The solution
is to compile the Python interpreter with its modules (and also
probably bootloader) on the oldest system you have around, so that it
gets linked with the oldest version of GLIBC.
and
How to get recent Python environment working on old Linux distribution? The issue is that Python and its modules has to be
compiled against older GLIBC. Another issue is that you probably want
to use latest Python features and on old Linux distributions there is
only available really old Python version (e.g. on Centos 5 is
available Python 2.4).

How can I work out why a specific version of a library is in the dependencies?

I'm building a large C++ project using cmake on ubuntu 12.04 and then taking the resulting binary package and trying to run it on ubuntu 11.04. However the program fails saying it needs glibc version 2.14 but can only find up to version 2.13.
How can I find out exactly why glibc=>2.14 is required?
Unlike most libraries, glibc versions its symbols. Every symbol is tagged with a value (e.g. "GLIBC_2.3.4") representing the version of the library where it's interface was last changed. This allows the library to contain more than one version of a given symbol and support binaries compiled against older versions while preserving the ability to evolve. You can see this detail with objdump -T /lib/libc.so.6.
Basically, something in your app was linked against a symbol that was changed since 11.04. Try objdump -T on your binary and see what tags it's looking for.
But broadly, backwards compatibility doesn't work like that in Linux. If you want something to run on older software, you should build it on older software. It's possible to set up a backwards-compatible toolchain on more recent distros, but it's not the default.
When you build your C++ project, it will link to the version of the glibc library on your 12.04 installation. What are the linker options in your build command?
Without knowing exactly what you are building, I'd say you might be better off building on 11.04 and then running on 12.04.