Skip to content

Instantly share code, notes, and snippets.

@codebje
Created August 7, 2018 00:24
Show Gist options
  • Save codebje/000df013a2a4b7c10d6014d8bf7bccf3 to your computer and use it in GitHub Desktop.
Save codebje/000df013a2a4b7c10d6014d8bf7bccf3 to your computer and use it in GitHub Desktop.
Build a multi-project Cabal application with Nix
with builtins; rec {
cabalProjects = listToAttrs (if pathExists ./cabal.project
then projectParse
else [ { name = baseNameOf ./.; value = ./.; } ] );
projectParse = let
contents = readFile ./cabal.project;
trimmed = replaceStrings ["packages:" " "] ["" ""] contents;
packages = filter (x: isString x && x != "") (split "\n" trimmed);
package = p: substring 0 (stringLength p - 1) p;
paths = map (p: let p' = package p; in { name = p'; value = toPath (./. + "/${p'}"); } ) packages;
in paths;
}.cabalProjects
{forShell ? false}:
let
pkgs = import ./nixpkgs.nix {};
ghc = pkgs.haskell.packages.ghc822;
targets = import ./cabal.nix;
haskellPackages = ghc.extend (pkgs.lib.composeExtensions
(pkgs.haskell.lib.packageSourceOverrides (targets // {
# any version overrides or submodule package dependencies here
# some-package = "0.2.0.0"; # fetch specific hackage version
# some-package = ./dir/subproject; # git submodule packages
}))
(self: super: {
ghcWithPackages = p: super.ghcWithPackages (
# I like to have ghci-pretty and ghcid available in my nix-shell
f: p f ++ (if forShell then [ f.cabal-install f.ghci-pretty f.ghcid ] else [])
);
# any fetch/overrides go here
# some-package = pkgs.haskell.lib.dontCheck (self.callCabal2nix "some-package" (pkgs.fetchFromGitHub { ... }) {});
# some-package = pkgs.haskell.lib.overrideCabal super.some-package (drv: { patches = (drv.patches or [ ... ]); });
})
);
buildSet = pkgs.lib.foldl (ps: p: ps // { ${p.pname} = p; }) {} packages;
packages = map (t: haskellPackages.${t} ) (builtins.attrNames targets);
tools = [ pkgs.pkgconfig ];
in
if forShell
then haskellPackages.shellFor { packages = _: packages; buildInputs = tools; }
else buildSet
import ./. { forShell = true; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment