Newer version of package in overlay

I’m using overlays in NixOS, and it’s working great except for one thing: when a package is defined in my overlay that already exists (in an older version) in the NixOS repo, the version in the repo is picked up instead of the version in my overlay.

How can I get NixOS to use the package in my overlay instead of the one in the repo? I suspect that I need to modify overlays.nix, but I’m not sure how to do it.

My overlays directory looks like this.

$ tree
.
├── default.nix
├── hello-amy
│   ├── default.nix
│   ├── simple_builder.sh
│   └── simple.c
├── jot
│   └── default.nix
├── liquid-fixpoint
│   └── default.nix
├── liquidhaskell
│   └── default.nix
└── overlays.nix
$ cat overlays.nix 
self: super:
with super.lib;
let
  # Using the nixos plumbing that's used to evaluate the config...
  eval = import <nixpkgs/nixos/lib/eval-config.nix>;
  # Evaluate the config,
  paths = (eval {modules = [(import <nixos-config>)];})
    # then get the `nixpkgs.overlays` option.
    .config.nixpkgs.overlays
  ;
in
foldl' (flip extends) (_: super) paths self

I tried swapping the order of paths in overlays.nix, like so:, but it had no effect. I’m not sure overlays.nix is even being used; if I delete it there’s no change in the behaviour of nixos-rebuild switch

  paths =
    # First get the `nixpkgs.overlays` option,
    .config.nixpkgs.overlays
    # then evaluate the config.
    (eval {modules = [(import <nixos-config>)];})

FYI, here’s my top-level default.nix.

$ cat default.nix 
self: super: {
  hello-amy = super.callPackage ./hello-amy {};
  jot = super.haskellPackages.callPackage ./jot {};
  liquid-fixpoint = super.haskellPackages.callPackage ./liquid-fixpoint {};
  liquidhaskell = super.haskellPackages.callPackage ./liquidhaskell {};
}
2 Likes

I should also mention that my /etc/nixos/configuration.nix contains the following:

  nixpkgs.overlays = [
    (import /home/amy/nix-overlays/default.nix)
  ];

As I said, I’m not sure overlays.nix is being used or is necessary. The reason I have it is that I was trying to follow the instructions in the wiki.

It sounds like you need to use self somewhere rather than super. What is the exact problem you are having, is it to do with the liquid haskell overrides?

That does make sense, @mpickering.

The liquid-fixpoint package on hackage won’t build with recent versions of GHC, so I want to use the GitHub version instead. (There’s an open issue on this.) I am able to manually build and install liquidhaskell as a user, so I have a workaround. But I want to get this aspect of the overlay working because I’ll need it for some other packages as well.

Here’s my new top-level default.nix, with super changed to self.

$ cat ~/nix-overlays/default.nix
self: super: {
  hello-amy = self.callPackage ./hello-amy {};
  jot = self.haskellPackages.callPackage ./jot {};
  liquid-fixpoint = self.haskellPackages.callPackage ./liquid-fixpoint {};
  liquidhaskell = self.haskellPackages.callPackage ./liquidhaskell {};
}

And here’s the default.nix for liquid-fixpoint which I created using cabal2nix. As you can see, it picks up liquid-fixpoint version 0.8.0.1 from GitHub. But when I do nixos-rebuild switch, it’s using version 0.7.0.7 from Hackage.

$ cat ~/nix-overlays/liquid-fixpoint/default.nix 
{ mkDerivation, ansi-terminal, array, ascii-progress, async
, attoparsec, base, bifunctors, binary, boxes, bytestring, cereal
, cmdargs, containers, deepseq, directory, dotgen, fetchgit, fgl
, fgl-visualize, filemanip, filepath, ghc-prim, git, hashable
, intern, located-base, mtl, nettools, ocaml, parallel, parallel-io
, parsec, pretty, process, stdenv, stm, syb, tasty, tasty-ant-xml
, tasty-hunit, tasty-rerun, text, text-format, time, transformers
, unordered-containers, z3
}:
mkDerivation {
  pname = "liquid-fixpoint";
  version = "0.8.0.1";
  src = fetchgit {
    url = "https://github.com/ucsd-progsys/liquid-fixpoint.git";
    sha256 = "0j35a9692csm84zb5mizj24d4lr86fxznrjg8nww2ms5nr2g67dz";
    rev = "f3a7f69ba727f18261a6e1a5bd5d0a0098380d91";
    fetchSubmodules = true;
  };
  configureFlags = [ "-fbuild-external" ];
  isLibrary = true;
  isExecutable = true;
  libraryHaskellDepends = [
    ansi-terminal array ascii-progress async attoparsec base bifunctors
    binary boxes bytestring cereal cmdargs containers deepseq directory
    dotgen fgl fgl-visualize filemanip filepath ghc-prim hashable
    intern located-base mtl parallel parallel-io parsec pretty process
    syb text text-format time transformers unordered-containers
  ];
  executableHaskellDepends = [ base ];
  executableSystemDepends = [ ocaml ];
  testHaskellDepends = [
    base containers directory filepath mtl process stm tasty
    tasty-ant-xml tasty-hunit tasty-rerun text transformers
  ];
  testSystemDepends = [ git nettools z3 ];
  doCheck = false;
  homepage = "https://github.com/ucsd-progsys/liquid-fixpoint";
  description = "Predicate Abstraction-based Horn-Clause/Implication Constraint Solver";
  license = stdenv.lib.licenses.bsd3;
}

Ah, the problem here is that you’re extending the top-level attribute set with a new attribute called liquid-fixpoint. What you mean to do is extend the haskell package set with that package and then use it to build liquidhaskell. I would do something like (untested):

self: super: {
  hello-amy = self.callPackage ./hello-amy {};
  jot = self.haskellPackages.callPackage ./jot {};
  lh-packages = self.haskellPackages.extend(h-sel: h-sup: { liquid-fixpoint = h-sel.callPackage ./liquid-fixpoint {}; });
  liquidhaskell = self.lh-packages.callPackage ./liquidhaskell {};
}

The old advice would be to override the definition of haskellPackages but I don’t like doing that in general as it is a bit fiddly and can cause other things to break. I prefer to define new package sets with specific overrides in when I need to for specific applications.

Make sense?

1 Like

Your explanation was extremely helpful, and it did the trick! I’ll document what I did here in case it helps someone else:

The top-level default.nix in my overlay looks like this:

self: super: {
  hello-amy = self.callPackage ./hello-amy {};
  jot = self.haskellPackages.callPackage ./jot {};
  lh-packages = self.haskellPackages.extend(h-sel: h-sup: { liquid-fixpoint = h-sel.callPackage ./liquid-fixpoint {}; });
  my-liquidhaskell = self.lh-packages.callPackage ./liquidhaskell {};
}

And then in my /etc/nixos/configuration.nix, instead of adding haskellPackages.liquidhaskell to environment.systemPackages, I added my-liquidhaskell. Now, when I do nixos-rebuild switch, it picks up the correct version.

Unfortunately, that led to a build error because liquidhaskell expects ghc 8.4.3, but I know how to fix that problem.

2 Likes

And for anyone that doesn’t, you have to replace haskellPackages with haskell.packages.ghc843.

1 Like