To create easily distributable C++ executables for Linux, the binaries’ dependencies should be minimized. In order to reduce an executable’s dependencies, a binary can be created by linking static libraries. Static linking can be used with most libraries, including the C++ standard library, but it is not preferred with the standard system C library, glibc. Previously, we discussed how static executables can be used for the purpose of special-case test executables, but static linking glibc should be avoided for the purpose of creating distributable binaries. To create distributable binaries, the executable can be built on an system with the oldest version of glibc possible; glibc is not forwards-compatible, but it has very good backwards compatibility. In this post, we describe how Docker can help to efficiently build C++ executables locally or in the cloud with an old version of glibc.
A Linux distribution with one of the oldest available glibc libraries on DockerHub is CentOS. The centos:5 image has glibc version 2.5. By building on this Docker image, the executable will run on an operating system with glibc 2.5 or later.
The build environment image we created has build tools like CMake, Python, and Ninja, but it also has a newer version of the GCC compiler. By installing Dev Tools, a newer toolchain with GCC 4.8 is available in /opt. This compiler generates more optimized binaries than the version available in the package manager, and it has better support for newer language features, like the C++11 standard. Statically linking libstdc++ avoids version compatibility issues.
The Docker image can be used to efficiently build the distributable executables on a newer Linux system or Windows or Mac OSX. Also, the same Docker image can be used for continuous integration testing in the cloud, and it is even possible to use the continuous integration artifacts for distribution.