Glibc version mismatch - c++

I have created .so library in my Ubuntu and run it on another machine. Got error:
/lib/tls/i686/cmov/libc.so.6: version `GLIBC_2.15' not found
I suppose this is general C++ library. But how to solve such problem? I can't change client configuration and that means I must to do something with my configuration. But what exactly I must do?
UPD
ldd -version returns
my machine:
ldd (Ubuntu EGLIBC 2.19-0ubuntu6.6) 2.19
host machine:
ldd (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) 2.11.1

On the target machine, run ldd --version and check the output which will tell you what version of GLIBC_ they have.
You can then roll yours back to match their version.
Statically link your executable so it doesn't need their Clib.
You can also alter your program to use the older version, once you know what it is, that is.
See this SO solution for how to do that. How can I link to a specific glibc version?

You have to make sure that you are linking to corresponding or older versions of GLIBC. GCC has flag --sysroot which allows you to define which libs are used.
This may help with details: https://sourceware.org/glibc/wiki/Testing/Builds

The point is that creating a shared library necessarily means that you need to link it to the C library (glibc, in your case). That means that calls to C library functions (which the stdc++ library does) get replaced with actual correct symbol locations in the C library.
Now, if the C library on the compiling/linking machine is not the same as on the target machine, this must fail, and hence, libc version gets checked.
Solutions is to either statically link your .so (which honestly doesn't make much sense, usually), or just correctly compile and link it for your target machine.

Beside compiling everything static, which is usually a bad
idea or does not work at all, the only way to solve the isssue
is to recompile your binary for the target platform.
Install a virtual machine or chroot with the same Ubuntu version
as on the target platform and compile there. There are also solutions
like sbuild or pbuilder/cowbuilder which automates this for Debian/Ubuntu packages.

Related

Which version libstdc++.so is used in case of multiple GCC on the same system

I am trying to install the gcc 4.8 on a system where gcc 4.3 is installed and used currently. I did some research and knew that it is possible to keep multiple versions of gcc. And it seems for me that using --program-suffix= option is the best solution for me. But my question is, can I install new gcc 4.8 directly into the place where old gcc is installed? Can libraries from both versions be mixed in the same lib directory?
Some more details: the old gcc is installed in /usr/bin, /usr/lib64. If i install new gcc directly to the same location, new libraries will be also installed /usr/lib64. Is this a problem? Will gcc compiler know which library to use when linking?
Many thanks in advance!
I'm on Gentoo, which does support installing multiple versions of GCC at the same time. The libraries end up in /usr/lib/gcc/<target>/<version>. Ubuntu seems to install them in the same place, so I'd guess this to be a fairly common setup.
While gcc can apparently figure out the correct version to link against at compile time, the version used at runtime is configured using a file in /etc/ld.so.conf.d. So it might happen that a program gets compiled against one version of the gcc libraries, but executed with another.
If the ld.so.conf.d setting prefers newer versions over older, then this is mostly all right as long as gcc guys didn't introduce a new bug into one of these libraries, and as long as the configuration causes the libraries to be fully backwards-compatible.
In this bug we had a situation where libstdc++ broke backwards compatibility with regard to some C++11 features which were experimental and enabled using a custom configure switch. These things should be rare, but they can happen.
In a related gcc bug report I learned from Jonathan Wakely:
It is totally unsupported (and unlikely to work) to mix C++11 code built with GCC 4.x and 4.y, for any x!=y
Mixing code built with 4.8.x and 4.8.y should work, and does with the default configuration.
So while this setup works in practice on Gentoo, you are on your own if you try this yourself. Particularly since I know of no clean way to ensure that resulting binaries will link against the matching libraries at runtime.
You can try whether --program-suffix affects library names as well. If so, then the SONAME of the newer version libraries should be different from that of the older, helping to get the linking right at runtime. If the library name is unaffected, you could try examining the build system whether you can either change the SONAME of the generated libraries, or have the linker set the RPATH of all the programs it links. I have no experience with either of these approaches.
On Gentoo, /usr/bin/gcc appears to be some kind of wrapper, and the actual programs end up in /usr/<target>/gcc-bin/<version>/gcc and the likes. At least judging from the package web site, Ubuntu doesn't do this for the default version of gcc, although something similar is apparently used for cross-compilation to Android. I guess that setting is the result of a matching --bindir at configure time.

How can I link to an older version of a shared library

I'm building my program on my computer, on which libtiff.so -> libtiff.so.5.
And then pushing the builds on another machine on which libtiff.so -> libtiff.so.4.
At runtime, my program exists : « error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory ».
I cannot upgrade the other machine, and I would like to avoid compiling on a virtual machine (with the same linux version than the executing machine). Therefore, I would like to force the compiler to use the libtiff.so.4 instead of libtiff.so.5.
I have libtiff.so.4 installed on my computer (as well as libtiff.so.5). How can I force the linkage with this version instead of the newer version. I thought about moving the libtiff.so -> libtiff.so.4, but I'm afraid of breaking my system if it needs the latest version (apt-get purge libtiff5 gives an error because some other package needs it).
Is it possible to link with an older (installed) version of a library? If yes, how?
And is it harmfull to change the symbolic link of libtiff.so to the older version? If not, will it solve my issue?
You can use this syntax to link to a specific version of a library:
gcc [other options] -l:libtiff.so.4
You do not need to specify a path; the usual directories are searched in order to find the library.
Note: as Michael Wild mentioned, you should have the header files for that version installed instead of the newest ones.
As others have mentioned, you can force the linker by specifying the full versioned name, or even the absolute path.
However, I would strongly advice against doing so. The problem is, that the installed headers correspond to the newer version of the library. If there have been API/ABI-breaking changes between these library versions, the program might work, crash intermittently, or if you're lucky, not work at all.
Instead you should temporarily install the development package that corresponds to the libtiff.so.4 library. If on Debian/Ubuntu or similar, this would be the libtiff4-dev package.
Specify the full path to the .so: instead of -ltiff pass /lib64/libtiff.so.4 to the linker.
You see that error when application is running. So you can either stop your application and then exrract your library tar file. Or, force to link the lib file to the newer version after you extract. In second case, you will use something like:
ln -fs libversionname libfile
Example:
ln -fs libomyapp.1.1.3 libomyapp.lib
This links your libomyapp.lib to the version specified. This can be your older vsersion or your newer version.
But as said, best way to work is to bring down your application to properly match to the expected lib functionality to work without errors or issues.

Building Boost with LSB C++ Compiler

I want to build my program with LSB C++ Compiler from the Linux Standard Base http://www.linuxfoundation.org/collaborate/workgroups/lsb. Program depends on the Boost library, built with gcc 4.4 version. Compilation fails. Is it possible to build the Boost library with LSB C++ Compiler? Alternatively, is it possible to build the Boost library with some old gcc version, what version is recommended? My final goal is to get my executable and third-party Boost libraries running on most Linux distributions.
Generally, what can be done to get better binary compatibility for Linux distributions, developing C++ closed-source application depending on the Boost library?
I've recently had call to do this, in the event that it's of use to anyone else these are the steps I followed:
Download and install the LSB SDK
Download a version of boost and extract to /opt/boost/boost_<version> (I used 1.43)
Make sure libbz2-dev is installed.
Bootstrap with
cd /opt/boost/boost_<version>
./bootstrap.sh --prefix=/opt/boost --without-libraries=python,mpi --without-icu
Edit /opt/boost/boost_<version>/project-config.jam and add the line
using gcc : : /opt/lsb/bin/lsbc++ : <cflags>-U_GNU_SOURCE <cxxflags>-U_GNU_SOURCE ;
near the top of the file. Note that this will fail if you have a using declaration in one of the other files bjam reads its configuration from, you can pass --debug-configuration to get an idea of which files it's reading.
Run
./bjam cflags=-fPIC cxxflags=-fPIC linkflags=-fPIC install
I didn't try to get either the python or MPI libraries working, nor did I try to get ICU working with the boost.regex library. The latter is probably a case of building static versions of the ICU libraries with the LSB toolset.
The -fPIC isn't strictly necessary for 32-bit Linux, but is required if you want to link static libraries into a shared library for 64-bit Linux.
The end result should be binaries in /opt/boost/lib and headers in /opt/boost/include, obviously you can modify the prefix to suit your own preferences. I still have a fair amount of work to do before I've ported all our code to the LSB, so I can't report on how well the certification process goes yet.
LSB C++ compiler is not actually a compiler. The lsbc++ executable is a wrapper around GCC compiler that is installed on your system (the actual compiler can be controlled via --lsb-cxx option). You will most likely hack into boost build system for it to call LSB wrapper instead of native gcc compiler.
So the issues that may arise are most likely not that LSB compiler can't compile the language constructs, but instead, that there are some linking issues.
For example, LSB compiler by default discards any shared libraries the code is linked against, unless they belong to LSB. This may lead to linking errors if BOOST relies on such libraries. This can be controlled via LSBCC_SHAREDLIBS environment variable, but you should make sure you ship these libs along with your product.
Another issue is that LSB falls behind GCC compiler releases (and BOOST may crawl into all dark corners of compilers). As far as I know, GCC 4.4 is not tested sufficiently, so you'd better try it with 4.3 compiler.
And Google doesn't seem to find anything related to building boost with LSBCC, so if you manage to do it, please, share your experience, for example, as your own answer to your question.

compile against libc++ statically

I wrote some custom c++ code and it works fine in ubuntu, but when I upload it to my server (which uses centos 5) its fails and says library is out of date. I googled all around and centos cannot use the latest libraries. How can I compile against the stl so that it is included in the binary and it doesn't matter that centos uses an old library?
P.S. I don't want to upload the source to the server and compile there.
In your linking step, you can simply add the "-static" flag to gcc:
http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Link-Options.html#Link-Options
You may install on your Ubuntu box the compiler that fits the version of the library on your server.
You may ship your application with libstdc++.so taken from the system you compiled it at, provided you tune the linking so it gets loaded instead of centos' one.
You may compile it statically. To do this, you should switch your compiler from g++ to
gcc -lgcc_s -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
Choose whatever you like. Note that approaches (2) and (3) may arise the problem of dependencies: your project (particularly, the stdc++ implementation that, being statically linked, is now a part of your app) may require some functions to present in the system libraries on centos. If there are no such functions, your application won't start. The reason why it can happen is that ubuntu system you're compiling at is newer, and forward compatibility is not preserved in linux libraries.

Can I use a shared library compiled on Ubuntu on a Redhat Linux machine?

I have compiled a shared library on my Ubuntu 9.10 desktop. I want to send the shared lib to a co-developer who has a Red Hat Enterprise 5 box.
Can he use my shared lib on his machine?
First point: all of the answers regarding compiler version seem misguided. What's important are the linkages (and the architecture, of course).
If you copy the .so file over to the start system (into its own /usr/local/* or /opt/* directory, for example) then try to run the intended executable using an LD_PRELOAD environment settings. If the linker (ld-linux.so) manages to resolve all the symbols between the two then the program should load and run.
So it should be possible, and reasonably safe (so long as you're not over-writing any of the existing system libraries and just using LD_* /etc/ld.so.preload (in a chroot?) magic to link the target executables to this library.
However, I think it's a bad idea. You have a package management issue. Both Ubuntu and Red Hat have fine package management tools. Use them! (Note the proper place to ask questions about package management would be ServerFault or SuperUser, definitely not SO).
Unlikely: you wouldn't have asked this question if it just worked, would you?
According to DistroWatch, Ubuntu 9.10 uses glibc-2.10.1, while RHEL-5.4 uses glibc-2.5. This means that if your library references any symbols with versions GLIBC_2.6 and above, it will not work on RHEL-5.
You can tell whether you use any such symbols (and which ones) with:
readelf -s /path/to/your/library.so | egrep 'GLIBC_2.([6-9]|10)'
If the output is non-empty, then the library will not work on RHEL-5.
You might be able to build a library compatible with RHEL-5 by using autopackage.
I join to Xinus. IMHO compiler, in case of Ubuntu and RHEL, it will be gcc, is tightly coupled with glibc. So if on both machines it's same, than most probably it caa run.
But why guessing, do a small test drive (main with couple of lines) and if it's running than there's a good chance that a bigger program can run on a "hostile" environment :)
The best solution is to give your code to your co developper,
and let's compile it !!!!
You have several solution
Upgrading his gcc to the same version as your
Install his gcc version on your computer and compile it
You must check if you both work on the same architecture 32 bits or 64 bits.
My opinion is that you can have some problems , because you probably do not use the same glibc
.
Yes, it is possible. Provide a static library to your partner and keep your gcc to the same or compatible version. you can check my post here: https://zqfan.github.io/2021/07/01/cpp-static-library/