[Haskell-cafe] Re: Cabal and linking with static libs (.a files)

Ketil Malde ketil+haskell at ii.uib.no
Tue Jun 27 06:23:01 EDT 2006

Simon Marlow <simonmarhaskell at gmail.com> writes:

> No idea, I'm afraid.  ghc -v might help you.  Try cut-and-pasting the
> linker command line and play around with ordering of -l options.

I noticed the linker is incredibly picky about the sequence of
options.  Anyway, I suspected that, but I couldn't seem to work around

> I'm sure there are other Cabal packages out there that link to .a
> libraries, it's quite a common thing to do.

I was going to post a long session trying to get things to work, but
while doing the writeup, I think perhaps I spotted the problem:

This command line, trying to link 'libafi.a' required by my package fmi-0.0: 

  polarvier:~/work/rbr/src % ghc --make -O2 -W -fglasgow-exts RBR.lhs hooks.o -o rbr -lafi
  Chasing modules from: RBR.lhs
  Skipping  Unslice          ( ./Unslice.lhs, ./Unslice.o )
  Skipping  Stats            ( ./Stats.hs, ./Stats.o )
  Skipping  Util             ( ./Util.hs, ./Util.o )
  Skipping  Main             ( RBR.lhs, RBR.o )
  Linking ...
  /home/ketil/lib/fmi-0.0/ghc-6.4.1/libHSfmi-0.0.a(FMIndex.o):(.text+0x642): undefined reference to `build_index'
  /home/ketil/lib/fmi-0.0/ghc-6.4.1/libHSfmi-0.0.a(FMIndex.o):(.text+0x78b): undefined reference to `count'
  /home/ketil/lib/fmi-0.0/ghc-6.4.1/libHSfmi-0.0.a(FMIndex.o):(.text+0xe95): undefined reference to `extract'
  collect2: ld returned 1 exit status

...didn't work, but examining the linking command from the -v output:

  gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
   /usr/lib/gcc/i486-linux-gnu/4.0.3/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o rbr -u GHCziBase_Izh_static_info -u GHCziBase_Czh_static_info -u GHCziFloat_Fzh_static_info -u GHCziFloat_Dzh_static_info -u GHCziPtr_Ptr_static_info -u GHCziWord_Wzh_static_info -u GHCziInt_I8zh_static_info -u GHCziInt_I16zh_static_info -u GHCziInt_I32zh_static_info -u GHCziInt_I64zh_static_info -u GHCziWord_W8zh_static_info -u GHCziWord_W16zh_static_info -u GHCziWord_W32zh_static_info -u GHCziWord_W64zh_static_info -u GHCziStable_StablePtr_static_info -u GHCziBase_Izh_con_info -u GHCziBase_Czh_con_info -u GHCziFloat_Fzh_con_info -u GHCziFloat_Dzh_con_info -u GHCziPtr_Ptr_con_info -u GHCziPtr_FunPtr_con_info -u GHCziStable_StablePtr_con_info -u GHCziBase_False_closure -u GHCziBase_True_closure -u GHCziPack_unpackCString_closure -u GHCziIOBase_stackOverflow_closure -u GHCziIOBase_heapOverflow_closure -u GHCziIOBase_NonTermination_closure -u GHCziIOBase_BlockedOnDeadMVar_closure -u GHCziIOBase_BlockedIndefinitely_closure -u GHCziIOBase_Deadlock_closure -u GHCziWeak_runFinalizzerBatch_closure -u __stginit_Prelude /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.0.3/crtbegin.o -L/usr/lib/ghc-6.4.1 -L/home/ketil/lib/fmi-0.0/ghc-6.4.1 -L/home/ketil/lib/bio-0.0/ghc-6.4.1 -L/home/ketil/lib/fps-0.7/ghc-6.4.1 -L/usr/lib/gcc/i486-linux-gnu/4.0.3 -L/usr/lib/gcc/i486-linux-gnu/4.0.3 -L/usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../lib -L/usr/lib/gcc/i486-linux-gnu/4.0.3/../../.. -L/lib/../lib -L/usr/lib/../lib RBR.o ./Util.o ./Stats.o ./Unslice.o hooks.o -lafi -lHShaskell98 -lHSfmi-0.0 -lHSbio-0.0 -lHSfps-0.7 -lHSbase -lHSbase_cbits -lHSrts -lm -lgmp -ldl -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.0.3/crtend.o /usr/lib/gcc/i486-linux-gnu/4.0.3/../../../../lib/crtn.o

GHC puts the C library (-lafi) *before* Haskell library
(-lHSfmi-0.0) that refers to it.  Redoing the collect2 command but
moving -lafi last does, in fact, work.  Also, specifying
extra-libraries in the cabal package works, as long as they are
specified in the correct order.

The remaining question is whether inserting command line specified
libraries this early is a good choice.  Perhaps one option that
appears harmless is to specify it multiple times?

BTW, for some reason, linking still fails when I'm using -optl-static,
and I have to manually run collect2 tacking on '-lstdc++ -lc' at the
end to make it link.

If I haven't seen further, it is by standing in the footprints of giants

More information about the Haskell-Cafe mailing list