From 389ecf0f9b18ab6a913114fe45605106a47a1d4f Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Thu, 11 Jan 2024 14:40:18 +0530 Subject: [PATCH 1/2] wip --- nix/build-haskell-package.nix | 26 ++++++++++-- nix/modules/project/outputs.nix | 23 ++++++++++- nix/modules/project/packages/default.nix | 52 +++++++++++++++++++++++- 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/nix/build-haskell-package.nix b/nix/build-haskell-package.nix index 3563395a..b076da77 100644 --- a/nix/build-haskell-package.nix +++ b/nix/build-haskell-package.nix @@ -25,17 +25,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. diff --git a/nix/modules/project/outputs.nix b/nix/modules/project/outputs.nix index 2dce15d2..4fa1d6c6 100644 --- a/nix/modules/project/outputs.nix +++ b/nix/modules/project/outputs.nix @@ -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 = { @@ -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; + }]); }; + }; } diff --git a/nix/modules/project/packages/default.nix b/nix/modules/project/packages/default.nix index 5a39934c..6fc7cfdb 100644 --- a/nix/modules/project/packages/default.nix +++ b/nix/modules/project/packages/default.nix @@ -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) + (build-haskell-package name cfg.source "${project.config.projectRoot}/.haskellSrc2nix/${name}.nix") else log.traceDebug "${name}.callHackage ${cfg.source}" - (self.callHackage name 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; + }; }; } From b4500c6da56a917ace8d97793eaa99c0ee8f2de7 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Thu, 11 Jan 2024 15:20:47 +0530 Subject: [PATCH 2/2] log --- nix/modules/project/packages/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nix/modules/project/packages/default.nix b/nix/modules/project/packages/default.nix index 6fc7cfdb..d5aea850 100644 --- a/nix/modules/project/packages/default.nix +++ b/nix/modules/project/packages/default.nix @@ -73,10 +73,10 @@ in getOrMkPackage = name: cfg: if lib.types.path.check cfg.source then - log.traceDebug "${name}.callCabal2nix ${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}" + log.traceDebug "${name}.callHackage[cached] ${cfg.source}" ( # (self.callHackage name cfg.source { }) # callPackageKeepDeriver (self.hackage2nix name cfg.source) {}