Haskell与Ubuntu上的动态库链接

时间:2014-12-04 10:23:15

标签: haskell ubuntu linker

我遇到了链接到我们编写的Haskell库的问题。它在Ubuntu上出错,但在Arch Linux上却没有。我们得到的Ubuntu错误是:

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

这个问题似乎是因为libHScontainers-0.4.2.1-ghc7.4.1.so链接不正确,因为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)

显然无法找到依赖库。它们已安装。但是,如果我在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)

找到了库。

正如所建议的,我可以在我们尝试链接到Haskell库的应用程序中使用-rpath在Ubuntu上解决这个问题。但这意味着我们必须为每个Haskell程序包执行此操作,这对我来说似乎是错误的。 我们还可以通过向/etc/ld.so.conf.d/ghc.conf添加一行来解决此问题。但是这也必须针对每个包进行,并且不是用户友好的。

我有几个问题:

  • 解决这个问题的正确方法是什么?
  • 为什么ghc-dynamic中的软件包链接不正确?
  • 为什么链接器能够找到libHScontainers-0.4.2.1-ghc7.4.1.so但不能找到libHSdeepseq-1.3.0.0-ghc7.4.1.so

1 个答案:

答案 0 :(得分:1)

我强烈怀疑这是因为ghc安装的Haskell库具有依赖项的位置(它们的ELF标题的RPATH字段;您可以使用readelf -d验证} { {1}}。当库 X 依赖于库 Y 时,库 X 可以指示库 Y 应该在相对位置找到使用$ORIGIN到自己的位置。动态链接器支持此功能,但静态链接器不支持

(我在这里推测:)你的库将定义其直接依赖项的位置(在你的情况下,我猜,这包括$ORIGIN)就其而言拥有containers,而不是RPATH。这就是为什么链接器可以找到它们,但不能找到它的传递依赖性(再次,我猜,在你的情况下,这包括$ORIGIN)。

那么为什么Arch Linux和Ubuntu之间存在差异? (进一步推测。)这是因为与Arch Linux不同,Ubunbu的链接器默认使用deepseq。你看,--as-needed会将你的库与所有的依赖关系(包括传递的)链接起来,但是链接器会省略其中的一些依赖关系,因为它不直接依赖于它们。您可以通过使用ghc重新链接来验证这一点。

请注意,静态链接器的这些错误确实不是错误,而是警告:它试图解析符号,但它不能; 但动态链接器无论如何都能。所以你可以指示链接器忽略这些错误(--no-as-needed),一切都应该好。

我一直在努力在--unresolved-symbols=ignore-all中添加显式支持来生成用于C程序的Haskell库,并且发现了同样的问题。有关详细信息,请参阅https://github.com/haskell/cabal/pull/2540#issuecomment-95984067