mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-01-21 04:13:12 +00:00
haskellPackages.shellFor: improve documentation
This commit is contained in:
parent
0fa596936b
commit
17eee57642
@ -258,6 +258,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 +275,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 +286,143 @@ 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 generated a Hoogle database for all the
|
||||
# dependencies.
|
||||
withHoogle ? false
|
||||
, ...
|
||||
} @ args:
|
||||
let
|
||||
combinedPackageFor = packages:
|
||||
let
|
||||
selected = packages self;
|
||||
# A list of the packages we want to build a development shell for.
|
||||
#
|
||||
# This is a list of Haskell package derivations.
|
||||
selected = packages self;
|
||||
|
||||
pname = if pkgs.lib.length selected == 1
|
||||
then (pkgs.lib.head selected).name
|
||||
else "packages";
|
||||
# This is a list of attribute sets, where the each attribute set
|
||||
# corresponds to the build inputs 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;
|
||||
|
||||
# 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);
|
||||
# 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;
|
||||
|
||||
# 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);
|
||||
# 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;
|
||||
|
||||
genericBuilderArgs = {
|
||||
inherit pname;
|
||||
version = "0";
|
||||
license = null;
|
||||
} // packageInputs;
|
||||
# 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;
|
||||
|
||||
in self.mkDerivation genericBuilderArgs;
|
||||
# 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;
|
||||
|
||||
# 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" ];
|
||||
in ((combinedPackageFor packages).envFunc { inherit withHoogle; }).overrideAttrs (old: mkDerivationArgs // {
|
||||
|
||||
in pkgWithCombinedDepsDevDrv.overrideAttrs (old: mkDerivationArgs // {
|
||||
nativeBuildInputs = old.nativeBuildInputs ++ mkDerivationArgs.nativeBuildInputs or [];
|
||||
buildInputs = old.buildInputs ++ mkDerivationArgs.buildInputs or [];
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user