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.
Related
Say I have a C++ binary that was compiled with a version of gcc say 4.4.x, which is used on a client linux box.
If I want to upgrade my compiler to use a newer one, say 4.9.3 (because I want to use C++11):
What kind of things would need to be upgraded on the client box to run this new binary? (e.g. .so libraries)
And how would one find this out?
What kind of things would need to be upgraded on the client box to run this new binary?
You will need to ship two shared libraries with your application: libgcc_s and libstdc++. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html for more details.
You can ship these libraries in the same directory with your executables if you link using $ORIGIN. See https://stackoverflow.com/a/4742034/412080 for more details.
And how would one find this out?
Run ldd and readelf -d on your executables to see what libraries they need.
I'm guessing from the fact that you mention GCC 3.4 that your client system is running RedHat/CentOS/Scientific Linux 4 which is so old that even Red Hat ended support for it three years ago. If you were running any newer version then you would have been able to take advantage of the Developer Toolsets which include a modified version of GCC that statically links newer parts of the standard library into your binary so that it can run on legacy systems without newer glibc/libstdc++ runtimes.
There are two mechanisms to test compatibility of shared libraries:
The SONAME: a canonical name for the library that is used by the linker to reference the library. You can query the list of required libraries for every ELF object (executable or library) with the ldd command, and you need to do this recursively for each referenced library to get a full list of libraries needed.
The symbol version information. This is an additional constraint that allows adding functionality to existing libraries by introducing version requirements per symbol used -- a program only using symbols that have existed for ages will require a lower minimum version of the library than one that uses new functionality.
Both of these need to be fulfilled in order for the program to run.
The typical approach of Linux distributions is to keep a mapping of SONAME to package name (as multiple versions differing in SONAME can be installed concurrently), and a table of versioned symbols to the package revision these were introduced. The appropriate package development tools for your distribution should be able to create a list of dependency specifications that matches your program's requirements; if they fail to do so because symbols are unknown, it is likely that this version cannot be supported on that release of the distribution.
An alternative could be to link statically all libraries (notably libstdc++) other than the libc (and libm and libdl if you use them); then the produced ELF executable depends only of the libc; however, with ancient enough kernels or libc (on the target machine) even that might fail to work...
For details, read Drepper's paper: How To Write Shared Libraries
I've compiled a Linux package on ubuntu 12.04 which uses boost and on this system i have boost 1.46. I tried to run the compiled release on another system and it complains that it can't find libboost_system.so.1.46.1. That system has boost 1.49 installed. How do I compile so that the program uses whatever version of boot exists instead of the specific version on the development machine.
You cannot expect your program to work with a different version of the library.
The fact that there are /different/ versions implies that they're /not the same/.
As mentioned, either
statically link to your specific version, or
you can ship the shared libraries (as long as you put them in a app-specific location and make sure you find them at runtime). Incidentally, see the second example here: How to compile boost async_client.cpp for the relevant linker options to use a custom library (it assumes the same location is to be used at runtime (rpath)
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.
I'm writing a cross-platform application which is not GNU GPL compatible. The major problem I'm currently facing is that the application is linked dynamically with glibc and libstdc++, and almost every new major update to the libraries are not backwards compatible. Hence, random crashes are seen in my application.
As a workaround, I distribute binaries of my application compiled on several different systems (with different C/C++ runtime versions). But I want to do without this. So my question is, keeping licensing and everything in mind, can I link against glibc and libstdc++ statically? Also, will this cause issues with rtld?
You don't need to.
Copy the original libraries you linked against to a directory (../lib in this example) in your application folder.
Like:
my_app_install_path
.bin
lib
documentation
Rename you app for something like app.bin. Substitute your app for a little shell script that sets the enviroment variable LD_LIBRARY_PATH to the library path (and concatenate the previous LD_LIBRARY_PATH contents, if any). Now ld should be able to find the dynamic libraries you linked against and you don't need to compile them statically to your executable.
Remember to comply with the LGPL adding the given attribution to the libraries and pointing in the documentation where the source can be downloaded.
glibc is under the LGPL. Under section 6. of LGPL 2.1, you can distribute your program linked to the library provided you comply with one of five options. The first is to provide the source code of the library, along with the object code (source is optional, not required) of your own program, so it can be relinked with the library. You can alternatively provide a written offer of the same. Your own code does not have to be under the LGPL, and you don't have to release source.
libstdc++ is under the GPL, but with a major exception. You can basically just distribute under the license of your choice without providing source for either your own code or libstdc++. The only condition is that you compile normally, without e.g. proprietary modifications or plugins to GCC.
IANAL, and you should consider consulting one if you need real legal advice.
Specifying the option -static-libgcc to the linker would cause it to link against a static version of the C library, if available on the system. Otherwise it is ignored.
I must question what the heck you are doing with the poor library functions?
I have some cross platform software as well. It runs fine on Linux systems of all sorts. Build with the oldest version of software that you want to support. The glibc and libstdc++ libraries are really very backward compatible.
I have built on CentOS 4 and run it on RHEL 6 beta. No problems.
I can build on stable Debian and run it on testing.
Now, I do sometimes have trouble with some libraries if I try to build on, say old Debian and try to run it on CentOS 5.4. That is usually due to distribution configuration choices that are different, like choosing threading or non-threading.
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.