Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions nix/build-haskell-package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,37 @@ let
name = "${name}";
inherit src;
};

callPackageKeepDeriver = src: args:
pkgs.haskell.lib.compose.overrideCabal
(orig: {
passthru = orig.passthru or { } // {
# When using callCabal2nix or callHackage, it is often useful
# to debug a failure by inspecting the Nix expression
# generated by cabal2nix. This can be accessed via this
# cabal2nixDeriver field.
cabal2nixDeriver = src;
};
})
(self.callPackage src args);

callCabal2nixWithOptions = name: src: expr: args:
pkgs.haskell.lib.compose.overrideCabal
(orig: {
inherit src;
})
(callPackageKeepDeriver expr args);
in

name: root:
name: root: expr:
lib.pipe root
[
# Avoid rebuilding because of changes in parent directories
(mkNewStorePath "source-${name}")
(x: log.traceDebug "${name}.mkNewStorePath ${x.outPath}" x)

(root: self.callCabal2nix name root { })
(x: log.traceDebug "${name}.cabal2nixDeriver ${x.cabal2nixDeriver.outPath}" x)
(root: callCabal2nixWithOptions name root expr { })
# (x: log.traceDebug "${name}.cabal2nixDeriver ${x.cabal2nixDeriver.outPath}" x)

# Make sure all files we use are included in the sdist, as a check
# for release-worthiness.
Expand Down
23 changes: 22 additions & 1 deletion nix/modules/project/outputs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ in
);
};

gen-pkgset =
let
drv = pkgs.runCommandNoCC "cabal2nix-generated" { } (
"mkdir -p $out\n" +
builtins.concatStringsSep "\n" (
lib.mapAttrsToList (name: expr: "cp -a ${expr} $out/${name}.nix") config.packagesNix
)
);
in
pkgs.writeShellApplication {
name = "gen-pkgset";
runtimeInputs = [ pkgs.rsync ];
text = ''
set -x
mkdir -p .haskellSrc2nix
rsync -a --delete --chmod=u+rw ${drv}/ .haskellSrc2nix
'';
};
in
{
outputs = {
Expand All @@ -113,8 +131,11 @@ in

apps =
lib.mkMerge
(lib.mapAttrsToList (_: packageInfo: packageInfo.exes) config.outputs.packages);
(lib.mapAttrsToList (_: packageInfo: packageInfo.exes) config.outputs.packages ++ [{
gen-pkgset.program = gen-pkgset;
}]);
};

};
}

56 changes: 52 additions & 4 deletions nix/modules/project/packages/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,64 @@ in
build-haskell-package = import ../../../build-haskell-package.nix {
inherit pkgs lib self log;
};
callPackageKeepDeriver = src: args:
pkgs.haskell.lib.compose.overrideCabal
(orig: {
passthru = orig.passthru or { } // {
# When using callCabal2nix or callHackage, it is often useful
# to debug a failure by inspecting the Nix expression
# generated by cabal2nix. This can be accessed via this
# cabal2nixDeriver field.
cabal2nixDeriver = src;
};
})
(self.callPackage src args);
getOrMkPackage = name: cfg:
if lib.types.path.check cfg.source
then
log.traceDebug "${name}.callCabal2nix ${cfg.source}"
(build-haskell-package name cfg.source)
log.traceDebug "${name}.callCabal2nix[cached] ${cfg.source}"
(build-haskell-package name cfg.source "${project.config.projectRoot}/.haskellSrc2nix/${name}.nix")
else
log.traceDebug "${name}.callHackage ${cfg.source}"
(self.callHackage name cfg.source { });
log.traceDebug "${name}.callHackage[cached] ${cfg.source}"
(
# (self.callHackage name cfg.source { })
# callPackageKeepDeriver (self.hackage2nix name cfg.source) {}
callPackageKeepDeriver "${project.config.projectRoot}/.haskellSrc2nix/${name}.nix" { }
);
in
lib.mapAttrs getOrMkPackage project.config.packages;
};

# cabal2nix generated Nix expressions for packages
# uses `hackage2nix`
packagesNix = lib.mkOption {
default =
lib.mapAttrs
(name: cfg:
let
self = project.config.basePackages;
callCabal2nixWithOptionsExr = name: src: extraCabal2nixOptions:
let
filter = path: type:
pkgs.lib.hasSuffix ".cabal" path ||
baseNameOf path == "package.yaml";
in
self.haskellSrc2nix {
inherit name extraCabal2nixOptions;
src =
if pkgs.lib.canCleanSource src
then pkgs.lib.cleanSourceWith { inherit src filter; }
else src;
};
readCabal2NixExpr = drv:
"${builtins.trace drv.outPath drv}/default.nix";
in
readCabal2NixExpr (if lib.types.path.check cfg.source
# FIXME: Patch `src` to not point to nix store.
then callCabal2nixWithOptionsExr name cfg.source ""
else self.hackage2nix name cfg.source)
)
project.config.packages;
};
};
}