Linux static linking is dead?

Viewed 43533

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;
6 Answers

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.

Static linking is back on the rise!

  • Linus Torvalds is in support of static linking, and expressed concern about the amount of static linking in Linux distributions (see also this discussion).
  • Many (most?) Go programming language executables are statically linked.
    • The increased portability and backward compatibility is one reason for them being popular.
  • Other programming languages have similar efforts to make static linking really easy, for example:
    • Haskell (I am working on this effort)
    • Zig (see here for details)
  • Configurable Linux distributions / package sets like NixOS / nixpkgs make it possible to link a large fraction of their packages statically (for example, its pkgsStatic package set can provide all kinds of statically linked executables).
  • Static linking can result in better unused-code elimination at link time, making executables smaller.
  • libcs like musl make static linking easy and correct.
  • Some big software industry leaders agree on this. For example Google is writing new libc targeted at static linking ("support static non-PIE and static-PIE linking", "we do not intend to invest in at this point [in] dynamic loading and linking support").
Related