How statically linked programs run on Linux
eli.thegreenplace.net
eli.thegreenplace.net
The reason most C++ programs ran on all Windows computers (and with such a tiny file size) is Windows shipped with the common libraries (C++ runtime) required to run the programs.
When Borland came out with Delphi they wanted Microsoft to include some of their own common libraries to reduce the footprint of the executable -- but Microsoft said no, meaning Delphi's executables had to have everything linked into it statically, resulting in files that were an order of magnitude bigger. Aside from the stigma from larger file sizes in an era (the 90s) when this mattered, they arguably came out ahead in this department as Delphi by default avoided "DLL hell" (until MS solved it more or less definitively with Windows 2000) and would run anywhere, on anything, with no additional dependencies.
Incidentally, cross-compiling static binaries is a hugely productive feature of Go.
But if you're trying to produce commercial shippable software (what used to be called shrinkwrap), you're not going to fit in as easily with a package management system. Your binaries will probably need updating when the shared libraries update; that's a major headache. And this is one of the reasons why there hasn't been much of a commercial market in software for Linux. Everything generally works much more smoothly if your only dependencies are glibc and a handful of other bits.
On the other hand that is also a bit silly; if the box is owned then all else is peanuts;
I was actually surprised that the VDSO [1] page was missing from that. For those unfamiliar... the Linux kernel selects the best system call implementation for the current system and exports a special page to user-space. It also provides a few specific additional routines (generally related to getting the current time without having to jump in and out of the kernel).
I'm not advocating for this approach, but it's there and can have a big impact. As a fun exercise, I just checked how much impact this has on my VM right now...
timetest.c:
#include <stdio.h>
#include <time.h>
int main(void) {
for (int i = 0; i < 1000000000; i++) {
time(NULL);
}
}
gcc timetest.c -o timetest -std=c99 && time ./timetest real 0m3.589s
user 0m3.588s
sys 0m0.000s
gcc timetest.c -o timetest -std=c99 -static && time ./timetest real 0m41.436s
user 0m16.900s
sys 0m24.456s
[1] http://en.wikipedia.org/wiki/VDSO> all kinds of features in the libc (locale (through iconv), NSS, IDN, ...) require dynamic linking (...)
These are all features which have been shoehorned into libc on Linux, but only work when it's a shared library because they rely on shared state. I would argue a cleaner way of implementing them would have been as services, but alas, you have what you have.
Those features use dynamic linking so that they can load only the necessary implementations at runtime - eg if you aren't using LDAP name lookups, then the NSS won't load the library that does LDAP name lookups.
But of course you could still easily mmap() a file to achieve the same thing (even from the shared library .init functions).
I can understand that the shared section might be abused by goofy programmers ("Hey guys! We don't need to open a file for storage, we can just build it into the DDL!") ... but is there a reason you think it's a bad idea otherwise?
The above sentence could be misconstrued.
I assume when you say static libraries, you mean standard shared libraries (i.e. those listed when you run ldd). Not statically-linked libraries?
If you want to share state between processes, the library must explicitly set up a shared mapping - but of course a statically linked library can do this just as well.
A statically-linked library won't share any state with other users of the library. It's statically-linked into the binary. State will be shared only with the instances of the same binary.
[1]: http://sta.li
Unfortunately there is a lot of hostility to making binary distribution easier on Linux because of the "you should be using shared libraries and why would you ever want to distribute binaries when you can just distribute the source code?" attitude that prevails.
Having said that, GCC did finally add a real option to link statically (i.e. not `-static`) a few years ago. And I believe the linker finally supports symbol versioning.