Linux static linking is dead

gccglibclinuxstatic-linking

In fact, -static gcc flag on Linux doesn't work now. Let me cite from the GNU libc FAQ:

2.22. Even statically linked programs need some shared libraries
which is not acceptable for me. What
can I do?

{AJ} NSS (for details just type `info
libc "Name Service Switch"') won't
work properly without shared
libraries. NSS allows using different
services (e.g. NIS, files, db, hesiod)
by just changing one configuration
file (/etc/nsswitch.conf) without
relinking any programs. The only
disadvantage is that now static
libraries need to access shared
libraries. This is handled
transparently by the GNU C library.

A solution is to configure glibc with
–enable-static-nss. In this case you can create a static binary that will
use only the services dns and files
(change /etc/nsswitch.conf for this).
You need to link explicitly against
all these services. For example:

 gcc -static test-netdb.c -o test-netdb \
   -Wl,--start-group -lc -lnss_files -lnss_dns -lresolv -Wl,--end-group

The problem with this approach is
that you've got to link every static
program that uses NSS routines with
all those libraries.
{UD} In fact, one cannot say anymore that a libc compiled with this option
is using NSS. There is no switch
anymore. Therefore it is highly
recommended not to use
–enable-static-nss since this makes the behaviour of the programs on the
system inconsistent.

Concerning that fact is there any reasonable way now to create a full-functioning static build on Linux or static linking is completely dead on Linux? I mean static build which:

  • Behaves exactly the same way as
    dynamic build do (static-nss with
    inconsistent behaviour is evil!);
  • Works on reasonable variations of glibc environment and Linux versions;

Best Answer

I think this is very annoying, and I think it is arrogant to call a feature "useless" because it has problems dealing with certain use cases. The biggest problem with the glibc approach is that it hard-codes paths to system libraries (gconv as well as nss), and thus it breaks when people try to run a static binary on a Linux distribution different from the one it was built for.

Anyway, you can work around the gconv issue by setting GCONV_PATH to point to the appropriate location, this allowed me to take binaries built on Ubuntu and run them on Red Hat.