
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
2012/9/19 Brandon Allbery
: On Wed, Sep 19, 2012 at 7:06 AM, Jason Dusek
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