callCabal2nixWithOptions: add srcModifier argument

Fixes #256769

Repro + test of fix here: https://gitlab.com/ramirez7/bug-repros/-/merge_requests/1

Adds a `srcModifier` argument to `callCabal2nixWithOptions` to allow
customizing the source files used to generate the cabal file (e.g. to
support `hpack`/`package.yaml`).
This commit is contained in:
Armando Ramirez 2023-09-27 14:41:12 -07:00 committed by sternenseemann
parent 9e2c860bc2
commit 876d055062
2 changed files with 76 additions and 12 deletions

View File

@ -230,7 +230,7 @@ completely incompatible with packages from `haskellPackages`.
Every haskell package set has its own haskell-aware `mkDerivation` which is used Every haskell package set has its own haskell-aware `mkDerivation` which is used
to build its packages. Generally you won't have to interact with this builder to build its packages. Generally you won't have to interact with this builder
since [cabal2nix][cabal2nix] can generate packages since [cabal2nix](#haskell-cabal2nix) can generate packages
using it for an arbitrary cabal package definition. Still it is useful to know using it for an arbitrary cabal package definition. Still it is useful to know
the parameters it takes when you need to the parameters it takes when you need to
[override](#haskell-overriding-haskell-packages) a generated Nix expression. [override](#haskell-overriding-haskell-packages) a generated Nix expression.
@ -1123,18 +1123,75 @@ for [this to work][optparse-applicative-completions].
Note that this feature is automatically disabled when cross-compiling, since it Note that this feature is automatically disabled when cross-compiling, since it
requires executing the binaries in question. requires executing the binaries in question.
## Import-from-Derivation helpers {#haskell-import-from-derivation}
### cabal2nix {#haskell-cabal2nix}
[`cabal2nix`][cabal2nix] can generate Nix package definitions for arbitrary
Haskell packages using [import from derivation][import-from-derivation].
`cabal2nix` will generate Nix expressions that look like this:
```nix
# cabal get mtl-2.2.1 && cd mtl-2.2.1 && cabal2nix .
{ mkDerivation, base, lib, transformers }:
mkDerivation {
pname = "mtl";
version = "2.2.1";
src = ./.;
libraryHaskellDepends = [ base transformers ];
homepage = "http://github.com/ekmett/mtl";
description = "Monad classes, using functional dependencies";
license = lib.licenses.bsd3;
}
```
This expression should be called with `haskellPackages.callPackage`, which will
supply [`haskellPackages.mkDerivation`](#haskell-mkderivation) and the Haskell
dependencies as arguments.
`callCabal2nix name src args`
: Create a package named `name` from the source derivation `src` using
`cabal2nix`.
`args` are extra arguments provided to `haskellPackages.callPackage`.
`callCabal2nixWithOptions name src opts args`
: Create a package named `name` from the source derivation `src` using
`cabal2nix`.
`opts` are extra options for calling `cabal2nix`. If `opts` is a string, it
will be used as extra command line arguments for `cabal2nix`, e.g. `--subpath
path/to/dir/containing/cabal-file`. Otherwise, `opts` should be an AttrSet
which can contain the following attributes:
`extraCabal2nixOptions`
: Extra command line arguments for `cabal2nix`.
`srcModifier`
: A function which is used to modify the given `src` instead of the default
filter.
The default source filter will remove all files from `src` except for
`.cabal` files and `package.yaml` files.
<!--
`callHackage`
: TODO
`callHackageDirect`
: TODO
`developPackage`
: TODO
-->
<!-- <!--
TODO(@NixOS/haskell): finish these planned sections TODO(@NixOS/haskell): finish these planned sections
### Overriding the entire package set ### Overriding the entire package set
## Import-from-Derivation helpers
* `callCabal2nix`
* `callHackage`, `callHackageDirect`
* `developPackage`
## Contributing {#haskell-contributing} ## Contributing {#haskell-contributing}
### Fixing a broken package {#haskell-fixing-a-broken-package} ### Fixing a broken package {#haskell-fixing-a-broken-package}
@ -1309,3 +1366,4 @@ relevant.
[profiling]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html [profiling]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html
[search.nixos.org]: https://search.nixos.org [search.nixos.org]: https://search.nixos.org
[turtle]: https://hackage.haskell.org/package/turtle [turtle]: https://hackage.haskell.org/package/turtle
[import-from-derivation]: https://nixos.org/manual/nix/stable/language/import-from-derivation

View File

@ -211,15 +211,21 @@ in package-set { inherit pkgs lib callPackage; } self // {
}) firstRevision; }) firstRevision;
# Creates a Haskell package from a source package by calling cabal2nix on the source. # Creates a Haskell package from a source package by calling cabal2nix on the source.
callCabal2nixWithOptions = name: src: extraCabal2nixOptions: args: callCabal2nixWithOptions = name: src: opts: args:
let let
filter = path: type: extraCabal2nixOptions = if builtins.isString opts
then opts
else opts.extraCabal2nixOptions or "";
srcModifier = opts.srcModifier or null;
defaultFilter = path: type:
pkgs.lib.hasSuffix ".cabal" path || pkgs.lib.hasSuffix ".cabal" path ||
baseNameOf path == "package.yaml"; baseNameOf path == "package.yaml";
expr = self.haskellSrc2nix { expr = self.haskellSrc2nix {
inherit name extraCabal2nixOptions; inherit name extraCabal2nixOptions;
src = if pkgs.lib.canCleanSource src src = if srcModifier != null
then pkgs.lib.cleanSourceWith { inherit src filter; } then srcModifier src
else if pkgs.lib.canCleanSource src
then pkgs.lib.cleanSourceWith { inherit src; filter = defaultFilter; }
else src; else src;
}; };
in overrideCabal (orig: { in overrideCabal (orig: {