How to Distribute C++11 Shared Library on Centos6

How to distribute c++11 shared library on centos6

Can I compile a c++11 shared library on centos6 and have it work on standard centos installs ?

If you can't build your code with the standard CentOS 6 g++/glibc/libstdc++, then no, it's not going to run on standard CentOS 6 installs.

The CentOS distro is for long term support (LTS). Critical bugs get fixed with updates, but software otherwise doesn't change, usually. This is a feature. Even with 3rd party repositories (e.g. EPEL), the available software for CentOS isn't really recent.

Can I compile a c++11 shared library on ubuntu 13.10, and have it load on centos6 (and older ubuntus) ? how ?

If you can compile it using the g++ 4.4 toolchain, sure. In this case, you cannot use a more advanced compiler. A quick search on Ubuntu's 12.04 LTS package list shows libstdc++6-4.5-dbg using a version of libstdc++.so.6 which would be backward incompatible, based on error messages above.

How can I distribute my c++11 shared library on centos6 ?

As you've shown above, you'll have at least one updated dependency (libstdc++.so.6) that you'll need to ship with your library, and install in some odd location, with it's attendant headaches (LD_LIBRARY_PATH, what happens to any other C++ plugins, etc.). And update at some point.

Some enterprise users would object to something like this, mainly because it doesn't mesh well with the existing OS.

Statically linking in dependencies (like in Ali's answer with the Developer Toolset below) could work also. It's also not without problems (updates to dependencies again), but might be the best chance for your code to work on CentOS 6.

I see from comments to Ali's answer, that devtools 1 (gcc 4.7.0) didn't work, making it unlikely that devtools 1.1 would work. So it seems you do need C++11 support up to the level of gcc 4.8 in this case.

How can I deploy a C++11 program (with dependencies) on CentOS 6, whose GCC is C++03?

Actually, you can distribute a program compiled with a newer g++ compiler on a vanilla CentOS 6 platform. There are several ways to do this: The easiest is to use the DevToolset 3, which will give you g++ 4.9.2 (the dev toolset 2 will give you gcc 4.8.2). Then, just compile your application with this g++. When distributing your software, you need to make sure to also ship the libstdc++.so that is being shipped with g++ 4.9. Either set the LD_LIBRARY_PATH so it gets picked up on startup, or set the RPATH to tell your executable where to look first for libraries.

Essentially, you can do this also with newer compilers, but then you first need to compile the compiler itself. If you don't want to compile a compiler first, go with a respective dev toolset and you should be fine.

Yes, you can also try to statically link libstdc++.a. Search for the option -static-libstdc++:

When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.

But if you statically link, you will not get any security updates etc. Granted, you will not get the updates, if you ship libstdc++.so on your own as well, but incremental updates maybe easier.

And with respect to running your application: The rule of thumb is: Compile on the oldest platform you need to support, then your binaries (with self-shipped libstdc++ and other required libs) will likely work also on newer versions. That is, if you compile on CentoOS 6, and it works, then you can expect it to also work on CentOS 7. On a related subject, this is exactly the reason why for instance AppImage and related solutions recommend to build on an old system.

How to run an old binary on modern GNU/Linux distribution?

Is there a reliable way

No. :p

Is there a way to run an old binary on modern Linux without containers or virtual machines?

You can run the program using the old linker and with the library path. When you have a old system chroot, you can:

LD_LIBRARY_PATH=$PWD/lib $PWD/lib/ld-linux-x86-64.so.2 ./my-program

But note that if the ./my-program will then run anything via fork+exec, there may be problems. You may set PATH to the locations from chroot, but still the interpreter could be the wrong one. So it "generally works" if it's a simple program.

Anyway if not with docker or plain chroot, you might want to see proot program.

Multiple glibc libraries on a single host

It is very possible to have multiple versions of glibc on the same system (we do that every day).

However, you need to know that glibc consists of many pieces (200+ shared libraries) which all must match. One of the pieces is ld-linux.so.2, and it must match libc.so.6, or you'll see the errors you are seeing.

The absolute path to ld-linux.so.2 is hard-coded into the executable at link time, and can not be easily changed after the link is done (Update: can be done with patchelf; see this answer below).

To build an executable that will work with the new glibc, do this:

g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

The -rpath linker option will make the runtime loader search for libraries in /path/to/newglibc (so you wouldn't have to set LD_LIBRARY_PATH before running it), and the -dynamic-linker option will "bake" path to correct ld-linux.so.2 into the application.

If you can't relink the myapp application (e.g. because it is a third-party binary), not all is lost, but it gets trickier. One solution is to set a proper chroot environment for it. Another possibility is to use rtldi and a binary editor. Update: or you can use patchelf.



Related Topics



Leave a reply



Submit