3

I'm trying to make a Haskell development environment for a web project that just has the dependencies hakyll, blaze, and clay. Only, clay appears to fail to build, complaining that Setup: Encountered missing dependencies: hspec >=2.2.0 && <2.6, hspec-discover >=2.2.0 && <2.6, and I can't seem to get past this.

I tried running cabal2nix . --shell > shell.nix on this cabal file:

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

But I'm running into the missing dependencies problem. Any ideas?

Edit: here's the shell.nix that I'm generating from the above, using cabal2nix:

{ 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

And here's how I've been trying to modify it, so that it overrides 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

But I'm obviously doing something wrong, since I'm getting: error: cannot auto-call a function that has an argument without a default value ('haskellLib').

Jonathan
  • 9,074
  • 8
  • 45
  • 80

2 Answers2

2

This is typically caused by a package pinning an old version of dependency, not available in nixpkgs. Peter is correct that clay needs to bump the hspec version.

However, you can try to temporarily fix it by jailbreaking the package (removing the version bounds) in nixpkgs, see:

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

In case the package does not build with newer version of hspec, you could try to add the old version to the package set and override the package to use it:

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

But that would require require re-generating hackage-packages.nix so I do not recommend it.

It is better idea to patch the package to support newer version of the dependency and add the patch to overrides:

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

Also do not forget to open an issue upstream – I see you already did – or a pull request.

Jan Tojnar
  • 4,640
  • 3
  • 25
  • 44
  • I think the issue is, I don't understand how to modify my .nix files so that they can do a jailbreak, (or anything else, really). I've updated my answer to reflect what I've been trying, but the examples you give don't really show how I could use those functions in practice. – Jonathan Feb 24 '19 at 21:23
  • I primarily meant fixing the issues in nixpkgs but your way is fine too. The issue is that you are not passing haskellLib to the expression. Try pkgs.haskell.lib. Or see https://discourse.nixos.org/t/when-haskell-dependencies-fail/2244/2 – Jan Tojnar Feb 25 '19 at 07:14
1

It's probably not really relevant anymore, but I encountered the same problem with clay.

I use an overlay to modify the (Haskell) package set. It looks like this (called 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 ]

My default.nix is created by cabal2nix . > default.nix from my cabal file, which in turn just specifies clay as a dependency.

In a (very simplified) release.nix file you can use the overlay as follows:

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

After that, nix-build release.nix works just fine. I don't use the --shell option to create a shell.nix file, but create it myself and import the release.nix file. Then I enrich my shell environment by adding in a couple of build tools. This works as expected as well.

InvisiblePanda
  • 1,519
  • 1
  • 16
  • 37