aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
diff options
context:
space:
mode:
Diffstat (limited to 'infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix')
-rw-r--r--infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix209
1 files changed, 174 insertions, 35 deletions
diff --git a/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix b/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
index 1418cfef0574..4ae3f0b2427f 100644
--- a/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
+++ b/infra/libkookie/nixpkgs/pkgs/development/haskell-modules/make-package-set.nix
@@ -221,30 +221,56 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
# , overrides : Defaulted (HaskellPackageOverrideSet)
# , modifier : Defaulted
# , returnShellEnv : Defaulted
+ # , withHoogle : Defaulted
+ # , cabal2nixOptions : Defaulted
# } -> NixShellAwareDerivation
+ #
# Given a path to a haskell package directory, an optional package name
# which defaults to the base name of the path, an optional set of source
# overrides as appropriate for the 'packageSourceOverrides' function, an
# optional set of arbitrary overrides, and an optional haskell package
# modifier, return a derivation appropriate for nix-build or nix-shell to
# build that package.
+ #
+ # If 'returnShellEnv' is true this returns a derivation which will give you
+ # an environment suitable for developing the listed packages with an
+ # incremental tool like cabal-install.
+ #
+ # If 'withHoogle' is true (the default if a shell environment is requested)
+ # then 'ghcWithHoogle' is used to generate the derivation (instead of
+ # 'ghcWithPackages'), see the documentation there for more information.
+ #
+ # 'cabal2nixOptions' can contain extra command line arguments to pass to
+ # 'cabal2nix' when generating the package derivation, for example setting
+ # a cabal flag with '--flag=myflag'.
developPackage =
{ root
, name ? builtins.baseNameOf root
, source-overrides ? {}
, overrides ? self: super: {}
, modifier ? drv: drv
- , returnShellEnv ? pkgs.lib.inNixShell }:
+ , returnShellEnv ? pkgs.lib.inNixShell
+ , withHoogle ? returnShellEnv
+ , cabal2nixOptions ? "" }:
let drv =
(extensible-self.extend
(pkgs.lib.composeExtensions
(self.packageSourceOverrides source-overrides)
overrides))
- .callCabal2nix name root {};
- in if returnShellEnv then (modifier drv).env else modifier drv;
+ .callCabal2nixWithOptions name root cabal2nixOptions {};
+ in if returnShellEnv
+ then (modifier drv).envFunc {inherit withHoogle;}
+ else modifier drv;
ghcWithPackages = selectFrom: withPackages (selectFrom self);
+ # Put 'hoogle' into the derivation's PATH with a database containing all
+ # the package's dependencies; run 'hoogle server --local' in a shell to
+ # host a search engine for the dependencies.
+ #
+ # To reload the Hoogle server automatically on .cabal file changes try
+ # this:
+ # echo *.cabal | entr -r -- nix-shell --run 'hoogle server --local'
ghcWithHoogle = selectFrom:
let
packages = selectFrom self;
@@ -258,6 +284,7 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
# packages themselves. Using nix-shell on this derivation will
# give you an environment suitable for developing the listed
# packages with an incremental tool like cabal-install.
+ #
# In addition to the "packages" arg and "withHoogle" arg, anything that
# can be passed into stdenv.mkDerivation can be included in the input attrset
#
@@ -274,7 +301,7 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
# (import ./.).shellFor {
# packages = p: [p.frontend p.backend p.common];
# withHoogle = true;
- # buildInputs = [ pkgs.python ];
+ # buildInputs = [ pkgs.python pkgs.cabal-install ];
# }
#
# -- cabal.project
@@ -285,38 +312,150 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
#
# bash$ nix-shell --run "cabal new-build all"
# bash$ nix-shell --run "python"
- shellFor = { packages, withHoogle ? false, ... } @ args:
+ shellFor =
+ { # Packages to create this development shell for. These are usually
+ # your local packages.
+ packages
+ , # Whether or not to generate a Hoogle database for all the
+ # dependencies.
+ withHoogle ? false
+ , # Whether or not to include benchmark dependencies of your local
+ # packages. You should set this to true if you have benchmarks defined
+ # in your local packages that you want to be able to run with cabal benchmark
+ doBenchmark ? false
+ , ...
+ } @ args:
let
- combinedPackageFor = packages:
- let
- selected = packages self;
-
- pname = if pkgs.lib.length selected == 1
- then (pkgs.lib.head selected).name
- else "packages";
-
- # If `packages = [ a b ]` and `a` depends on `b`, don't build `b`,
- # because cabal will end up ignoring that built version, assuming
- # new-style commands.
- combinedPackages = pkgs.lib.filter
- (input: pkgs.lib.all (p: input.outPath or null != p.outPath) selected);
-
- # Returns an attrset containing a combined list packages' inputs for each
- # stage of the build process
- packageInputs = pkgs.lib.zipAttrsWith
- (_: pkgs.lib.concatMap combinedPackages)
- (map (p: p.getCabalDeps) selected);
-
- genericBuilderArgs = {
- inherit pname;
- version = "0";
- license = null;
- } // packageInputs;
-
- in self.mkDerivation genericBuilderArgs;
-
- mkDerivationArgs = builtins.removeAttrs args [ "packages" "withHoogle" ];
- in ((combinedPackageFor packages).envFunc { inherit withHoogle; }).overrideAttrs (old: mkDerivationArgs // {
+ # A list of the packages we want to build a development shell for.
+ # This is a list of Haskell package derivations.
+ selected = packages self;
+
+ # This is a list of attribute sets, where each attribute set
+ # corresponds to the build inputs of one of the packages input to shellFor.
+ #
+ # Each attribute has keys like buildDepends, executableHaskellDepends,
+ # testPkgconfigDepends, etc. The values for the keys of the attribute
+ # set are lists of dependencies.
+ #
+ # Example:
+ # cabalDepsForSelected
+ # => [
+ # # This may be the attribute set corresponding to the `backend`
+ # # package in the example above.
+ # { buildDepends = [ gcc ... ];
+ # libraryHaskellDepends = [ lens conduit ... ];
+ # ...
+ # }
+ # # This may be the attribute set corresponding to the `common`
+ # # package in the example above.
+ # { testHaskellDepends = [ tasty hspec ... ];
+ # libraryHaskellDepends = [ lens aeson ];
+ # benchmarkHaskellDepends = [ criterion ... ];
+ # ...
+ # }
+ # ...
+ # ]
+ cabalDepsForSelected = map (p: p.getCabalDeps) selected;
+
+ # A predicate that takes a derivation as input, and tests whether it is
+ # the same as any of the `selected` packages.
+ #
+ # Returns true if the input derivation is not in the list of `selected`
+ # packages.
+ #
+ # isNotSelected :: Derivation -> Bool
+ #
+ # Example:
+ #
+ # isNotSelected common [ frontend backend common ]
+ # => false
+ #
+ # isNotSelected lens [ frontend backend common ]
+ # => true
+ isNotSelected = input: pkgs.lib.all (p: input.outPath or null != p.outPath) selected;
+
+ # A function that takes a list of list of derivations, filters out all
+ # the `selected` packages from each list, and concats the results.
+ #
+ # zipperCombinedPkgs :: [[Derivation]] -> [Derivation]
+ #
+ # Example:
+ # zipperCombinedPkgs [ [ lens conduit ] [ aeson frontend ] ]
+ # => [ lens conduit aeson ]
+ #
+ # Note: The reason this isn't just the function `pkgs.lib.concat` is
+ # that we need to be careful to remove dependencies that are in the
+ # `selected` packages.
+ #
+ # For instance, in the above example, if `common` is a dependency of
+ # `backend`, then zipperCombinedPkgs needs to be careful to filter out
+ # `common`, because cabal will end up ignoring that built version,
+ # assuming new-style commands.
+ zipperCombinedPkgs = vals:
+ pkgs.lib.concatMap
+ (drvList: pkgs.lib.filter isNotSelected drvList)
+ vals;
+
+ # Zip `cabalDepsForSelected` into a single attribute list, combining
+ # the derivations in all the individual attributes.
+ #
+ # Example:
+ # packageInputs
+ # => # Assuming the value of cabalDepsForSelected is the same as
+ # # the example in cabalDepsForSelected:
+ # { buildDepends = [ gcc ... ];
+ # libraryHaskellDepends = [ lens conduit aeson ... ];
+ # testHaskellDepends = [ tasty hspec ... ];
+ # benchmarkHaskellDepends = [ criterion ... ];
+ # ...
+ # }
+ #
+ # See the Note in `zipperCombinedPkgs` for what gets filtered out from
+ # each of these dependency lists.
+ packageInputs =
+ pkgs.lib.zipAttrsWith (_name: zipperCombinedPkgs) cabalDepsForSelected;
+
+ # A attribute set to pass to `haskellPackages.mkDerivation`.
+ #
+ # The important thing to note here is that all the fields from
+ # packageInputs are set correctly.
+ genericBuilderArgs = {
+ pname =
+ if pkgs.lib.length selected == 1
+ then (pkgs.lib.head selected).name
+ else "packages";
+ version = "0";
+ license = null;
+ }
+ // packageInputs
+ // pkgs.lib.optionalAttrs doBenchmark {
+ # `doBenchmark` needs to explicitly be set here because haskellPackages.mkDerivation defaults it to `false`. If the user wants benchmark dependencies included in their development shell, it has to be explicitly enabled here.
+ doBenchmark = true;
+ };
+
+ # This is a pseudo Haskell package derivation that contains all the
+ # dependencies for the packages in `selected`.
+ #
+ # This is a derivation created with `haskellPackages.mkDerivation`.
+ #
+ # pkgWithCombinedDeps :: HaskellDerivation
+ pkgWithCombinedDeps = self.mkDerivation genericBuilderArgs;
+
+ # The derivation returned from `envFunc` for `pkgWithCombinedDeps`.
+ #
+ # This is a derivation that can be run with `nix-shell`. It provides a
+ # GHC with a package database with all the dependencies of our
+ # `selected` packages.
+ #
+ # This is a derivation created with `stdenv.mkDerivation` (not
+ # `haskellPackages.mkDerivation`).
+ #
+ # pkgWithCombinedDepsDevDrv :: Derivation
+ pkgWithCombinedDepsDevDrv = pkgWithCombinedDeps.envFunc { inherit withHoogle; };
+
+ mkDerivationArgs = builtins.removeAttrs args [ "packages" "withHoogle" "doBenchmark" ];
+
+ in pkgWithCombinedDepsDevDrv.overrideAttrs (old: mkDerivationArgs // {
nativeBuildInputs = old.nativeBuildInputs ++ mkDerivationArgs.nativeBuildInputs or [];
buildInputs = old.buildInputs ++ mkDerivationArgs.buildInputs or [];
});