diff options
Diffstat (limited to 'nixpkgs/doc/languages-frameworks/haskell.section.md')
-rw-r--r-- | nixpkgs/doc/languages-frameworks/haskell.section.md | 190 |
1 files changed, 164 insertions, 26 deletions
diff --git a/nixpkgs/doc/languages-frameworks/haskell.section.md b/nixpkgs/doc/languages-frameworks/haskell.section.md index 87da2e63663a..60972331840a 100644 --- a/nixpkgs/doc/languages-frameworks/haskell.section.md +++ b/nixpkgs/doc/languages-frameworks/haskell.section.md @@ -23,7 +23,7 @@ installing and using them. All of these packages are originally defined in the `haskellPackages` package set and are re-exposed with a reduced dependency closure for convenience. -(see `justStaticExecutables` below) +(see `justStaticExecutables` or `separateBinOutput` below) The `haskellPackages` set includes at least one version of every package from Hackage as well as some manually injected packages. This amounts to a lot of @@ -45,16 +45,17 @@ The attribute names in `haskellPackages` always correspond with their name on Hackage. Since Hackage allows names that are not valid Nix without escaping, you need to take care when handling attribute names like `3dmodels`. -For packages that are part of [Stackage], we use the version prescribed by a -Stackage solver (usually the current LTS one) as the default version. For all -other packages we use the latest version from Hackage. See -[below](#haskell-available-versions) to learn which versions are provided -exactly. +For packages that are part of [Stackage] (a curated set of known to be +compatible packages), we use the version prescribed by a Stackage snapshot +(usually the current LTS one) as the default version. For all other packages we +use the latest version from [Hackage](https://hackage.org) (the repository of +basically all open source Haskell packages). See [below](#haskell-available- +versions) for a few more details on this. -Roughly half of the 16K packages contained in `haskellPackages` don't actually -build and are marked as broken semi-automatically. Most of those packages are -deprecated or unmaintained, but sometimes packages that should build, do not -build. Very often fixing them is not a lot of work. +Roughly half of the 16K packages contained in `haskellPackages` don’t actually +build and are [marked as broken semi-automatically](https://github.com/NixOS/nixpkgs/blob/haskell-updates/pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml). +Most of those packages are deprecated or unmaintained, but sometimes packages +that should build, do not build. Very often fixing them is not a lot of work. <!-- TODO(@sternenseemann): @@ -126,19 +127,23 @@ Every package set also re-exposes the GHC used to build its packages as `haskell ### Available package versions {#haskell-available-versions} We aim for a “blessed” package set which only contains one version of each -package, like Stackage (and based on it) but with more packages. Normally in -nixpkgs the number of building Haskell packages is roughly two to three times -the size of Stackage. For choosing the version to use for a certain package we -use the following rules: - -1. By default, for every package `haskellPackages.foo` is the newest version -found on Hackage (at the time of the last update of our package set). -2. If the Stackage snapshot that we use (usually the newest LTS snapshot) -contains a package, we use the Stackage version as default version for that -package. -3. For some packages, which are not on Stackage, we have manual overrides to -set the default version to a version older than the newest on Hackage. We do -this to get them or their reverse dependencies to compile in our package set. +package, like [Stackage], which is a curated set of known to be compatible +packages. We use the version information from Stackage snapshots and extend it +with more packages. Normally in Nixpkgs the number of building Haskell packages +is roughly two to three times the size of Stackage. For choosing the version to +use for a certain package we use the following rules: + +1. By default, for `haskellPackages.foo` is the newest version of the package +`foo` found on [Hackage](https://hackage.org), which is the central registry +of all open source Haskell packages. Nixpkgs contains a reference to a pinned +Hackage snapshot, thus we use the state of Hackage as of the last time we +updated this pin. +2. If the [Stackage] snapshot that we use (usually the newest LTS snapshot) +contains a package, [we use instead the version in the Stackage snapshot as +default version for that package.](https://github.com/NixOS/nixpkgs/blob/haskell-updates/pkgs/development/haskell-modules/configuration-hackage2nix/stackage.yaml) +3. For some packages, which are not on Stackage, we have if necessary [manual +overrides to set the default version to a version older than the newest on +Hackage.](https://github.com/NixOS/nixpkgs/blob/haskell-updates/pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml) 4. For all packages, for which the newest Hackage version is not the default version, there will also be a `haskellPackages.foo_x_y_z` package with the newest version. The `x_y_z` part encodes the version with dots replaced by @@ -146,9 +151,12 @@ underscores. When the newest version changes by a new release to Hackage the old package will disappear under that name and be replaced by a newer one under the name with the new version. The package name including the version will also disappear when the default version e.g. from Stackage catches up with the -newest version from Hackage. -5. For some packages, we also manually add other `haskellPackages.foo_x_y_z` -versions, if they are required for a certain build. +newest version from Hackage. E.g. if `haskellPackages.foo` gets updated from +1.0.0 to 1.1.0 the package `haskellPackages.foo_1_1_0` becomes obsolete and +gets dropped. +5. For some packages, we also [manually add other `haskellPackages.foo_x_y_z` +versions](https://github.com/NixOS/nixpkgs/blob/haskell-updates/pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml), +if they are required for a certain build. Relying on `haskellPackages.foo_x_y_z` attributes in derivations outside nixpkgs is discouraged because they may change or disappear with every package @@ -1066,6 +1074,18 @@ benchmark component. `dontCoverage drv` : Sets the `doCoverage` argument to `false` for `drv`. +`enableExecutableProfiling drv` +: Sets the `enableExecutableProfiling` argument to `true` for `drv`. + +`disableExecutableProfiling drv` +: Sets the `enableExecutableProfiling` argument to `false` for `drv`. + +`enableLibraryProfiling drv` +: Sets the `enableLibraryProfiling` argument to `true` for `drv`. + +`disableLibraryProfiling drv` +: Sets the `enableLibraryProfiling` argument to `false` for `drv`. + #### Library functions in the Haskell package sets {#haskell-package-set-lib-functions} Some library functions depend on packages from the Haskell package sets. Thus they are @@ -1140,6 +1160,124 @@ covered in the old [haskell4nix docs](https://haskell4nix.readthedocs.io/). If you feel any important topic is not documented at all, feel free to comment on the issue linked above. +### How to enable or disable profiling builds globally? {#haskell-faq-override-profiling} + +By default, Nixpkgs builds a profiling version of each Haskell library. The +exception to this rule are some platforms where it is disabled due to concerns +over output size. You may want to… + +* …enable profiling globally so that you can build a project you are working on + with profiling ability giving you insight in the time spent across your code + and code you depend on using [GHC's profiling feature][profiling]. + +* …disable profiling (globally) to reduce the time spent building the profiling + versions of libraries which a significant amount of build time is spent on + (although they are not as expensive as the “normal” build of a Haskell library). + +::: {.note} +The method described below affects the build of all libraries in the +respective Haskell package set as well as GHC. If your choices differ from +Nixpkgs' default for your (host) platform, you will lose the ability to +substitute from the official binary cache. + +If you are concerned about build times and thus want to disable profiling, it +probably makes sense to use `haskell.lib.compose.disableLibraryProfiling` (see +[](#haskell-trivial-helpers)) on the packages you are building locally while +continuing to substitute their dependencies and GHC. +::: + +Since we need to change the profiling settings for the desired Haskell package +set _and_ GHC (as the core libraries like `base`, `filepath` etc. are bundled +with GHC), it is recommended to use overlays for Nixpkgs to change them. +Since the interrelated parts, i.e. the package set and GHC, are connected +via the Nixpkgs fixpoint, we need to modify them both in a way that preserves +their connection (or else we'd have to wire it up again manually). This is +achieved by changing GHC and the package set in seperate overlays to prevent +the package set from pulling in GHC from `prev`. + +The result is two overlays like the ones shown below. Adjustable parts are +annotated with comments, as are any optional or alternative ways to achieve +the desired profiling settings without causing too many rebuilds. + +<!-- TODO(@sternenseemann): buildHaskellPackages != haskellPackages with this overlay, +affected by https://github.com/NixOS/nixpkgs/issues/235960 which needs to be fixed +properly still. +--> + +```nix +let + # Name of the compiler and package set you want to change. If you are using + # the default package set `haskellPackages`, you need to look up what version + # of GHC it currently uses (note that this is subject to change). + ghcName = "ghc92"; + # Desired new setting + enableProfiling = true; +in + +[ + # The first overlay modifies the GHC derivation so that it does or does not + # build profiling versions of the core libraries bundled with it. It is + # recommended to only use such an overlay if you are enabling profiling on a + # platform that doesn't by default, because compiling GHC from scratch is + # quite expensive. + (final: prev: + let + inherit (final) lib; + in + + { + haskell = lib.recursiveUpdate prev.haskell { + compiler.${ghcName} = prev.haskell.compiler.${ghcName}.override { + # Unfortunately, the GHC setting is named differently for historical reasons + enableProfiledLibs = enableProfiling; + }; + }; + }) + + (final: prev: + let + inherit (final) lib; + haskellLib = final.haskell.lib.compose; + in + + { + haskell = lib.recursiveUpdate prev.haskell { + packages.${ghcName} = prev.haskell.packages.${ghcName}.override { + overrides = hfinal: hprev: { + mkDerivation = args: hprev.mkDerivation (args // { + # Since we are forcing our ideas upon mkDerivation, this change will + # affect every package in the package set. + enableLibraryProfiling = enableProfiling; + + # To actually use profiling on an executable, executable profiling + # needs to be enabled for the executable you want to profile. You + # can either do this globally or… + enableExecutableProfiling = enableProfiling; + }); + + # …only for the package that contains an executable you want to profile. + # That saves on unnecessary rebuilds for packages that you only depend + # on for their library, but also contain executables (e.g. pandoc). + my-executable = haskellLib.enableExecutableProfiling hprev.my-executable; + + # If you are disabling profiling to save on build time, but want to + # retain the ability to substitute from the binary cache. Drop the + # override for mkDerivation above and instead have an override like + # this for the specific packages you are building locally and want + # to make cheaper to build. + my-library = haskellLib.disableLibraryProfiling hprev.my-library; + }; + }; + }; + }) +] +``` + +<!-- TODO(@sternenseemann): write overriding mkDerivation, overriding GHC, and +overriding the entire package set sections and link to them from here where +relevant. +--> + [Stackage]: https://www.stackage.org [cabal-project-files]: https://cabal.readthedocs.io/en/latest/cabal-project.html [cabal2nix]: https://github.com/nixos/cabal2nix |