Haskell Cabal:"包间接取决于同一包的多个版本"

时间:2012-02-15 20:48:31

标签: haskell dependencies package cabal cabal-install

清除了所有cabal install个ed包后,我在以下会话中运行了这个:

$ cabal update
Downloading the latest package list from hackage.haskell.org
james@bast:~/.cabal/packages$ cabal install cabal-dev
Resolving dependencies...
Downloading cabal-dev-0.9.1...
[1 of 1] Compiling Main             ( /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/Setup.hs, /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/dist/setup/Main.o )
Linking /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/dist/setup/setup ...
Configuring cabal-dev-0.9.1...
Warning: This package indirectly depends on multiple versions of the same
package. This is highly likely to cause a compile failure.
package containers-0.4.2.1 requires array-0.4.0.0
package Cabal-1.14.0 requires array-0.4.0.0
package text-0.11.1.13 requires array-0.4.0.0
package deepseq-1.3.0.0 requires array-0.4.0.0
package containers-0.4.2.1 requires array-0.4.0.0
package HTTP-4000.2.2 requires array-0.4.0.0
package cabal-dev-0.9.1 requires containers-0.4.2.1
package Cabal-1.14.0 requires containers-0.4.2.1
package template-haskell-2.7.0.0 requires containers-0.4.2.1
Building cabal-dev-0.9.1...
Preprocessing executable 'ghc-pkg-6_8-compat' for cabal-dev-0.9.1...
<command line>: cannot satisfy -package-id Cabal-1.14.0-4af45d3c8d10dc27db38ae0e7e5a952b: 
    Cabal-1.14.0-4af45d3c8d10dc27db38ae0e7e5a952b is unusable due to missing or recursive dependencies:
      array-0.4.0.0-46f61f5fd9543ebf309552ef84dccc86 containers-0.4.2.1-98f9aa15f9c08b13673dc9d89385f449
    (use -v for more information)
cabal: Error: some packages failed to install:
cabal-dev-0.9.1 failed during the building phase. The exception was:
ExitFailure 1
$ 

所以我无法安装cabal-dev的原因显然是

  • 它“间接依赖于同一个软件包的多个版本。”但是,cabal并未声明其声称cabal-dev需要多个版本的包。
  • Cabal-1.14.0具有“缺失或递归依赖”,特别是以某种方式涉及array-0.4.0.0containers-0.4.2.1

它列出的依赖关系图表确认这些声明都不正确(或者它列出的依赖关系是假的或不完整的):

claimed dependency graph of cabal-dev-0.9.1

所以:我错过了什么?哪些或哪些不正确:我,cabal或一个或多个软件包?

我正在跑步:

$ cabal --version
cabal-install version 0.10.2
using version 1.10.1.0 of the Cabal library 
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.4.1
$

1 个答案:

答案 0 :(得分:11)

当我们已经安装了包B和C但是针对不同版本的D构建时,问题就出现了,然后我们尝试在包A中同时使用包B和C: 钻石依赖问题 这可以正常工作,但仅当包B和C不公开其接口中D中定义的类型时。如果他们这样做,那么包A将无法一起使用B和C中的函数,因为它们不会使用相同的类型。那就是你会遇到类型错误。

要选择一个具体的例子,假设包D是bytestring,我们安装了bytestring-0.9.0.1和0.9.0.4。让我们说B是utf8-string而C是regex-base。可以说包A是Yi编辑程序。所以重点是,在Yi中的代码中的某个位置,我们希望将作为UTF-8解码结果产生的字节串作为输入传递给其中一个正则表达式函数。但这不起作用,因为utf8-string包中的函数使用bytestring-0.9.0.1中的ByteString类型,而regex包中的regex函数使用bytestring-0.9.0.4中的ByteString类型。因此,当我们尝试编译Yi时会出现类型错误:

无法匹配预期类型bytestring-0.9.0.4:Data.ByteString.ByteString' against inferred type bytestring-0.9.0.1:Data.ByteString.ByteString'

就GHC而言,这两种类型是完全无关的!

这显然非常烦人。也没有简单的解决方案。在这个例子中,我们假设已经构建了包B和C,所以实际上没有办法合理地使用这两个包而不用针对不同版本的包D重建它们。在这种情况下,显而易见的解决方案是重建B使用D-1.1而不是D-1.0。重建程序包的问题当然是它打破了已经针对它构建的所有其他包。目前尚不清楚您是否希望包管理器自动重建大量明显不相关的包。

从长远来看,最佳解决方案似乎是做Nix所做的事情。在上面的例子中,Nix不是用针对D-1.1构建的B替换针对D-1.0构建的包B,而是添加针对D-1.1构建的另一个B实例。所以B的原始实例将保持不变,没有任何东西会破坏。这是功能性的方法:我们从不改变值(已安装的软件包),我们只是创建新的软件包,并在不再需要时收集旧的软件。

实际上,这意味着我们必须使用包的一些哈希值和所有依赖包的哈希值来识别已安装的包。 jhc已经做到这一点,并且正在采取行动为GHC做类似的事情,尽管更多的是针对跟踪API / ABI变化。对于基于源代码的理智包管理,我认为这是正确的方向。

我应该注意,这不是一个新问题。您已经能够构建此问题,因为ghc开始允许同时安装同一个包的多个版本。我们现在只是更频繁地注意到它,因为我们拆分了基础包并允许升级这些拆分包。

目前的状态是Cabal警告这个问题,但并没有真正帮助你解决它。对于上面的例子,我们得到:

$ cabal configure
Configuring A-1.0...
Warning: This package indirectly depends on multiple versions of
the same package. This is highly likely to cause a compile failure.
package B-1.0 requires D-1.0
package C-1.0 requires D-1.1