On 6/16/06, Tomas Puverle <Tomas.Puverle@morganstanley.com> wrote:

I am not sure whether it is a good idea to force people to link
everything dynamically.  In our case, all of our apps are built with
static libraries, and for good reasons.

I'm not recommending this, but Sun makes it impossible to link a 100% static binary on Solaris 10.  You can (with care) link with static versions of your own and third-party libraries, but there are simply no static versions of the system libraries provided.

When linking with gcc, the naive approach of just using -static fails:

% gcc -static -o hello hello.o
/openpkg/bin/ld: cannot find -lc
collect2: ld returned 1 exit status

Sun's linker, I believe, supports using both -Bstatic and -Bdynamic on the same link line, so you can choose to link some libraries staticly and others dynamically, but with GNU ld it seems like these flags are all-or-none:

% ls
Makefile  greet.c  hello.c  hello.cpp

% make
gcc    -c -o greet.o greet.c
gcc -shared -o libgreet.so greet.o
ar rv libgreet.a greet.o
ar: creating libgreet.a
a - greet.o
gcc    -c -o hello.o hello.c
gcc   -L.  -o hello hello.o -lgreet
gcc   -L.  -o hello-static -Bstatic hello.o -lgreet -Bdynamic

% ldd hello-static
        libgreet.so =>   ./libgreet.so
        libc.so.1 =>     /lib/libc.so.1
        libm.so.2 =>     /lib/libm.so.2

So even though I've tried to request static linking for -lgreet, I've gotten the shared version.  I believe this is because the -Bdynamic at the end of the command line overrides the earlier -Bstatic so the entire link is performed using dynamic libraries.

Thankfully, GNU ld offers a "grouping" feature which seems to offer a solution to the problem:

% gcc -o hello-static hello.o  -Wl,--start-group -Wl,-static -L. -lgreet -Wl,--end-group -Wl,-dy
% ldd hello-static
        libc.so.1 =>     /lib/libc.so.1
        libm.so.2 =>     /lib/libm.so.2

Note that I've had to tell the linker, after the -static group, to revert to dynamic linking or else I end up with the dreaded "/openpkg/bin/ld: cannot find -lc"

The command lines I'm seeing from BBv2 when static linking is requested look like (paraphrased):

g++ -o program -Wl,--start-group object-files /full/path/to/libboost_filesystem-gcc41-sgd-1_34.a \
    -Wl,--end-group -static -Wl,--strip-all

So this is almost right.  I think that the -static needs to move inside the "group" and after the group must come, paradoxically, -Wl,-dy.  Then any libraries mentioned inside the --start-group/--end-group pair would be linked staticly and the system libraries which are pulled in implicitly would be dynamically linked.  Note that the Boost libraries themselves are being linked using fully qualified paths to the archive library; this is a can't-miss approach to ensuring that exact file is the one that is used.

For my testing, I have a simple brute-force workaround in place that eliminates the use of -static altogether.  This addresses these regression testing issues for me, but I think this issue might bear some further discussion.

--
Caleb Epstein