[Haskell-cafe] Partial statical linking

Jason Dusek jason.dusek at gmail.com
Wed Sep 26 16:20:58 CEST 2012


Hi,

I made a mistake when I said this worked, earlier. My experiment
was run on a system where I had implemented Christian Maeder's
suggestion, by symlinking some static libs in to GHC's libdir.
Naturally, everything appeared to work.

It turns out we have to pass the libraries with -optl, to
prevent GHC from reordering them relative to the other linker
options we've passed.

  ghc -outputdir ./tmp --make -O2 sssp.hs -o sssp.ubuntu \
   -optl-Wl,--whole-archive \
    -optl/usr/lib/x86_64-linux-gnu/libffi.a \
    -optl/usr/lib/x86_64-linux-gnu/libgmp.a \
    -optl/usr/lib/x86_64-linux-gnu/libz.a \
   -optl-Wl,--no-whole-archive

The next great discovery in this area could be an automated, and
general, way of generating the static libraries list. At
present, what I have to do is:

 1. compile the executable once with plain `ghc --make',

 2. use `ldd' to find shared libraries used by this executable
    and correlate these with debs use `dpkg -S',

 3. throw away shared libraries that are part of the `libc'
    Debian package,

 4. find the corresponding `.a' files for each `.so', use find
    and some Sed trickery and

 5. construct the appropriate linker linker before compiling
    everything again.

I could probably skip recompiling everything in step 5 and just
relink. I've made steps 2, 3 and 4 into a shell script that
could be easily adapted to other projects:

  https://github.com/erudify/sssp/blob/master/ubuntu/util

I wonder how much of this we could legitimately ask GHC to do
for us. Statically linking every C dependency is unwise -- it's
not supposed to work to link libc and its immediate dependencies
-- and it does seem odd to ask that GHC have knowledge of this.

--
Jason Dusek
pgp // solidsnack // C1EBC57DC55144F35460C8DF1FD4C6C1FED18A2B


2012/9/24 Jason Dusek <jason.dusek at gmail.com>:
> 2012/9/19 Brandon Allbery <allbery.b at gmail.com>:
>> On Wed, Sep 19, 2012 at 7:06 AM, Jason Dusek <jason.dusek at gmail.com> wrote:
>>> What I attempted was building a binary with only some C libraries
>>> statically linked, with this command line:
>>>
>>>   # Build https://github.com/erudify/sssp on Ubunut 12.04
>>>   ghc -outputdir ./tmp -v --make -O2 sssp.hs -o sssp.ubuntu \
>>>     /usr/lib/x86_64-linux-gnu/libffi.a \
>>>     /usr/lib/x86_64-linux-gnu/libgmp.a \
>>>     /usr/lib/x86_64-linux-gnu/libz.a
>>>
>>> However, this really made no difference. Running `ldd' on the
>>> resulting binary reveals that libz and friends are still
>>> dynamically linked:
>>
>> On Linux you probably need -optl--whole-archive for this to do anything;
>> alternately, you would need to get the final ld command line out of ghc and
>> insert the above libraries into it *after* the package .a files.
>>
>> Putting them before the packages (including the GHC runtime) that need them,
>> as will happen by default, will cause them to be ignored because they
>> contain no required symbols *at that point* in the link.  --whole-archive
>> tells to blindly link the whole static archive in instead of ignoring it.
>
> Hi Brandon,
>
> This turned out to be the right ticket. The full command line is
> like this:
>
>   ghc -outputdir ./tmp --make -O2 sssp.hs -o sssp.ubuntu \
>     -optl-Wl,--whole-archive \
>       /usr/lib/x86_64-linux-gnu/libffi.a \
>       /usr/lib/x86_64-linux-gnu/libgmp.a \
>       /usr/lib/x86_64-linux-gnu/libz.a \
>     -optl-Wl,--no-whole-archive
>
> Without the --no-whole-archive at the end, I get errors like:
>
>   (.text+0x880): multiple definition of `__morestack_unblock_signals'
>   /usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc.a(generic-morestack.o):(.text+0x880):
> first defined here
>   /usr/lib/gcc/x86_64-linux-gnu/4.6/libgcc.a(generic-morestack.o): In
> function `__morestack_allocate_stack_space':
>
> I am not sure why that happens -- libgcc.a wasn't explicitly
> asked for; but it stands to reason that one shouldn't specify
> --whole-archive for everything GHC links, just the archives of
> interest. Life is short and art is long.
>
> --
> Jason Dusek
> pgp // solidsnack // C1EBC57DC55144F35460C8DF1FD4C6C1FED18A2B



More information about the Haskell-Cafe mailing list