CentOS Revisited – How Old is Too Old?

I recently started working with CentOS 5.11 as an operating system on which to build Python wheels for Linux. I wrote about why I used CentOS 5.11. The oversimplified reason is because it’s old. After using it for a while, I’ve started to wonder, how old is too old?

Why CentOS 5.11, Again?

To understand why the authors of PEP 513 recommend CentOS 5.11, we must briefly consider a subject that Python programmers can usually ignore—binary dependencies.

When one builds a binary on Linux (or any system, for that matter), it comes with dependencies on runtime libraries. Even a simple “hello world” program will depend on the C runtime library (glibc if you build with GCC). The benefit of building binaries on an older Linux is that the runtime dependencies—particularly glibc—are likely to be present on newer systems. The reverse is not true. If you link your binary to a brand new glibc, it won’t be able to run on older systems because they don’t have the glibc needed to load your binary.

CentOS 5.11 was released on the last day of September 2014 (according to DistroWatch.org), so it’s only 1½ years old. But it’s a derivative of Red Hat which is a notoriously conservative distro. To give you some idea of how conservative it is, CentOS 5.11 provides Python 2.4.3 which was released in 2006, eight years before CentOS 5.11, and almost ten years before PEP 513 was released. CentOS 5.11 is a snapshot of what was state-of-the-art some years ago.

There’s nothing wrong with a Linux distro that chooses to be this conservative. If you want modern software, or bleeding edge, there are distros for that. RedHat Enterprise Linux (and thus CentOS) is not one of them.

CentOS 5.11’s “old school” attitude makes it a very safe bet that the versions of it base libraries (like glibc) will appear on other Linux distros, and that’s why it’s a good choice for building Linux wheels.

Great! Are There Any Downsides?

Yup.

The point of using an older Linux is to ensure that runtime libraries are not too new to appear on other Linuxes. But what if the opposite happens?

What happens if a library on CentOS 5.11 is so old that some of the Linux world no longer supports it? That’s what happened when I tried (for one of my clients) to wrap a Fortran library with Python and distribute it as a wheel. I built the Fortran code with the default GFortran/GCC version which was 4.1.2.

The resulting binary has a dependency on libgfortran.so.1. This library has become old enough that it’s not always easy to install. For instance, it’s not in the repositories of the very popular Ubuntu 14.04 LTS.

That’s particularly surprising when you consider that Ubuntu 14.04 LTS was released about six months before CentOS 5.11. Despite this, the former had already dropped support for the default libgfortran of the latter.

This is a good example of how CentOS 5.11 helps to avoid dependency problems, but doesn’t entirely solve them. In short, caveat munitor (builder beware).

How I Resolved the libgfortran.so.1 Dependency

I was able to build a wheel for my client that solved the specific libgfortran.so.1 dependency problem described above. I set the binary’s rpath to include the binary’s directory ($ORIGIN) and shipped libgfortran.so.1 as part of the Python wheel in the same directory as the custom shared library. The relevant Makefile portion looks like this—

gfortran -shared               \
         -fPIC                 \
         -Wall                 \
         -Wl,-rpath,'$$ORIGIN' \
         -o my_library.so      \
         $(OBJS)

And running ldd on the resulting library shows that the binary uses the local libgfortran.so.1 as intended—

$ ldd libmy_library.so
   linux-vdso.so.1 => (0x00007ffd0d93d000)
   libfftw3.so.3 => /usr/lib/x86_64-linux-gnu/libfftw3.so.3 (0x00007f1b97297000)
   libgfortran.so.1 => /home/philip/miniconda2/lib/python2.7/site-packages/my_library/bin/./libgfortran.so.1 (0x00007f1b97000000)
   libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1b96cfa000)
   libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1b96ae4000)
   libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1b9671f000)
   /lib64/ld-linux-x86-64.so.2 (0x00007f1b9f8b9000)

Matplotlib Advice

A little bonus tip: if you want to install matplotlib on CentOS 5.11, save some time and read this Stack Overflow comment by Byron Dover first.

Leave a Reply

Your email address will not be published.