我如何让 cabal 使用包的本地版本作为 Hackage 包的依赖项?

How do I get cabal to use a local version of a package as a dependency for a Hackage package?

我正在尝试在 GHC 9.2.1 上安装 aeson。我首先 运行 cabal install --allow-newer --lib aeson,它在构建 attoparsec 时失败了。原来这个问题是 already fixed in their Git repo,但还没有在 Hackage 上发布。然后我执行了这些步骤来构建带有修复的本地版本:

git clone https://github.com/haskell/attoparsec.git
cd attoparsec
cabal install --allow-newer --lib .
cd ..

成功了,但是当我再次执行 cabal install --allow-newer --lib aeson 时,它再次尝试从 Hackage 构建 attoparsec,因此再次失败。我怎样才能让 cabal 使用我刚刚构建和安装的东西?

主要有两种方法。

一个是创建一个 cabal project,其中包括 attoparsec 的克隆版本和您正在处理的本地包(可能依赖于 aeson 的包)。它可以像

一样简单
packages: attoparsec yourpackage

事实上,您甚至不需要克隆存储库,您可以使用 source-repository-package 字段代替。

因为local packages always take precedence over external ones,解析依赖时会选择repo版本

这种方法效果很好,但缺点是如果您在许多不同的项目中使用修补后的 attoparsec,则每次都必须引用并重新编译它。


另一种方法是在那里创建一个 local no-index package repository in your machine, give it priority over stardard Hackage, and put attoparsec's sdist tarball

您需要使用全局 cabal 配置的 repository 字段声明额外的包存储库(配置的路径显示在 cabal help 的最后一行)。默认情况下,只有 Hackage:

repository hackage.haskell.org
   url: http://hackage.haskell.org/

要使本地包存储库优先于 Hackage,您需要在全局 Cabal 配置或 cabal.project 文件中使用 active-repositories 字段。

这种方法的优点是不需要创建Cabal项目,而且补丁版本的attoparsec只会被编译一次(就像来自Hackage)。