Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Tue, 24 Jul 2012 19:34:46 -0400
From: Rich Felker <>
Subject: Re: empty lib*.a files

On Tue, Jul 24, 2012 at 10:33:18PM +0200, Daniel Cegiełka wrote:
> > musl puts everything in libc. The other libs are only present for
> > compatibility with build scripts that are incapable of proper detection.
> > They are, as it is said, intentionally left blank.
> >
> > With valediction,
> >  - Gregor Richards
> >
> thx, we had a lot of problems with crypt_blowfish in libc vs libcrypt :)

To clarify, the reasons all of the standard library is integrated into
a single file mainly apply to dynamic linking:

1. Performance: Loading one shared library is faster than loading 3+
shared libraries. A modern multithreaded program is likely to use at
least libc, libm, libpthread, and librt.

2. Saving memory: Each additional shared library wastes at least one
page of commit charge and dirty physical memory, even though it will
probably just be for the GOT except in libc which needs a few pieces
of global data. Technically libm might be able to get by without a GOT
entirely, but I doubt the linker would make a GOT-free library even if
it technically could.

3. Avoiding exposing implementation internals and version
incompatibility: If libc/libm/libpthread/etc. are separate libraries,
they need cross-library references to implementation-internal
functions and data. This in turn can lead to bad breakage if there's a
version mismatch between them, and even worse, if a static version of
libm or libpthread got used with a dynamic libc, the binary would now
be permanently pegged to a particular version of libc due to using
impermanent internal interfaces specific to that version.

None of these issues apply if you're using static linking, but the
reason I also chose not to split up the static library files is the
same as the end of point 3 above: if libpthread.a contained static
versions of the pthread functions, it might get linked into a program
using dynamic, and introduce the version lock-in described
above. To avoid this, we'd have to make sure a file named existed as a no-op linker script (if it existed as an
empty ELF shared library file, it might get added to the program's
DT_NEEDED and then points 1 and 2 above would apply).

Since there's no benefit to separating the standard library into
broken-down .a files, and lots of potential pitfalls, I chose not to
separate it for static linking either.

As for why the empty .a files exist, it's because POSIX requires -lm,
-lpthread, etc. to be valid options to the C compiler, and requires
portable programs to use these options in their build scripts even if
the implementation does not require them. Making empty .a files is the
easiest way to meet that requirement.


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.