Haskell 在 Ubuntu 上与动态库链接

标签 haskell ubuntu linker

我在链接到我们编写的 Haskell 库时遇到问题。在 Ubuntu 上会出错,但在 Arch Linux 上不会。我们在 Ubuntu 上得到的错误是这样的:

/usr/bin/ld:警告:libHSdeepseq-1.3.0.0-ghc7.4.1.so,/usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7 需要。 4.1.so,没有找到(尝试使用-rpath或-rpath-link) /usr/lib/ghc/containers-0.4.2.1/libHScontainers-0.4.2.1-ghc7.4.1.so:对“deepseqzm1zi3zi0zi0_ControlziDeepSeq_zdfNFDataArrayzuzdcrnf1_info”的 undefined reference

问题似乎是由 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 => 未找到 libHSbase-4.5.0.0-ghc7.4.1.so => 未找到 libHSghc-prim-0.2.0.0-ghc7.4.1.so => 未找到 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

最佳答案

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

(我在这里推测:)您的库将根据其自身的 containers 定义其直接 依赖项的位置(在您的情况下,我猜这包括 RPATH ),这与 $ORIGIN 无关。这就是为什么链接器可以找到那些,但不能找到它的传递依赖项(同样,我猜,这包括 deepseq 在你的情况下)。

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

请注意,静态链接器的这些错误实际上不是错误,而是警告:它试图解析符号,但它不能; 但动态链接器无论如何都可以。因此,您可以指示链接器忽略这些错误 (--unresolved-symbols=ignore-all),一切都会好起来的。

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

关于Haskell 在 Ubuntu 上与动态库链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27291531/

相关文章:

haskell - 如何将Yesod升级到最新版本?

haskell - 在 haskell 中编写仅适用于关联类型的函数

ubuntu - 使用 Transmit 或 Cyber​​duck 的 SFTP super 用户

ubuntu - Terraform 无法在 Ubuntu 16.04 上安装 haproxy?

c++ - 未定义对 operator new 的引用

windows - 为 Windows 编译 Linux 应用程序 (C)

c - 对带有 -Wl,--wrap 的包装函数的 undefined reference

haskell - 在《哈姆雷特》中使用 UTCTime

haskell - "function arrows associate to the right"有什么用?

ubuntu - 使用 Puppet 时如何等待主目录出现?