2020-04-24 23:36:52 +00:00
# This expression takes a file like `hackage-packages.nix` and constructs
# a full package set out of that.
{ # package-set used for build tools (all of nixpkgs)
buildPackages
, # A haskell package set for Setup.hs, compiler plugins, and similar
# build-time uses.
buildHaskellPackages
, # package-set used for non-haskell dependencies (all of nixpkgs)
pkgs
2021-02-05 17:12:51 +00:00
, # stdenv provides our build and host platforms
2020-04-24 23:36:52 +00:00
stdenv
2021-02-05 17:12:51 +00:00
, # this module provides the list of known licenses and maintainers
lib
# needed for overrideCabal & packageSourceOverrides
2020-04-24 23:36:52 +00:00
, haskellLib
, # hashes for downloading Hackage packages
2022-09-09 14:08:57 +00:00
# This is either a directory or a .tar.gz containing the cabal files and
# hashes of Hackage as exemplified by this repository:
# https://github.com/commercialhaskell/all-cabal-hashes/tree/hackage
2020-04-24 23:36:52 +00:00
all-cabal-hashes
, # compiler to use
ghc
2021-02-05 17:12:51 +00:00
, # A function that takes `{ pkgs, lib, callPackage }` as the first arg and
2020-04-24 23:36:52 +00:00
# `self` as second, and returns a set of haskell packages
package-set
, # The final, fully overriden package set usable with the nixpkgs fixpoint
# overriding functionality
extensible-self
} :
# return value: a function from self to the package set
self :
let
inherit ( stdenv ) buildPlatform hostPlatform ;
2021-02-05 17:12:51 +00:00
inherit ( lib ) fix' extends makeOverridable ;
2020-04-24 23:36:52 +00:00
inherit ( haskellLib ) overrideCabal ;
mkDerivationImpl = pkgs . callPackage ./generic-builder.nix {
inherit stdenv ;
nodejs = buildPackages . nodejs-slim ;
inherit ( self ) buildHaskellPackages ghc ghcWithHoogle ghcWithPackages ;
inherit ( self . buildHaskellPackages ) jailbreak-cabal ;
2021-12-06 16:07:01 +00:00
hscolour = overrideCabal ( drv : {
2020-04-24 23:36:52 +00:00
isLibrary = false ;
doHaddock = false ;
hyperlinkSource = false ; # Avoid depending on hscolour for this build.
postFixup = " r m - r f $ o u t / l i b $ o u t / s h a r e $ o u t / n i x - s u p p o r t " ;
2021-12-06 16:07:01 +00:00
} ) self . buildHaskellPackages . hscolour ;
cpphs = overrideCabal ( drv : {
isLibrary = false ;
postFixup = " r m - r f $ o u t / l i b $ o u t / s h a r e $ o u t / n i x - s u p p o r t " ;
} ) ( self . cpphs . overrideScope ( self : super : {
2020-04-24 23:36:52 +00:00
mkDerivation = drv : super . mkDerivation ( drv // {
enableSharedExecutables = false ;
enableSharedLibraries = false ;
doHaddock = false ;
useCpphs = false ;
} ) ;
2021-12-06 16:07:01 +00:00
} ) ) ;
2020-04-24 23:36:52 +00:00
} ;
mkDerivation = makeOverridable mkDerivationImpl ;
# manualArgs are the arguments that were explictly passed to `callPackage`, like:
#
# callPackage foo { bar = null; };
#
# here `bar` is a manual argument.
callPackageWithScope = scope : fn : manualArgs :
let
# this code is copied from callPackage in lib/customisation.nix
#
# we cannot use `callPackage` here because we want to call `makeOverridable`
# on `drvScope` (we cannot add `overrideScope` after calling `callPackage` because then it is
# lost on `.override`) but determine the auto-args based on `drv` (the problem here
# is that nix has no way to "passthrough" args while preserving the reflection
# info that callPackage uses to determine the arguments).
2021-02-05 17:12:51 +00:00
drv = if lib . isFunction fn then fn else import fn ;
auto = builtins . intersectAttrs ( lib . functionArgs drv ) scope ;
2020-04-24 23:36:52 +00:00
2022-01-13 20:06:32 +00:00
# Converts a returned function to a functor attribute set if necessary
ensureAttrs = v : if builtins . isFunction v then { __functor = _ : v ; } else v ;
2020-04-24 23:36:52 +00:00
# this wraps the `drv` function to add a `overrideScope` function to the result.
2022-01-13 20:06:32 +00:00
drvScope = allArgs : ensureAttrs ( drv allArgs ) // {
2020-04-24 23:36:52 +00:00
overrideScope = f :
let newScope = mkScope ( fix' ( extends f scope . __unfix__ ) ) ;
# note that we have to be careful here: `allArgs` includes the auto-arguments that
# weren't manually specified. If we would just pass `allArgs` to the recursive call here,
# then we wouldn't look up any packages in the scope in the next interation, because it
# appears as if all arguments were already manually passed, so the scope change would do
# nothing.
in callPackageWithScope newScope drv manualArgs ;
} ;
2021-02-05 17:12:51 +00:00
in lib . makeOverridable drvScope ( auto // manualArgs ) ;
2020-04-24 23:36:52 +00:00
mkScope = scope : let
ps = pkgs . __splicedPackages ;
scopeSpliced = pkgs . splicePackages {
pkgsBuildBuild = scope . buildHaskellPackages . buildHaskellPackages ;
pkgsBuildHost = scope . buildHaskellPackages ;
pkgsBuildTarget = { } ;
pkgsHostHost = { } ;
pkgsHostTarget = scope ;
pkgsTargetTarget = { } ;
} // {
# Don't splice these
inherit ( scope ) ghc buildHaskellPackages ;
} ;
in ps // ps . xorg // ps . gnome2 // { inherit stdenv ; } // scopeSpliced ;
defaultScope = mkScope self ;
callPackage = drv : args : callPackageWithScope defaultScope drv args ;
# Use cabal2nix to create a default.nix for the package sources found at 'src'.
haskellSrc2nix = { name , src , sha256 ? null , extraCabal2nixOptions ? " " }:
let
sha256Arg = if sha256 == null then " - - s h a 2 5 6 = " else '' - - s h a 2 5 6 = " ${ sha256 } " '' ;
2022-03-05 16:20:37 +00:00
in buildPackages . runCommand " c a b a l 2 n i x - ${ name } " {
2020-04-24 23:36:52 +00:00
nativeBuildInputs = [ buildPackages . cabal2nix-unwrapped ] ;
preferLocalBuild = true ;
allowSubstitutes = false ;
LANG = " e n _ U S . U T F - 8 " ;
LOCALE_ARCHIVE = pkgs . lib . optionalString ( buildPlatform . libc == " g l i b c " ) " ${ buildPackages . glibcLocales } / l i b / l o c a l e / l o c a l e - a r c h i v e " ;
2022-03-05 16:20:37 +00:00
} ''
export HOME = " $ T M P "
mkdir - p " $ o u t "
cabal2nix - - compiler = $ { self . ghc . haskellCompilerName } - - system = $ { hostPlatform . config } $ { sha256Arg } " ${ src } " $ { extraCabal2nixOptions } > " $ o u t / d e f a u l t . n i x "
'' ;
2020-04-24 23:36:52 +00:00
2022-09-09 14:08:57 +00:00
# Given a package name and version, e.g. name = "async", version = "2.2.4",
# gives its cabal file and hashes (JSON file) as discovered from the
# all-cabal-hashes value. If that's a directory, it will copy the relevant
# files to $out; if it's a tarball, it will extract and move them to $out.
2020-04-24 23:36:52 +00:00
all-cabal-hashes-component = name : version : buildPackages . runCommand " a l l - c a b a l - h a s h e s - c o m p o n e n t - ${ name } - ${ version } " { } ''
mkdir - p $ out
2022-09-09 14:08:57 +00:00
if [ - d $ { all-cabal-hashes } ]
then
cp $ { all-cabal-hashes } / $ { name } / $ { version } / $ { name } . json $ out
cp $ { all-cabal-hashes } / $ { name } / $ { version } / $ { name } . cabal $ out
else
tar - - wildcards - xzvf $ { all-cabal-hashes } \ * / $ { name } / $ { version } / $ { name } . { json , cabal }
mv * / $ { name } / $ { version } / $ { name } . { json , cabal } $ out
fi
2020-04-24 23:36:52 +00:00
'' ;
hackage2nix = name : version : let component = all-cabal-hashes-component name version ; in self . haskellSrc2nix {
name = " ${ name } - ${ version } " ;
sha256 = '' $( s e d - e ' s / . * " S H A 2 5 6 " : " / / ' - e ' s / " . * $/ / ' " ${ component } / ${ name } . j s o n " ) '' ;
src = " ${ component } / ${ name } . c a b a l " ;
} ;
2022-11-27 09:42:12 +00:00
# Adds a nix file derived from cabal2nix in the passthru of the derivation it
# produces. This is useful to debug callHackage / callCabal2nix by looking at
# the content of the nix file pointed by `cabal2nixDeriver`.
# However, it does not keep a reference to that file, which may be garbage
# collected, which may be an annoyance.
2020-04-24 23:36:52 +00:00
callPackageKeepDeriver = src : args :
2021-12-06 16:07:01 +00:00
overrideCabal ( orig : {
2020-04-24 23:36:52 +00:00
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 ;
} ;
2021-12-06 16:07:01 +00:00
} ) ( self . callPackage src args ) ;
2020-04-24 23:36:52 +00:00
2021-02-05 17:12:51 +00:00
in package-set { inherit pkgs lib callPackage ; } self // {
2020-04-24 23:36:52 +00:00
inherit mkDerivation callPackage haskellSrc2nix hackage2nix buildHaskellPackages ;
inherit ( haskellLib ) packageSourceOverrides ;
# callHackage :: Text -> Text -> AttrSet -> HaskellPackage
#
# e.g., while overriding a package set:
# '... foo = self.callHackage "foo" "1.5.3" {}; ...'
callHackage = name : version : callPackageKeepDeriver ( self . hackage2nix name version ) ;
# callHackageDirect
# :: { pkg :: Text, ver :: Text, sha256 :: Text }
# -> AttrSet
# -> HaskellPackage
#
# This function does not depend on all-cabal-hashes and therefore will work
# for any version that has been released on hackage as opposed to only
# versions released before whatever version of all-cabal-hashes you happen
# to be currently using.
callHackageDirect = { pkg , ver , sha256 }:
let pkgver = " ${ pkg } - ${ ver } " ;
in self . callCabal2nix pkg ( pkgs . fetchzip {
url = " m i r r o r : / / h a c k a g e / ${ pkgver } / ${ pkgver } . t a r . g z " ;
inherit sha256 ;
} ) ;
# Creates a Haskell package from a source package by calling cabal2nix on the source.
callCabal2nixWithOptions = name : src : extraCabal2nixOptions : args :
let
filter = path : type :
2021-12-06 16:07:01 +00:00
pkgs . lib . hasSuffix " . c a b a l " path ||
2020-04-24 23:36:52 +00:00
baseNameOf path == " p a c k a g e . y a m l " ;
expr = self . haskellSrc2nix {
inherit name extraCabal2nixOptions ;
src = if pkgs . lib . canCleanSource src
then pkgs . lib . cleanSourceWith { inherit src filter ; }
else src ;
} ;
2021-12-06 16:07:01 +00:00
in overrideCabal ( orig : {
2020-04-24 23:36:52 +00:00
inherit src ;
2021-12-06 16:07:01 +00:00
} ) ( callPackageKeepDeriver expr args ) ;
2020-04-24 23:36:52 +00:00
callCabal2nix = name : src : args : self . callCabal2nixWithOptions name src " " args ;
# : { root : Path
# , name : Defaulted String
# , source-overrides : Defaulted (Either Path VersionNumber)
# , overrides : Defaulted (HaskellPackageOverrideSet)
# , modifier : Defaulted
# , returnShellEnv : Defaulted
2020-11-15 13:44:38 +00:00
# , withHoogle : Defaulted
# , cabal2nixOptions : Defaulted
2020-04-24 23:36:52 +00:00
# } -> NixShellAwareDerivation
2020-11-15 13:44:38 +00:00
#
2020-04-24 23:36:52 +00:00
# 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.
2020-11-15 13:44:38 +00:00
#
# 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'.
2020-04-24 23:36:52 +00:00
developPackage =
{ root
2021-05-20 23:08:51 +00:00
, name ? if builtins . typeOf root == " p a t h " then builtins . baseNameOf root else " "
2020-04-24 23:36:52 +00:00
, source-overrides ? { }
, overrides ? self : super : { }
, modifier ? drv : drv
2020-11-15 13:44:38 +00:00
, returnShellEnv ? pkgs . lib . inNixShell
, withHoogle ? returnShellEnv
, cabal2nixOptions ? " " } :
2020-04-24 23:36:52 +00:00
let drv =
( extensible-self . extend
( pkgs . lib . composeExtensions
( self . packageSourceOverrides source-overrides )
overrides ) )
2020-11-15 13:44:38 +00:00
. callCabal2nixWithOptions name root cabal2nixOptions { } ;
in if returnShellEnv
then ( modifier drv ) . envFunc { inherit withHoogle ; }
else modifier drv ;
2020-04-24 23:36:52 +00:00
2022-01-13 20:06:32 +00:00
# This can be used to easily create a derivation containing GHC and the specified set of Haskell packages.
#
# Example:
# $ nix-shell -p 'haskellPackages.ghcWithPackages (hpkgs: [ hpkgs.mtl hpkgs.lens ])'
# $ ghci # in the nix-shell
# Prelude > import Control.Lens
#
# GHC is setup with a package database with all the specified Haskell packages.
#
# ghcWithPackages :: (HaskellPkgSet -> [ HaskellPkg ]) -> Derivation
ghcWithPackages = self . callPackage ./with-packages-wrapper.nix {
haskellPackages = self ;
} ;
2020-04-24 23:36:52 +00:00
2020-11-15 13:44:38 +00:00
# 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.
#
2022-01-13 20:06:32 +00:00
# Example usage:
# $ nix-shell -p 'haskellPackages.hoogleWithPackages (p: [ p.mtl p.lens ])'
# [nix-shell] $ hoogle server
#
# hoogleWithPackages :: (HaskellPkgSet -> [ HaskellPkg ]) -> Derivation
#
2020-11-15 13:44:38 +00:00
# To reload the Hoogle server automatically on .cabal file changes try
# this:
# echo *.cabal | entr -r -- nix-shell --run 'hoogle server --local'
2022-01-13 20:06:32 +00:00
hoogleWithPackages = self . callPackage ./hoogle.nix {
haskellPackages = self ;
} ;
hoogleLocal =
{ packages ? [ ] }:
lib . warn " h o o g l e L o c a l i s d e p r e c a t e d , u s e h o o g l e W i t h P a c k a g e s i n s t e a d " (
self . hoogleWithPackages ( _ : packages )
) ;
# This is like a combination of ghcWithPackages and hoogleWithPackages.
# It provides a derivation containing both GHC and Hoogle with an index of
# the given Haskell package database.
#
# Example:
# $ nix-shell -p 'haskellPackages.ghcWithHoogle (hpkgs: [ hpkgs.conduit hpkgs.lens ])'
#
# ghcWithHoogle :: (HaskellPkgSet -> [ HaskellPkg ]) -> Derivation
ghcWithHoogle = self . ghcWithPackages . override {
withHoogle = true ;
} ;
2020-04-24 23:36:52 +00:00
# Returns a derivation whose environment contains a GHC with only
# the dependencies of packages listed in `packages`, not the
# 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.
2020-11-06 00:33:48 +00:00
#
2020-04-24 23:36:52 +00:00
# In addition to the "packages" arg and "withHoogle" arg, anything that
# can be passed into stdenv.mkDerivation can be included in the input attrset
#
# # default.nix
# with import <nixpkgs> {};
2021-12-06 16:07:01 +00:00
# haskellPackages.extend (haskell.lib.compose.packageSourceOverrides {
2020-04-24 23:36:52 +00:00
# frontend = ./frontend;
# backend = ./backend;
# common = ./common;
# })
#
# # shell.nix
# let pkgs = import <nixpkgs> {} in
# (import ./.).shellFor {
# packages = p: [p.frontend p.backend p.common];
# withHoogle = true;
2020-11-06 00:33:48 +00:00
# buildInputs = [ pkgs.python pkgs.cabal-install ];
2020-04-24 23:36:52 +00:00
# }
#
# -- cabal.project
# packages:
# frontend/
# backend/
# common/
#
# bash$ nix-shell --run "cabal new-build all"
# bash$ nix-shell --run "python"
2020-11-06 00:33:48 +00:00
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
2021-02-05 17:12:51 +00:00
# An optional function that can modify the generic builder arguments
# for the fake package that shellFor uses to construct its environment.
#
# Example:
# let
# # elided...
# haskellPkgs = pkgs.haskell.packages.ghc884.override (hpArgs: {
# overrides = pkgs.lib.composeExtensions (hpArgs.overrides or (_: _: { })) (
# _hfinal: hprev: {
# mkDerivation = args: hprev.mkDerivation ({
# doCheck = false;
# doBenchmark = false;
# doHoogle = true;
# doHaddock = true;
# enableLibraryProfiling = false;
# enableExecutableProfiling = false;
# } // args);
# }
# );
# });
# in
2021-07-17 21:14:59 +00:00
# haskellPkgs.shellFor {
2021-02-05 17:12:51 +00:00
# packages = p: [ p.foo ];
# genericBuilderArgsModifier = args: args // { doCheck = true; doBenchmark = true };
# }
#
# This will disable tests and benchmarks for everything in "haskellPkgs"
# (which will invalidate the binary cache), and then re-enable them
# for the "shellFor" environment (ensuring that any test/benchmark
# dependencies for "foo" will be available within the nix-shell).
, genericBuilderArgsModifier ? ( args : args )
2022-03-30 09:31:56 +00:00
# Extra dependencies, in the form of cabal2nix build attributes.
#
# An example use case is when you have Haskell scripts that use
# libraries that don't occur in your packages' dependencies.
#
# Example:
#
# extraDependencies = p: {
# libraryHaskellDepends = [ p.releaser ];
# };
, extraDependencies ? p : { }
2020-11-06 00:33:48 +00:00
, . . .
} @ args :
2020-04-24 23:36:52 +00:00
let
2020-11-06 00:33:48 +00:00
# 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 =
2022-03-30 09:31:56 +00:00
pkgs . lib . zipAttrsWith ( _name : zipperCombinedPkgs ) ( cabalDepsForSelected ++ [ ( extraDependencies self ) ] ) ;
2020-11-06 00:33:48 +00:00
# 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 " p a c k a g e s " ;
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
2021-02-05 17:12:51 +00:00
pkgWithCombinedDeps = self . mkDerivation ( genericBuilderArgsModifier genericBuilderArgs ) ;
2020-11-06 00:33:48 +00:00
# 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 ; } ;
2022-03-30 09:31:56 +00:00
mkDerivationArgs = builtins . removeAttrs args [ " g e n e r i c B u i l d e r A r g s M o d i f i e r " " p a c k a g e s " " w i t h H o o g l e " " d o B e n c h m a r k " " e x t r a D e p e n d e n c i e s " ] ;
2020-11-06 00:33:48 +00:00
in pkgWithCombinedDepsDevDrv . overrideAttrs ( old : mkDerivationArgs // {
2020-04-24 23:36:52 +00:00
nativeBuildInputs = old . nativeBuildInputs ++ mkDerivationArgs . nativeBuildInputs or [ ] ;
buildInputs = old . buildInputs ++ mkDerivationArgs . buildInputs or [ ] ;
} ) ;
ghc = ghc // {
withPackages = self . ghcWithPackages ;
withHoogle = self . ghcWithHoogle ;
} ;
2022-07-14 12:49:19 +00:00
/*
Run ` cabal sdist ` on a source .
Unlike ` haskell . lib . sdistTarball ` , this does not require any dependencies
to be present , as it uses ` cabal-install ` instead of building ` Setup . hs ` .
This makes ` cabalSdist ` faster than ` sdistTarball ` .
* /
cabalSdist = {
src ,
name ? if src ? name then " ${ src . name } - s d i s t . t a r . g z " else " s o u r c e . t a r . g z "
} :
pkgs . runCommandLocal name
{
inherit src ;
2022-09-09 14:08:57 +00:00
nativeBuildInputs = [
buildHaskellPackages . cabal-install
# TODO after https://github.com/haskell/cabal/issues/8352
# remove ghc
self . ghc
] ;
2022-07-14 12:49:19 +00:00
dontUnpack = false ;
} ''
unpackPhase
cd " ' ' ${ sourceRoot:-. } "
patchPhase
mkdir out
HOME = $ PWD cabal sdist - - output-directory out
mv out /* . t a r . g z $ o u t
'' ;
/*
Like ` haskell . lib . buildFromSdist ` , but using ` cabal sdist ` instead of
building ` ./Setup ` .
Unlike ` haskell . lib . buildFromSdist ` , this does not require any dependencies
to be present . This makes ` buildFromCabalSdist ` faster than ` haskell . lib . buildFromSdist ` .
* /
buildFromCabalSdist = pkg :
haskellLib . overrideSrc
{
src = self . cabalSdist { inherit ( pkg ) src ; } ;
version = pkg . version ;
}
pkg ;
2022-10-21 18:38:19 +00:00
/*
Modify a Haskell package to add shell completion scripts for the
given executables produced by it . These completion scripts will be
picked up automatically if the resulting derivation is installed ,
e . g . by ` nix-env - i ` .
This depends on the ` - - * - completion ` flag ` optparse-applicative ` provides
automatically . Since we need to invoke installed executables , completions
are not generated if we are cross-compiling .
commands : names of the executables built by the derivation
pkg : Haskell package that builds the executables
Example :
generateOptparseApplicativeCompletions [ " e x e c 1 " " e x e c 2 " ] pkg
Type : [ str ] -> drv -> drv
* /
generateOptparseApplicativeCompletions =
self . callPackage (
{ stdenv }:
commands :
pkg :
if stdenv . buildPlatform . canExecute stdenv . hostPlatform
then lib . foldr haskellLib . __generateOptparseApplicativeCompletion pkg commands
else pkg
) { } ;
2020-04-24 23:36:52 +00:00
}