October 8, 2006
I’ve been trying to build a static version of MPD, for easy deployment as part of another project I’m working on. I have arrived somewhere semi-satisfactory, but I would like any libtool/autoconf/etc. übermeisters that might happen along a question: with a project that builds a binary using automake, autoconf and libtool, how do you instruct the compile chain to build a dynamically linked binary with only dependencies you know can easily be satisfied?
Read on for details.
For a project, I need a version of MPD I can drop on a server and expect to just work. That includes all the format decoding, and the streaming to an icecast server via libshout. On a server of course, this is problematic, as you don’t install libvorbis, libmad, libshout and whatnot on a server.
So, for ease of deployment, I want to build a static version of MPD, with all these dependencies linked in. Then I’ll have one huge binary that can transcode and stream, all by itself, and all will be well.
MPD uses a lot of GNU goodness (and by ‘good’ I mean ‘mad’) in its build process: automake, autoconf and libtool. After looking around the web for a bit, it turns out that building a static MPD is trivial:
svn co https://svn.musicpd.org/mpd/tags/release-$VERSION/ mpd cd mpd ./autogen.sh ./configure --enable-static --disable-shared --disable-ao \ --enable-shout --disable-sun --disable-pulse \ --disable-oss --disable-alsa make LDFLAGS='-all-static'
Once the build process has run through, it seems that all is indeed well:
$ ldd src/mpd not a dynamic executable
However, if you look back up a couple of lines, libtool outputs a crapload of warnings of the form:
warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
Oh, not good. So, the build is static, however I am now tied to the exact version of libc I had when I compiled. Not good for deployment, I‘d much rather ’just’ have a libc with a compatible ABI, rather than the exact same one.
I’ve already seen instances of binaries I will call “static-dynamic”. They are dynamically linked, but only to libc and various other very low level linux libs. All other dependencies are rolled in statically. That way, the only requirements for the dynamic executable are “Must have a working libc installed”, which seems reasonable.
Subversion knows how to build such static-dynamic libraries:
$ ldd ~/private/svn-1.4/bin/svn linux-gate.so.1 => (0xffffe000) libgdbm.so.2 => /usr/lib/libgdbm.so.2 (0xf7fdd000) libcrypt.so.1 => /lib/tls/i686/cmov/libcrypt.so.1 (0x4e569000) libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x4d3a7000) libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0x4d27b000) libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x4d14a000) /lib/ld-linux.so.2 (0x4c8bb000)
However, Subversion’s build is extremely highly customized, and I think we just bruteforce the linking process into doing our bidding.
But surely, this kind of request is not uncommon, and the libtool folks have come up with an easy way to build such a static-dynamic binary easily with a gnu toolchain?
If anyone knows how to do this, I’m eagerly awaiting your comments. In the meantime, I have my fully static build, and I will hope that it doesn’t esplode too much.