Compile static copy of Midnight Commander

I work with quite a few clusters, and in trying to get batch jobs running, I tend to generate many tiny files which are usually almost identical and almost useless.  The rare exception is the lone non-identical file, which is invariably critical in solving a problem.  Run a test job ten or fifty times, and a directory can fill up rapidly.  ls and rm get annoying for large directories.  So, I like to have a text-mode file manager on hand to help sort through, mark, and blow away useless cruft while identifying useful cruft.

I grew up with Midnight Commander, and I’m a creature of habit, so I set about trying to compile a copy of mc statically, so I only had to do it once for all the x86_64 clusters I deal with (and incidentally dodge the problems of differing versions of dependency libraries, lack of development libraries, and so on).  Turns out that’s not so simple.  One would hope that

./configure --disable-shared --enable-static

would do it.  Not so much, at least not with mc.  The mc binary would still be huge, but would still contain dynamic links to glib, pcre, curses, and a host of other things.

Various mailing list posts circa 2002 were unhelpful, especially those of the form “edit the Makefiles and add -static to LIBS“.  Though a scientist, after a few hours the scientific process breaks down and I make more than one change at once.  In other words, the following, while it worked, probably contains thoroughly unnecessary duplication of flags:

./configure --with-glib-static --without-x --disable-shared --enable-static \
    CC='gcc -static -static-libgcc -fno-exceptions' \
    CXX='g++ -static -static-libgcc -fno-exceptions' \
    LDFLAGS='-Wl,-static -static -lc' \
    LIBS='-lc'

The keys to success were:

  1. Specifying CC, CXX, LDFLAGS, and LIBS as command-line arguments to configure rather than environment variables.  In the latter case, configure only seems to honor them occasionally.
  2. Putting the static linkage options into what will run as the compiler.
  3. When -static-libgcc is specified, an -fno-exceptions option may be necessary to avoid pulling in stack unwinding code that seems to be available only in a shared library.
  4. Adding LIBS='-lc', because otherwise LDFLAGS='-Wl,-static' seemed to cause the linker to miss the crt0 startup routines, which a tailing '-lc' fixes.

That generated a completely static executable.  Installation wasn’t terribly straightforward, since I didn’t want to install a second copy of mc on my development box (even in my home directory), tar it up, and then clean it up.  (I don’t claim this is logical; just that I simply didn’t want to do it after spending far too long trying to get a static executable.)   I wound up pulling everything from my (properly installed, local) copy of mc, both from /etc/mc and /usr/share/mc, pooling it in one directory (~/etc/mc) on the clusters, and pointing mc to it with MC_DATADIR=$HOME/etc/mc (via an export MC_DATADIR=... in my .bashrc).

It should be noted that this hack depends on the presence of static link libraries for glib, ncurses/slang, and perhaps pcre.  That took a little doing as well (since my development box runs Gentoo, that meant twiddling with USE flags and re-emerging some packages).

Advertisement
Explore posts in the same categories: Computing

Tags: , ,

You can comment below, or link to this permanent URL from your own site.

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Connecting to %s


Follow

Get every new post delivered to your Inbox.