I am having issues linking to a Haskell library we wrote. It goes wrong on Ubuntu, but not on Arch Linux. The error on Ubuntu we get is this:
/usr/bin/ld: warning: libHSdeepseq-1.3.0.0-ghc7.4.1.so, needed by /usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so, not found (try using -rpath or -rpath-link)
/usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so: undefined reference to 'deepseqzm1zi3zi0zi0_ControlziDeepSeq_zdfNFDataArrayzuzdcrnf1_info'
The issue seems to be caused by the fact that libHScontainers-0.4.2.1-ghc7.4.1.so
is incorrectly linked as one can see by the output of ldd
:
ldd /usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so
linux-vdso.so.1 => (0x00007fffe95a2000)
libHSdeepseq-1.3.0.0-ghc7.4.1.so => not found
libHSbase-4.5.0.0-ghc7.4.1.so => not found
libHSghc-prim-0.2.0.0-ghc7.4.1.so => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f89a5a59000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f89a569a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f89a5fd8000)
Apparently the dependent libraries can not be found. They are installed. However if I do the same on Arch:
ldd /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/libHSdeepseq-1.3.0.2-ghc7.8.3.so
linux-vdso.so.1 (0x00007fff09dfe000)
libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007fb8d3e96000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007fb8d3b91000)
librt.so.1 => /usr/lib/librt.so.1 (0x00007fb8d3988000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fb8d3784000)
libffi.so.6 => /usr/lib/libffi.so.6 (0x00007fb8d357b000)
libHSarray-0.5.0.0-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../array-0.5.0.0/libHSarray-0.5.0.0-ghc7.8.3.so (0x00007fb8d32e1000)
libHSbase-4.7.0.1-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../base-4.7.0.1/libHSbase-4.7.0.1-ghc7.8.3.so (0x00007fb8d2967000)
libHSinteger-gmp-0.5.1.0-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../integer-gmp-0.5.1.0/libHSinteger-gmp-0.5.1.0-ghc7.8.3.so (0x00007fb8d274c000)
libHSghc-prim-0.3.1.0-ghc7.8.3.so => /usr/lib/ghc-7.8.3/deepseq-1.3.0.2/../ghc-prim-0.3.1.0/libHSghc-prim-0.3.1.0-ghc7.8.3.so (0x00007fb8d24cf000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fb8d212c000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fb8d1f10000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007fb8d435f000)
The libraries are found.
As suggested I can solve this on Ubuntu by using -rpath in the application we try to link to the Haskell library. But this means that we have to do this for every Haskell package which seems wrong to me.
We can also fix this by adding a line to /etc/ld.so.conf.d/ghc.conf
. But this also has to be done for every package and is not user-friendly.
A few questions I have:
ghc-dynamic
incorrectly linked?libHScontainers-0.4.2.1-ghc7.4.1.so
but not libHSdeepseq-1.3.0.0-ghc7.4.1.so
?I strongly suspect that this is because the Haskell libraries installed by ghc have the locations of their dependencies (the RPATH
field of their ELF header; you can verify using readelf -d
) defined in terms of $ORIGIN
. When library X depends on library Y, library X can indicate that library Y should be found in a location relative to its own location by using $ORIGIN
. This is supported by the dynamic linker, but is not supported by the static linker.
(I'm speculating here:) Your library will define the location of its direct dependencies (in your case, I'm guessing, this includes containers
) in terms of its own RPATH
, which is not in terms of $ORIGIN
. This is why the linker can find those, but not its transitive dependencies (again, I'm guessing, this includes deepseq
in your case).
So why the difference between Arch Linux and Ubuntu? (Speculating further.) This is because unlike on Arch Linux, Ubunbu's linker uses --as-needed
by default. You see, ghc
will link your library against all its dependencies (including transitive ones), but then the linker will omit some of those dependencies because it doesn't directly depend on them. You could verify this by relinking with --no-as-needed
.
Note that these errors by the static linkers really aren't errors, but warnings: it tries to resolve symbols, but it can't; but the dynamic linker will be able to anyway. So you can instruct the linker to ignore these errors (--unresolved-symbols=ignore-all
) and all should be well.
I've been battling with adding explicit support in Cabal
for generating Haskell libraries for use in C programs, and found the same problem. See https://github.com/haskell/cabal/pull/2540#issuecomment-95984067 for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With