I’m trying to switch over to using flakes for all of my Haskell projects.
The package I’m currently building uses a package in another directory. The location is ../grid, relative to the current directory. I’m really confused about the best way to do that with flakes. Should I…
Add it to the inputs expression in flake.nix?
Add it to flake.nix where it says # Dependency overrides go here?
Don’t mention it in flake.nix; instead add a cabal.project file that references it?
Incidentally, there is already a haskellPackages.grid in NixOS, but I’m developing a newer version locally. I want to use the local version of grid when I build this package.
Here’s my flake:
$ cat flake.nix
{
description = "Self-Organising Maps";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
haskellPackages = pkgs.haskellPackages;
jailbreakUnbreak = pkg:
pkgs.haskell.lib.doJailbreak (pkg.overrideAttrs (_: { meta = { }; }));
packageName = "som";
in {
packages.${packageName} =
haskellPackages.callCabal2nix packageName self rec {
# Dependency overrides go here
};
defaultPackage = self.packages.${system}.${packageName};
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
haskellPackages.haskell-language-server # you must build it with your ghc to work
ghcid
cabal-install
];
inputsFrom = builtins.attrValues self.packages.${system};
};
});
}
I haven’t been able to find a single example of a flake.nix that has something in the # Dependency overrides go here section. Everything I’ve tried to write there has failed, probably because I’m not using the right syntax.
After dozens of attempts, my best guess is that the flake should look something like this:
{
description = "Self-Organising Maps";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
haskellPackages = pkgs.haskellPackages.override {
overrides = self: super: rec {
grid = self.callCabal2nix "grid" (../grid) {};
};
};
jailbreakUnbreak = pkg:
pkgs.haskell.lib.doJailbreak (pkg.overrideAttrs (_: { meta = { }; }));
packageName = "som";
in {
packages.${packageName} =
haskellPackages.callCabal2nix packageName self rec {
# Dependency overrides go here
};
defaultPackage = self.packages.${system}.${packageName};
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
haskellPackages.haskell-language-server # you must build it with your ghc to work
ghcid
cabal-install
];
inputsFrom = builtins.attrValues self.packages.${system};
};
});
}
But that gives me an error:
$ nix build
error: access to absolute path '/nix/store/grid' is forbidden in pure eval mode (use '--impure' to override)
(use '--show-trace' to show detailed location information)
I should also mention that I build the local copy of grid using a flake. So there is a ../grid/flake.nix, relative to the directory where I’m trying to build som.
Yes. But you will need to use the absolute path (like url = "path:<absolute-path>";). This is because flake evaluation happens on files after they are copied to the Nix store. So something like this
doesn’t refer to the directory you think it does. It refers to the parent directory of the root of the current flake (something like /nix/store/<hash>-source), as can be seen in the error
But I understand how this can be confusing. As far as I know this is not really documented and I also learned it from someone else.
{
description = "Self-Organising Maps";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
grid.url = "path:/home/amy/github/grid";
};
outputs = { self, nixpkgs, flake-utils, grid }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
haskellPackages = pkgs.haskellPackages;
jailbreakUnbreak = pkg:
pkgs.haskell.lib.doJailbreak (pkg.overrideAttrs (_: { meta = { }; }));
packageName = "som";
in {
packages.${packageName} =
haskellPackages.callCabal2nix packageName self rec {
# Dependency overrides go here
};
defaultPackage = self.packages.${system}.${packageName};
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
haskellPackages.haskell-language-server # you must build it with your ghc to work
ghcid
cabal-install
];
inputsFrom = builtins.attrValues self.packages.${system};
};
});
}
But I’m missing the piece of the puzzle that tells it to use the grid that I defined in the inputs section instead of haskellPackages.grid. The error message below tells me that it’s still trying to use the old version of grid.
$ nix build
error: builder for '/nix/store/lii0k3mw3c03a9pha8w9rixjxn923zkr-som-11.0.2.drv' failed with exit code 1;
last 10 log lines:
> $, called at libraries/Cabal/Cabal/Distribution/Simple/Configure.hs:1024:20 in Cabal-3.2.1.0:Distribution.Simple.Configure
> configureFinalizedPackage, called at libraries/Cabal/Cabal/Distribution/Simple/Configure.hs:477:12 in Cabal-3.2.1.0:Distribution.Simple.Configure
> configure, called at libraries/Cabal/Cabal/Distribution/Simple.hs:625:20 in Cabal-3.2.1.0:Distribution.Simple
> confHook, called at libraries/Cabal/Cabal/Distribution/Simple/UserHooks.hs:65:5 in Cabal-3.2.1.0:Distribution.Simple.UserHooks
> configureAction, called at libraries/Cabal/Cabal/Distribution/Simple.hs:180:19 in Cabal-3.2.1.0:Distribution.Simple
> defaultMainHelper, called at libraries/Cabal/Cabal/Distribution/Simple.hs:116:27 in Cabal-3.2.1.0:Distribution.Simple
> defaultMain, called at /nix/store/4mdp8nhyfddh7bllbi7xszz7k9955n79-Setup.hs:2:8 in main:Main
> Setup: Encountered missing or private dependencies:
> grid >=8.0.0 && <8.1
>
For full logs, run 'nix log /nix/store/lii0k3mw3c03a9pha8w9rixjxn923zkr-som-11.0.2.drv'.