GHC 是否应该链接相同库的不同版本?

Should GHC be linking different versions of the same libraries?

我正在尝试使用 GHC 7.6.3 编译程序,但出现错误

/usr/lib/ghc/unix-2.6.0.1/libHSunix-2.6.0.1.a(execvpe.o): In function `pPrPr_disableITimers':
(.text+0x300): multiple definition of `pPrPr_disableITimers'
/home/tom/.cabal/lib/i386-linux-ghc-7.6.3/unix-2.7.1.0/libHSunix-2.7.1.0.a(ghcrts.o):ghcrts.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status

(问题最终源于 readProcessWithExitCode 的用法,但我认为这不是特别相关)

如果我 运行 ghc-v 然后我在命令行参数中看到

这是一个错误吗? GHC 真的应该尝试 link 两个不同版本的 unix 吗?

所以,关于这个错误本身,你没有给我足够的信息,但我将尝试使用我的心理调试能力来回答你的问题。

您试图编译依赖包 pq 的 GHC 程序。您可能使用 -package p-package q 指定了它们。您的包数据库可能看起来像这样(或传递看起来像这样):

id: p-0.1-8aa5d403c45ea59dcd2c39f123e27d57
depends: unix-2.6.0.1-9ce33138f4fcfb9c37f6e6c300bcc367

id: q-0.1-d5221a8c8a269b66ab9a07bdc23317dd
depends: unix-2.7.1.0-2f15426f5b53fe4c6490832f9b20d8d7

id: unix-2.6.0.1-9ce33138f4fcfb9c37f6e6c300bcc367
depends: (none)

id: unix-2.7.1.0-2f15426f5b53fe4c6490832f9b20d8d7
depends: (none)

当 GHC 查找包 p 时,它看到 p-0.1-8aa5d403c45ea59dcd2c39f123e27d57 并决定使用它。然后,当它查找包 q 时,它看到 q-0.1-d5221a8c8a269b66ab9a07bdc23317dd 并决定使用它。然后它会进行一致性检查,以确保对于任何 包 ID foo-0.1,它不会选择两个已安装的包 ID。在我的示例中,这是微不足道的事实,因为选择的 unix 的两个版本具有不同的包 ID(unix-2.6.0.1unix-2.7.1.0),并且我的心理调试能力表明在您的扩展中包数据库,也是如此。 (顺便说一句,如果你是 运行 GHC 7.10,那么阴影检查确保任何 包密钥 它没有选择两个不同的已安装包 ID。所以这是几乎可以肯定是真的。)

因此 GHC 接受了 kaboodle,我们尝试 link 在两个不同版本的 unix 中。糟糕!

那么,你该怎么办?这是您的选择。

  1. 使用 Cabal。 Cabal 将强制执行更强的约束,即对于每个 PACKAGE NAME,只有一个 PACKAGE VERSION。因此,当您尝试 cabal configure 时,它会告诉您它无法解析依赖关系,或者可能会选择针对 unix-2.6.0.1 而不是 unix-2.7.1.0 安装的 q 的早期版本

  2. 查看您是否有针对旧版 unix 安装的 q 版本,并明确请求它。默认情况下,如果一个包有多个可能的选择,GHC 将选择最新版本。您可以告诉它使用较早的版本。

  3. 重新安装针对 unix-2.7.1.0 编译的 p 的较新版本。然后 GHC 将拾取它并且没有不兼容。请注意,它必须是较新的版本,因为今天的 Cabal 不会让您拥有针对 unix-2.6.0.1 编译的 p-0.1 的副本以及针对 [=22= 编译的 p-0.1 的副本].傻吧?我们正在努力修复它。

  4. 删除您的 .cabal.ghc 目录,然后 cabal install 最新版本的 unix,然后是其他所有内容。然后一切都将(可能)针对新版本 unix 进行编译,不会有问题。

这里还有三个不太有用的解决方案:

  1. 请注意,您实际上只会收到此 link 错误,因为 unix 的 C 源代码即使在不同版本的软件包下也被分配了相同的名称(这不是Haskell 标识符的情况,它们是正确的版本前缀)。如果 unix 已修复,以便其所有 C 符号都带有版本前缀,则您不会看到此问题,并且您的程序可以正常编译。好吧,除非您尝试同时使用 unix 的两个不同版本的类型(然后您会被告知 unix-2.6.0.1:BlahBlahunix-2.7.1.0:BlahBlah 不同)。如果您幸运的话。 ) 目前没有关于如何执行此操作的约定,但有一张关于它的 GHC 票证:https://ghc.haskell.org/trac/ghc/ticket/9351

  2. 最近有人提出GHC在实现shadowing时应该强制执行更强的一致性约束,即Cabal强制执行的相同约束。在那个世界中,GHC 将无法找到 pq 之一,并且会报告并非所有包都是可满足的。那会更好吗?如何做到这一点的计划是让 Cabal 管理一个一致的 "view" 包数据库,这样当你单独使用 ghc 时,你永远不会看到不应该看到的包实际上是可见的。这就是这个 GSoC 项目:https://www.google-melange.com/gsoc/project/details/google/gsoc2015/vishal4556/5634387206995968

  3. 也许您可能会说,"Forget about all this fancy view business, really, GHC should just do a better consistency check on the packages you try to make it use to make sure that it's consistent with respect to a name to version mapping."(顺便说一句,安装程序可执行文件当前执行的检查将是一个简化的检查)。去年夏天我试图说服 Duncan GHC 应该这样做,但他坚定地认为这是 Cabal 的工作,我们不应该在 GHC 中复制这段代码。所以直到今天,GHC bugtracker 上还没有票据建议我们应该这样做。