Cabal and linking with static libs (.a files)

(Reposted to café - my -libraries mail seems to have gotten lost along the way) Hi, I'm building an interface to a C library, which comes in the form of two .a files. I can't seem to get Cabal to link statically with these, so that the resulting package (libHSfoo-v.v.a) is self contained. I've tried fiddling with Cabal's ld-options and extra-libraries, but so far with no success - loading my package either results in GHC looking for (and failing to find) .so files, or "unknown symbol". Help? -k PS: did --user stop working (with GHC 20060607)? I'm adding --user to both 'configure' and 'install', but Cabal still wants to put things in /usr/local. -- If I haven't seen further, it is by standing in the footprints of giants

Ketil Malde wrote:
(Reposted to café - my -libraries mail seems to have gotten lost along the way)
I'm building an interface to a C library, which comes in the form of two .a files. I can't seem to get Cabal to link statically with these, so that the resulting package (libHSfoo-v.v.a) is self contained.
I've tried fiddling with Cabal's ld-options and extra-libraries, but so far with no success - loading my package either results in GHC looking for (and failing to find) .so files, or "unknown symbol".
A static library doesn't normally specify what it links to, that all happens at link time. So if you say -optl-static when linking your program, it won't have any dependencies on shared libraries. What you actually want to do, I suspect, is to include verbatim copies of the .a dependencies in your (binary) Cabal package, to make it self-contained. Cabal doesn't have a way to do that at the moment. But it's quite easy: just copy the .a files from /usr/lib (or wherever) and put them in the same place as your libHSpackage.a.
PS: did --user stop working (with GHC 20060607)? I'm adding --user to both 'configure' and 'install', but Cabal still wants to put things in /usr/local.
I don't think anything changed: --user never changed the install prefix, it only ever changed where dependencies are found. To install in your home dir, you also need to say --prefix=$HOME. Cheers, Simon

Simon Marlow
What you actually want to do, I suspect, is to include verbatim copies of the .a dependencies in your (binary) Cabal package, to make it self-contained.
Exactly.
But it's quite easy: just copy the .a files from /usr/lib (or wherever) and put them in the same place as your libHSpackage.a.
Thanks! I managed to get it to work by following that advice, and also renaming foo.a to libfoo.a, and linking with -lfoo. -k -- If I haven't seen further, it is by standing in the footprints of giants

Ketil Malde
But it's quite easy: just copy the .a files from /usr/lib (or wherever) and put them in the same place as your libHSpackage.a.
I managed to get it to work by following that advice, and also renaming foo.a to libfoo.a, and linking with -lfoo.
Now you see it, now you don't. :-/ * .a files in /local/lib/foo-0.0/ghc-xxxx/ -- check * .a files named libfoo.a -- check * -lfoo on the command line -- check Using strace shows that the .a file is indeed being read by ghc, but I still get "undefined reference". Apologies for being dense, but I can't seem to make it work at all. Is there a cabalized library that does this (links to a .a type C library) that I can look at? -k -- If I haven't seen further, it is by standing in the footprints of giants

Ketil Malde wrote:
Now you see it, now you don't. :-/
* .a files in /local/lib/foo-0.0/ghc-xxxx/ -- check * .a files named libfoo.a -- check * -lfoo on the command line -- check
Using strace shows that the .a file is indeed being read by ghc, but I still get "undefined reference".
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. As a matter of style, rather than using -lfoo on the command line you should use the extra-libraries field in the .cabal file.
Apologies for being dense, but I can't seem to make it work at all. Is there a cabalized library that does this (links to a .a type C library) that I can look at?
Some of the standard packages do this, eg. http://darcs.haskell.org/package/network comes with a small amount of C code. GHC doesn't currently use Cabal to build this, though. I'm sure there are other Cabal packages out there that link to .a libraries, it's quite a common thing to do. Cheers, Simon

Simon Marlow
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 it.
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. -k -- If I haven't seen further, it is by standing in the footprints of giants

Ketil Malde wrote:
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?
The idea is that a package should be self-contained; that is, it should include any external libraries that it depends on in its extra-libraries field. If you follow this rule, then everything should work. Specifying a library multiple times might work, but it would slow down linking, so I'd like to avoid it if possible. Cheers, Simon
participants (2)
-
Ketil Malde
-
Simon Marlow