我该如何在Nix中创建Haskell开发环境?

时间:2019-02-22 19:55:12

标签: haskell nix hakyll

我正在尝试为仅具有依赖项hakyllblazeclay的Web项目构建Haskell开发环境。只是,黏土似乎无法建造,抱怨Setup: Encountered missing dependencies: hspec >=2.2.0 && <2.6, hspec-discover >=2.2.0 && <2.6,而我似乎无法超越。

我尝试在这个阴谋文件上运行cabal2nix . --shell > shell.nix

name:               open-editions
version:            0.1.0.0
build-type:         Simple
cabal-version:      >= 1.10

executable site
  main-is:          site.hs
  build-depends:    base == 4.*
                  , blaze-html
                  , clay
                  , hakyll == 4.12.*
  ghc-options:      -threaded
  default-language: Haskell2010

但是我遇到了缺少依赖项的问题。有任何想法吗?

编辑:这是我使用cabal2nix从上面生成的shell.nix:

{ nixpkgs ? import <nixpkgs> {}, compiler ? "default", doBenchmark ? false }:

let

  inherit (nixpkgs) pkgs;

  f = { mkDerivation, base, blaze-html, clay, hakyll, stdenv }:
      mkDerivation {
        pname = "open-editions";
        version = "0.1.0.0";
        src = ./.;
        isLibrary = false;
        isExecutable = true;
        executableHaskellDepends = [ base blaze-html clay hakyll ];
        license = "unknown";
        hydraPlatforms = stdenv.lib.platforms.none;
      };

  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 {});

in

  if pkgs.lib.inNixShell then drv.env else drv

这就是我一直在尝试对其进行修改的方法,以使其覆盖Clay:

{ haskellLib, super, nixpkgs ? import <nixpkgs> {}, compiler ? "default", doBenchmark ? false }:

let

  inherit (nixpkgs) pkgs;

  clay = haskellLib.doJailbreak super.clay;

  f = { mkDerivation, base, blaze-html, clay, hakyll, stdenv }:
      mkDerivation {
        pname = "open-editions";
        version = "0.1.0.0";
        src = ./.;
        isLibrary = false;
        isExecutable = true;
        executableHaskellDepends = [ base blaze-html clay hakyll ];
        license = "unknown";
        hydraPlatforms = stdenv.lib.platforms.none;
      };

  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 {});

in

  if pkgs.lib.inNixShell then drv.env else drv

但是我显然做错了,因为我得到:error: cannot auto-call a function that has an argument without a default value ('haskellLib')

2 个答案:

答案 0 :(得分:1)

这通常是由固定旧版本的依赖关系的软件包引起的,该软件包在nixpkgs中不可用。彼得correct认为粘土需要颠覆hspec version

但是,您可以尝试通过破坏nixpkgs中的软件包(删除版本限制)来临时修复它,请参见:

https://github.com/NixOS/nixpkgs/blob/cc98350d55522ebb2b7d35db32bc7c2fc5b8b273/pkgs/development/haskell-modules/configuration-common.nix#L1088-L1089

如果该软件包未使用较新版本的hspec构建,则可以尝试将旧版本添加到软件包集中并覆盖该软件包以使用它:

https://github.com/NixOS/nixpkgs/blob/cc98350d55522ebb2b7d35db32bc7c2fc5b8b273/pkgs/development/haskell-modules/configuration-common.nix#L1170

但这需要重新生成hackage-packages.nix,所以我不建议这样做。

最好对软件包进行补丁以支持较新版本的依赖项,然后将补丁添加到替代项中。

https://github.com/NixOS/nixpkgs/blob/cc98350d55522ebb2b7d35db32bc7c2fc5b8b273/pkgs/development/haskell-modules/configuration-common.nix#L1187-L1190

也不要忘记向上游打开问题-我见到您already did –或请求请求。

答案 1 :(得分:1)

这可能不再重要,但是我在clay上遇到了同样的问题。

我使用覆盖层来修改(Haskell)软件包集。看起来像这样(称为overlays.nix):

let
  customHaskellPackages = self: super: {
    haskellPackages = super.haskellPackages.override {
      overrides = hself: hsuper: {
        # Since clay is not really maintained any longer, the upper
        # version bounds have gone stale.
        # Everything works fine; we just need to free it from its
        # too-tight chains.
        clay =
          super.haskell.lib.doJailbreak
            hsuper.clay;

        # Other packages would go here, too
        some-foo-package =
          super.haskell.lib.dontCheck
            (hself.callPackage ./some-foo-package.nix {});
      };
    };
  };
in
[ customHaskellPackages ]

我的default.nix是由cabal2nix . > default.nix从我的阴谋文件中创建的,该文件又将clay指定为依赖项。

在(非常简化的)release.nix文件中,您可以按如下方式使用叠加层:

let
  overlays = import ./nix/overlays.nix;
  # I might have needed this for clay, but it might have been sth else
  config = { allowBroken = true; };
  pkgs = import <nixpkgs> { inherit config; inherit overlays; };
in
pkgs.haskellPackage.myApplication
# Or use haskellPackages.callPackage ./something.nix {} here if you didn't
# add your project to haskellPackages in the overlay

之后,nix-build release.nix可以正常工作。 我不使用--shell选项来创建shell.nix文件,而是自己创建并导入release.nix文件。然后,通过添加一些构建工具来丰富我的Shell环境。这也按预期工作。