statically linking shared libraries with libtool

I run a lot of experiments on our local cluster.  Unfortunately, over time, the library versions on the cluster tend to diverge from those on my local machine. As a result, I’ve gotten used to seeing this:

/usr/bin/python: /lib/x86_64-linux-gnu/ version `GLIBC_2.17' not found 
(required by /home/power/w/spartan/build/.libs/

If I was using Go this wouldn’t be a problem, as they statically link everything.  Despite the crowd of people who think shared libraries are the bees knees, I agree with this approach — it’s just far simpler than trying to deal with errors like the above. You can solve this most of the time by simply statically linking everything (–enable-static).  Sadly, if you’re trying to build a shared library (in my case, an extension module for Python), you can’t really go this route. (Statically linking Python API calls into a library which is then hoisted into Python is going to end very, very badly). What am I supposed to do with this error? If you trawl around the web, you find that depending on the exact error, you should either:

  • find an old version of GLIBC and link against that
  • insert assembly directives to indicate the old symbol

If you happen to have a single symbol that’s pulling the newer version, the latter is an easy fix (though it’s a bit annoying to ensure you’ve always got the directive declared before you use a function). If you’ve somehow acquired a dependency on the whole library things become more annoying. In my case, this dependency seemed to result from the chain: -> -> ->

Oddly enough, depending directly on libstdc++ isn’t the problem. If I remove the dependency on libspartan (just linking directly against all of the objects), we’re fine:

ldd -v .libs/

        Version information:
       (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/
       (GCC_3.0) => /lib/x86_64-linux-gnu/
       (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/
       (GLIBC_2.15) => /lib/x86_64-linux-gnu/
       (GLIBC_2.14) => /lib/x86_64-linux-gnu/
       (GLIBC_2.4) => /lib/x86_64-linux-gnu/
       (GLIBC_2.3.2) => /lib/x86_64-linux-gnu/
       (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/
       (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/
       (GLIBC_2.3.2) => /lib/x86_64-linux-gnu/
       (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/
       (GLIBCXX_3.4.14) => /usr/lib/x86_64-linux-gnu/
       (GLIBCXX_3.4.15) => /usr/lib/x86_64-linux-gnu/
       (GLIBCXX_3.4.10) => /usr/lib/x86_64-linux-gnu/
       (CXXABI_1.3) => /usr/lib/x86_64-linux-gnu/
       (GLIBCXX_3.4) => /usr/lib/x86_64-linux-gnu/

Notice, no reference to GLIBC_2.17. Luckily in this case there’s a simple solution: make all of the helper libraries into convenience libraries. This causes those libraries to be statically linked and avoids pulling in the extra dependencies:

# old

# new 

If we weren’t lucky — we’re actually using the symbol that’s from a later version — than we can force static linking of your dependent library; you do this by listing it explicitly by name in your LIBADD variable:

_spartan_wrap_la_LIBADD = -module -lrt /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a

libtool will complain that linking against a static library isn’t portable (which is true), but it should work correctly as long as the static library was built with -fPIC.

statically linking shared libraries with libtool

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s