Cabal and linking with static libs (.a files)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Cabal and linking with static libs (.a files)

Ketil Malde-3

(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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Cabal and linking with static libs (.a files)

Simon Marlow-5
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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Cabal and linking with static libs (.a files)

Ketil Malde-3
Simon Marlow <[hidden email]> writes:

> 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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Cabal and linking with static libs (.a files)

Ketil Malde-3
Ketil Malde <[hidden email]> writes:

>> 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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Cabal and linking with static libs (.a files)

Simon Marlow-5
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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Cabal and linking with static libs (.a files)

Ketil Malde-3
Simon Marlow <[hidden email]> 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
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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Cabal and linking with static libs (.a files)

Simon Marlow-5
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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe