如何使用 Cabal 将 Haskell 依赖项的版本固定到底层本机依赖项的版本?

How can I pin a version of a Haskell dependency to a version of an underlying native dependency with Cabal?

在我的特殊情况下,我的 Cabal 文件依赖于 Haskell 包 bindings-libzip。特别是,我可以接受 libzip 的几个不同版本,例如bindings-libzip-0.11bindings-libzip-0.10。这些又依赖于各自的本机 C libzip 库版本 0.110.10.

因此我的 .cabal 文件中有 bindings-libzip >= 0.10 < 0.12

Haskell 包 bindings-libzip-x 指定 PkgConfig-Depends libzip 版本 x 必须存在于客户端计算机上。假设下游用户安装了 libzip0.10 版本。但是,当拉下我的包时,该用户拉下了可能的最新依赖项并传递拉下了 bindings-libzip0.11 版本。这会导致构建过程出错,并显示有关安装的 libzip 版本不正确的消息。

有什么方法可以在我的 .cabal 文件中指定当且仅当 pkg-config 检测到 libzip0.11 版本并使用 bindings-libzip-0.10 当且仅当 pkg-config 检测到 libzip 的版本 0.10?

我认为执行此操作的方法是使用自定义 Setup.hs 文件(在 .cabal 文件中指定 build-type: Custom。)

您可以使用 main 覆盖构建过程的特定阶段,如下所示:

main = defaultMainWithHooks $ simpleUserHooks { preConf = myPreConf }

myPreConf :: Args -> ConfigFlags -> IO HookedBuildInfo
myPreConf args configFlags = ...

覆盖 confHook 也可能是您想要的。

一些链接:

自定义 Setup.hs 文件覆盖 confHook 的示例:

abcBridge arb-fft cabalmdvrpm darkplaces-text GLFW happybara-webkit-server haskeline HDBC-postgresql helics hlbfgsb hlibsass hpqtypes hruby hsqml hubris illuminate intel-aes keera-posture KiCS-debugger libpq llvm-general morfeusz postgresql-libpq tamarin-prover tamarin-prover-term tamarin-prover-theory tamarin-prover-utils voyeur wxc wxcore

特别是 hruby Setup.hs 看起来它正在做您想要做的事情。

我正在提交另一个答案,因为这使用了另一个想法...

使用带有 defaultMainWithHooksArgs 的自定义 Setup.hs 允许您检查和修改 cabal configure 命令的参数。

这是一个 Setup.hs 没有修改:

import Distribution.Simple
import Distribution.Simple.Configure
import System.Environment

main = do
  args <- getArgs
  defaultMainWithHooksArgs simpleUserHooks args

如果您的 .cabal 文件定义了标志,例如:

Flag Foo
  Default:  False

然后在参数中您将看到 "--flags=-foo"。所以思路是:

  1. 在 .cabal 文件中定义两个标志 - use10use11 到 select 要使用哪个版本的 bindings-libzip
  2. 在您的自定义中Setup.hs确定要使用的版本。
  3. 找到 "--flags=..." arg 并在将其传递给 defaultMainWithHooksArgs 之前对其进行适当修改。