为 n 个不同版本构建 haskell 包

Building haskell package for n different version

我正在尝试构建 bytestring and it fails with an error related to quickcheck。经过快速检查(没有双关语意),我发现 bytestring 依赖于版本 >= 2.4 && < 2.10 的快速检查,默认情况下 nix 构建快速检查版本 2.10.1.

阅读后 this 现在我知道我可以切换快速检查的版本了。

shell.nix:

{ compiler ? "default", doBenchmark ? false }:

let

config = { packageOverrides = pkgs: rec {
             haskellPackages = pkgs.haskellPackages.override {
               overrides = haskellPackagesNew: haskellPackagesOld: rec {
                 myproject = haskellPackagesNew.callPackage ./default.nix { };
                 QuickCheck = haskellPackagesNew.callPackage ./quickcheck.nix { };
               };
             };
           };
         };

  pkgs = (import <nixpkgs> { inherit config; }).pkgs;

  f = import ./default.nix;

  haskellPackages = if compiler == "default"
                       then pkgs.haskellPackages
                       else pkgs.haskell.packages.${compiler};

  variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;

  drv = variant (haskellPackages.callPackage f { development = true;});

in

{myproject = if pkgs.lib.inNixShell then drv.env else drv;}

default.nix 和 quickcheck.nix 是用 cabal2nix 生成的。

现在它抛出一个不同的错误,即一些包缺少它的依赖项,这是对版本 >=2.10 的快速检查。

如何判断只有 bytestring 会使用自定义版本?

编辑:quickcheck 的版本切换到 2.9.2

覆盖对单个包的依赖

问题是软件包集是使用原始快速检查版本创建的。全局覆盖这样一个经常使用的包肯定会导致问题。

相反,您可以覆盖依赖关系图中的特定边,例如 this:

myproject.overrideScope (self: super: {
    QuickCheck = haskellPackagesNew.callPackage ./quickcheck.nix { };
  });

可组合性

您的示例可以通过使用 haskellPackages.extend 而不是 overrides 来进一步改进。这将使您在之前扩展包集后可以自由地进一步扩展它。

您可以进行的另一项更改是在覆盖和覆盖的定义中避免 rec 递归属性集。通常最好改用 self。看到这个 blog post on flyingcircus.io.

packageOverrides 切换到 overlays 也是一个好主意。

这些事情现在可能不会引起问题,但会在较大的项目中导致意外,因此最好首先避免它们。

最终结果

我希望我做对了,因为我没有完整的示例。

{ compiler ? "default", doBenchmark ? false }:

let

  overlays = [(pkgs: super: {
             haskellPackages = super.haskellPackages.extend ( hself: hsuper: {
                 myproject = (hself.callPackage ./default.nix {}).overrideScope (pself: psuper: {
                     QuickCheck = pself.QuickCheck_2_9;
                   });
                 QuickCheck_2_9 = hself.callPackage ./quickcheck.nix { };
               };
             );
           };
         )];

  pkgs = (import <nixpkgs> { inherit overlays; }).pkgs;

  f = import ./default.nix;

  haskellPackages = if compiler == "default"
                       then pkgs.haskellPackages
                       else pkgs.haskell.packages.${compiler};

  variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;

  drv = variant (haskellPackages.callPackage f { development = true;});

in

{myproject = if pkgs.lib.inNixShell then drv.env else drv;}