Policy on static linking ?

Jilles Tjoelker jilles at stack.nl
Fri Jan 14 16:20:41 UTC 2011


On Fri, Jan 14, 2011 at 02:07:37PM +0000, Pete French wrote:
> I build code using static linking for deployment across a set of
> machines. For me this has a lot of advantages - I know that the
> code will run, no matter what the state of the ports is on the
> machine, and if there is a need to upgrade a library then I do it
> once on the build machine, rebuild the executable, and rsync it out
> to the leaf nodes. Only one place to track security updates, only
> one place where I need to have all the porst the code depends on
> installed.

> I recently wanted to use libdespatch, but I found that the port
> didn't install the static libraries. I filed a PR, and found out
> from the reponse that this was deliberate, and that a number of
> other ports were deliberately excluding static libraries too. Some
> good reasons where given, which I wont reporduce here,
> as you can read them at: http://www.freebsd.org/cgi/query-pr.cgi?pr=151306

> Today I finally hit the problem where a critical library I am using
> has stopped working with static libraries (or so it appears at first glance).
> I was wondering what the general policy here was - should I just bite the
> bullet and go dynamic, and accept the maintannance headache that cases, or
> could we define something like 'WITH_STATIC_LIBRARIES' that could be set
> which would make ports install a set of static libraries (maybe into
> a separate /usr/local/lib/static?) so that the likes of me could
> continue to build static code ? I'd very much like to be able to continue
> to ship single executables that "just run", but if theres some policy
> to only have dynamic libraries in ports going forward then fair enough...

Various features do not work with static linking because dlopen() does
not work from static executables. Libraries that are also used by
dlopen()ed modules should generally be linked dynamically, particularly
if these libraries have global state.

Things that use dlopen() include NSS (getpwnam() and the like), PAM and
most "plugin" systems. If libc is statically linked, NSS falls back to a
traditional mode that only supports the traditional things (e.g. no LDAP
user information); I think PAM and most plugin systems do not work at
all.

For some system libraries, there can be kernel compatibility problems
that prevent old libraries from working, although an ABI-compatible
shared library is available. This has happened with 6.x's libkse:
binaries statically linked to it do not run on 8.x or newer, while
libkse can be remapped to libthr for binaries dynamically linked to
libkse.

For these reasons, static linking to libc, libpthread and similar system
libraries should be reserved for /rescue/rescue and similar programs,
and not used in general.

Another feature only available with dynamic linking is hidden symbols
that are available only inside the shared object. Compiling a library
that uses this feature as a static library will make the hidden symbols
visible to the application or other libraries. This may cause name
clashes that otherwise wouldn't have been a problem or invite API abuse.
Proper use of hidden symbols can also speed up linking and load times
considerably, particularly if the code is written in C++.

Other issues are static linking's requirement to list all libraries a
library depends on and in the correct order. With dynamic linking,
listing the indirect dependencies is unnecessary and best avoided. This
is generally not very hard to fix but still needs extra effort. (For
example, pkg-config has Libs.private to help with it.)

If you want to link dynamically but avoid too much management overhead,
consider using PCBSD's PBI system which allows you to ship all necessary
.so files (except system ones) with your application.

-- 
Jilles Tjoelker


More information about the freebsd-stable mailing list