diff options
-rw-r--r-- | doc/default.nix | 18 | ||||
-rw-r--r-- | doc/haskell-users-guide.md | 698 | ||||
-rw-r--r-- | doc/haskell-users-guide.xml | 912 |
3 files changed, 715 insertions, 913 deletions
diff --git a/doc/default.nix b/doc/default.nix index 004ffb70b749e..b8dac00eb65e9 100644 --- a/doc/default.nix +++ b/doc/default.nix @@ -6,7 +6,7 @@ stdenv.mkDerivation { sources = sourceFilesBySuffices ./. [".xml"]; - buildInputs = [ libxml2 libxslt ]; + buildInputs = [ pandoc libxml2 libxslt ]; xsltFlags = '' --param section.autolabel 1 @@ -19,6 +19,22 @@ stdenv.mkDerivation { ''; buildCommand = '' + { + echo "<chapter xmlns=\"http://docbook.org/ns/docbook\"" + echo " xmlns:xlink=\"http://www.w3.org/1999/xlink\"" + echo " xml:id=\"users-guide-to-the-haskell-infrastructure\">" + echo "" + echo "<title>User's Guide to the Haskell Infrastructure</title>" + echo "" + pandoc ${./haskell-users-guide.md} -w docbook | \ + sed -e 's|<ulink url=|<link xlink:href=|' \ + -e 's|</ulink>|</link>|' \ + -e 's|<sect. id=|<section xml:id=|' \ + -e 's|</sect[0-9]>|</section>|' + echo "" + echo "</chapter>" + } >haskell-users-guide.xml + ln -s "$sources/"*.xml . echo ${nixpkgsVersion} > .version diff --git a/doc/haskell-users-guide.md b/doc/haskell-users-guide.md new file mode 100644 index 0000000000000..b06a81e5b36a0 --- /dev/null +++ b/doc/haskell-users-guide.md @@ -0,0 +1,698 @@ +--- +title: User's Guide for Haskell in Nixpkgs +author: Peter Simons +date: 2015-06-01 +--- + +# How to install Haskell packages + +Nixpkgs distributes build instructions for all Haskell packages registered on +[Hackage](http://hackage.haskell.org/), but strangely enough normal Nix package +lookups don't seem to discover any of them, except for the default version of ghc, cabal-install, and stack: + + $ nix-env -i alex + error: selector ‘alex’ matches no derivations + $ nix-env -qa ghc + ghc-7.10.2 + +The Haskell package set is not registered in the top-level namespace because it +is *huge*. If all Haskell packages were visible to these commands, then +name-based search/install operations would be much slower than they are now. We +avoided that by keeping all Haskell-related packages in a separate attribute +set called `haskellPackages`, which the following command will list: + + $ nix-env -f "<nixpkgs>" -qaP -A haskellPackages + haskellPackages.a50 a50-0.5 + haskellPackages.abacate haskell-abacate-0.0.0.0 + haskellPackages.abcBridge haskell-abcBridge-0.12 + haskellPackages.afv afv-0.1.1 + haskellPackages.alex alex-3.1.4 + haskellPackages.Allure Allure-0.4.101.1 + haskellPackages.alms alms-0.6.7 + [... some 8000 entries omitted ...] + +To install any of those packages into your profile, refer to them by their +attribute path (first column): + + $ nix-env -f "<nixpkgs>" -iA haskellPackages.Allure ... + +The attribute path of any Haskell packages corresponds to the name of that +particular package on Hackage: the package `cabal-install` has the attribute +`haskellPackages.cabal-install`, and so on. (Actually, this convention causes +trouble with packages like `3dmodels` and `4Blocks`, because these names are +invalid identifiers in the Nix language. The issue of how to deal with these +rare corner cases is currently unresolved.) + +Haskell packages who's Nix name (second column) begins with a `haskell-` prefix +are packages that provide a library whereas packages without that prefix +provide just executables. Libraries may provide executables too, though: the +package `haskell-pandoc`, for example, installs both a library and an +application. You can install and use Haskell executables just like any other +program in Nixpkgs, but using Haskell libraries for development is a bit +trickier and we'll address that subject in great detail in section [How to +create a development environment]. + +Attribute paths are deterministic inside of Nixpkgs, but the path necessary to +reach Nixpkgs varies from system to system. We dodged that problem by giving +`nix-env` an explicit `-f "<nixpkgs>"` parameter, but if you call `nix-env` +without that flag, then chances are the invocation fails: + + $ nix-env -iA haskellPackages.cabal-install + error: attribute ‘haskellPackages’ in selection path + ‘haskellPackages.cabal-install’ not found + +On NixOS, for example, Nixpkgs does *not* exist in the top-level namespace by +default. To figure out the proper attribute path, it's easiest to query for the +path of a well-known Nixpkgs package, i.e.: + + $ nix-env -qaP coreutils + nixos.coreutils coreutils-8.23 + +If your system responds like that (most NixOS installations will), then the +attribute path to `haskellPackages` is `nixos.haskellPackages`. Thus, if you +want to use `nix-env` without giving an explicit `-f` flag, then that's the way +to do it: + + $ nix-env -qaP -A nixos.haskellPackages + $ nix-env -iA nixos.haskellPackages.cabal-install + +Our current default compiler is GHC 7.10.x and the `haskellPackages` set +contains packages built with that particular version. Nixpkgs contains the +latest major release of every GHC since 6.10.4, however, and there is a whole +family of package sets available that defines Hackage packages built with each +of those compilers, too: + + $ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc6123 + $ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc763 + +The name `haskellPackages` is really just a synonym for +`haskell.packages.ghc7102`, because we prefer that package set internally and +recommend it to our users as their default choice, but ultimately you are free +to compile your Haskell packages with any GHC version you please. The following +command displays the complete list of available compilers: + + $ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler + haskell.compiler.ghc6104 ghc-6.10.4 + haskell.compiler.ghc6123 ghc-6.12.3 + haskell.compiler.ghc704 ghc-7.0.4 + haskell.compiler.ghc722 ghc-7.2.2 + haskell.compiler.ghc742 ghc-7.4.2 + haskell.compiler.ghc763 ghc-7.6.3 + haskell.compiler.ghc784 ghc-7.8.4 + haskell.compiler.ghc7102 ghc-7.10.2 + haskell.compiler.ghcHEAD ghc-7.11.20150402 + haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704 + haskell.compiler.ghcjs ghcjs-0.1.0 + haskell.compiler.jhc jhc-0.8.2 + haskell.compiler.uhc uhc-1.1.9.0 + +We have no package sets for `jhc` or `uhc` yet, unfortunately, but for every +version of GHC listed above, there exists a package set based on that compiler. +Also, the attributes `haskell.compiler.ghcXYC` and +`haskell.packages.ghcXYC.ghc` are synonymous for the sake of convenience. + +# How to create a development environment + +## How to install a compiler + +A simple development environment consists of a Haskell compiler and the tool +`cabal-install`, and we saw in section [How to install Haskell packages] how +you can install those programs into your user profile: + + $ nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install + +Instead of the default package set `haskellPackages`, you can also use the more +precise name `haskell.compiler.ghc7102`, which has the advantage that it refers +to the same GHC version regardless of what Nixpkgs considers "default" at any +given time. + +Once you've made those tools available in `$PATH`, it's possible to build +Hackage packages the same way people without access to Nix do it all the time: + + $ cabal get lens-4.11 && cd lens-4.11 + $ cabal install -j --dependencies-only + $ cabal configure + $ cabal build + +If you enjoy working with Cabal sandboxes, then that's entirely possible too: +just execute the command + + $ cabal sandbox init + +before installing the required dependencies. + +The `nix-shell` utility makes it easy to switch to a different compiler +version; just enter the Nix shell environment with the command + + $ nix-shell -p haskell.compiler.ghc784 + +to bring GHC 7.8.4 into `$PATH`. Re-running `cabal configure` switches your +build to use that compiler instead. If you're working on a project that doesn't +depend on any additional system libraries outside of GHC, then it's sufficient +even to run the `cabal configure` command inside of the shell: + + $ nix-shell -p haskell.compiler.ghc784 --command "cabal configure" + +Afterwards, all other commands like `cabal build` work just fine in any shell +environment, because the configure phase recorded the absolute paths to all +required tools like GHC in its build configuration inside of the `dist/` +directory. Please note, however, that `nix-collect-garbage` can break such an +environment because the Nix store paths created by `nix-shell` aren't "alive" +anymore once `nix-shell` has terminated. If you find that your Haskell builds +no longer work after garbage collection, then you'll have to re-run `cabal +configure` inside of a new `nix-shell` environment. + +## How to install a compiler with libraries + +GHC expects to find all installed libraries inside of its own `lib` directory. +This approach works fine on traditional Unix systems, but it doesn't work for +Nix, because GHC's store path is immutable once it's built. We cannot install +additional libraries into that location. As a consequence, our copies of GHC +don't know any packages except their own core libraries, like `base`, +`containers`, `Cabal`, etc. + +We can register additional libraries to GHC, however, using a special build +function called `ghcWithPackages`. That function expects one argument: a +function that maps from an attribute set of Haskell packages to a list of +packages, which determines the libraries known to that particular version of +GHC. For example, the Nix expression `ghcWithPackages (pkgs: [pkgs.mtl])` +generates a copy of GHC that has the `mtl` library registered in addition to +its normal core packages: + + $ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.mtl])" + + [nix-shell:~]$ ghc-pkg list mtl + /nix/store/zy79...-ghc-7.10.2/lib/ghc-7.10.2/package.conf.d: + mtl-2.2.1 + +This function allows users to define their own development environment by means +of an override. After adding the following snippet to `~/.nixpkgs/config.nix`, + + { + packageOverrides = super: let self = super.pkgs; in + { + myHaskellEnv = self.haskell.packages.ghc7102.ghcWithPackages + (haskellPackages: with haskellPackages; [ + # libraries + arrows async cgi criterion + # tools + cabal-install haskintex + ]); + }; + } + +it's possible to install that compiler with `nix-env -f "<nixpkgs>" -iA +myHaskellEnv`. If you'd like to switch that development environment to a +different version of GHC, just replace the `ghc7102` bit in the previous +definition with the appropriate name. Of course, it's also possible to define +any number of these development environments! (You can't install two of them +into the same profile at the same time, though, because that would result in +file conflicts.) + +The generated `ghc` program is a wrapper script that re-directs the real +GHC executable to use a new `lib` directory --- one that we specifically +constructed to contain all those packages the user requested: + + $ cat $(type -p ghc) + #! /nix/store/xlxj...-bash-4.3-p33/bin/bash -e + export NIX_GHC=/nix/store/19sm...-ghc-7.10.2/bin/ghc + export NIX_GHCPKG=/nix/store/19sm...-ghc-7.10.2/bin/ghc-pkg + export NIX_GHC_DOCDIR=/nix/store/19sm...-ghc-7.10.2/share/doc/ghc/html + export NIX_GHC_LIBDIR=/nix/store/19sm...-ghc-7.10.2/lib/ghc-7.10.2 + exec /nix/store/j50p...-ghc-7.10.2/bin/ghc "-B$NIX_GHC_LIBDIR" "$@" + +The variables `$NIX_GHC`, `$NIX_GHCPKG`, etc. point to the *new* store path +`ghcWithPackages` constructed specifically for this environment. The last line +of the wrapper script then executes the real `ghc`, but passes the path to the +new `lib` directory using GHC's `-B` flag. + +The purpose of those environment variables is to work around an impurity in the +popular [ghc-paths](http://hackage.haskell.org/package/ghc-paths) library. That +library promises to give its users access to GHC's installation paths. Only, +the library can't possible know that path when it's compiled, because the path +GHC considers its own is determined only much later, when the user configures +it through `ghcWithPackages`. So we [patched +ghc-paths](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/ghc-paths-nix.patch) +to return the paths found in those environment variables at run-time rather +than trying to guess them at compile-time. + +To make sure that mechanism works properly all the time, we recommend that you +set those variables to meaningful values in your shell environment, too, i.e. +by adding the following code to your `~/.bashrc`: + + if type >/dev/null 2>&1 -p ghc; then + eval "$(egrep ^export "$(type -p ghc)")" + fi + +If you are certain that you'll use only one GHC environment which is located in +your user profile, then you can use the following code, too, which has the +advantage that it doesn't contain any paths from the Nix store, i.e. those +settings always remain valid even if a `nix-env -u` operation updates the GHC +environment in your profile: + + if [ -e ~/.nix-profile/bin/ghc ]; then + export NIX_GHC="$HOME/.nix-profile/bin/ghc" + export NIX_GHCPKG="$HOME/.nix-profile/bin/ghc-pkg" + export NIX_GHC_DOCDIR="$HOME/.nix-profile/share/doc/ghc/html" + export NIX_GHC_LIBDIR="$HOME/.nix-profile/lib/ghc-$($NIX_GHC --numeric-version)" + fi + +## How to install a compiler with libraries, hoogle and documentation indexes + +If you plan to use your environment for interactive programming, not just +compiling random Haskell code, you might want to replace `ghcWithPackages` in +all the listings above with `ghcWithHoogle`. + +This environment generator not only produces an environment with GHC and all +the specified libraries, but also generates a `hoogle` and `haddock` indexes +for all the packages, and provides a wrapper script around `hoogle` binary that +uses all those things. A precise name for this thing would be +"`ghcWithPackagesAndHoogleAndDocumentationIndexes`", which is, regrettably, too +long and scary. + +For example, installing the following environment + + { + packageOverrides = super: let self = super.pkgs; in + { + myHaskellEnv = self.haskellPackages.ghcWithHoogle + (haskellPackages: with haskellPackages; [ + # libraries + arrows async cgi criterion + # tools + cabal-install haskintex + ]); + }; + } + +allows one to browse module documentation index [not too dissimilar to +this](https://downloads.haskell.org/~ghc/latest/docs/html/libraries/index.html) +for all the specified packages and their dependencies by directing a browser of +choice to `~/.nix-profiles/share/doc/hoogle/index.html` (or +`/run/current-system/sw/share/doc/hoogle/index.html` in case you put it in +`environment.systemPackages` in NixOS). + +After you've marveled enough at that try adding the following to your +`~/.ghc/ghci.conf` + + :def hoogle \s -> return $ ":! hoogle search -cl --count=15 \"" ++ s ++ "\"" + :def doc \s -> return $ ":! hoogle search -cl --info \"" ++ s ++ "\"" + +and test it by typing into `ghci`: + + :hoogle a -> a + :doc a -> a + +Be sure to note the links to `haddock` files in the output. With any modern and +properly configured terminal emulator you can just click those links to +navigate there. + +Finally, you can run + + hoogle server -p 8080 + +and navigate to http://localhost:8080/ for your own local +[Hoogle](https://www.haskell.org/hoogle/). Note, however, that Firefox and +possibly other browsers disallow navigation from `http:` to `file:` URIs for +security reasons, which might be quite an inconvenience. See [this +page](http://kb.mozillazine.org/Links_to_local_pages_do_not_work) for +workarounds. + + +## How to create ad hoc environments for `nix-shell` + +The easiest way to create an ad hoc development environment is to run +`nix-shell` with the appropriate GHC environment given on the command-line: + + nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [mtl pandoc])" + +For more sophisticated use-cases, however, it's more convenient to save the +desired configuration in a file called `shell.nix` that looks like this: + + { nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }: + let + inherit (nixpkgs) pkgs; + ghc = pkgs.haskell.packages.${compiler}.ghcWithPackages (ps: with ps; [ + monad-par mtl + ]); + in + pkgs.stdenv.mkDerivation { + name = "my-haskell-env-0"; + buildInputs = [ ghc ]; + shellHook = "eval $(egrep ^export ${ghc}/bin/ghc)"; + } + +Now run `nix-shell` --- or even `nix-shell --pure` --- to enter a shell +environment that has the appropriate compiler in `$PATH`. If you use `--pure`, +then add all other packages that your development environment needs into the +`buildInputs` attribute. If you'd like to switch to a different compiler +version, then pass an appropriate `compiler` argument to the expression, i.e. +`nix-shell --argstr compiler ghc784`. + +If you need such an environment because you'd like to compile a Hackage package +outside of Nix --- i.e. because you're hacking on the latest version from Git +---, then the package set provides suitable nix-shell environments for you +already! Every Haskell package has an `env` attribute that provides a shell +environment suitable for compiling that particular package. If you'd like to +hack the `lens` library, for example, then you just have to check out the +source code and enter the appropriate environment: + + $ cabal get lens-4.11 && cd lens-4.11 + Downloading lens-4.11... + Unpacking to lens-4.11/ + + $ nix-shell "<nixpkgs>" -A haskellPackages.lens.env + [nix-shell:/tmp/lens-4.11]$ + +At point, you can run `cabal configure`, `cabal build`, and all the other +development commands. Note that you need `cabal-install` installed in your +`$PATH` already to use it here --- the `nix-shell` environment does not provide +it. + +# How to create Nix builds for your own private Haskell packages + +If your own Haskell packages have build instructions for Cabal, then you can +convert those automatically into build instructions for Nix using the +`cabal2nix` utility, which you can install into your profile by running +`nix-env -i cabal2nix`. + +## How to build a stand-alone project + +For example, let's assume that you're working on a private project called +`foo`. To generate a Nix build expression for it, change into the project's +top-level directory and run the command: + + $ cabal2nix . >foo.nix + +Then write the following snippet into a file called `default.nix`: + + { nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }: + nixpkgs.pkgs.haskell.packages.${compiler}.callPackage ./foo.nix { } + +Finally, store the following code in a file called `shell.nix`: + + { nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }: + (import ./default.nix { inherit nixpkgs compiler; }).env + +At this point, you can run `nix-build` to have Nix compile your project and +install it into a Nix store path. The local directory will contain a symlink +called `result` after `nix-build` returns that points into that location. Of +course, passing the flag `--argstr compiler ghc763` allows switching the build +to any version of GHC currently supported. + +Furthermore, you can call `nix-shell` to enter an interactive development +environment in which you can use `cabal configure` and `cabal build` to develop +your code. That environment will automatically contain a proper GHC derivation +with all the required libraries registered as well as all the system-level +libraries your package might need. + +If your package does not depend on any system-level libraries, then it's +sufficient to run + + $ nix-shell --command "cabal configure" + +once to set up your build. `cabal-install` determines the absolute paths to all +resources required for the build and writes them into a config file in the +`dist/` directory. Once that's done, you can run `cabal build` and any other +command for that project even outside of the `nix-shell` environment. This +feature is particularly nice for those of us who like to edit their code with +an IDE, like Emacs' `haskell-mode`, because it's not necessary to start Emacs +inside of nix-shell just to make it find out the necessary settings for +building the project; `cabal-install` has already done that for us. + +If you want to do some quick-and-dirty hacking and don't want to bother setting +up a `default.nix` and `shell.nix` file manually, then you can use the +`--shell` flag offered by `cabal2nix` to have it generate a stand-alone +`nix-shell` environment for you. With that feature, running + + $ cabal2nix --shell . >shell.nix + $ nix-shell --command "cabal configure" + +is usually enough to set up a build environment for any given Haskell package. +You can even use that generated file to run `nix-build`, too: + + $ nix-build shell.nix + +## How to build projects that depend on each other + +If you have multiple private Haskell packages that depend on each other, then +you'll have to register those packages in the Nixpkgs set to make them visible +for the dependency resolution performed by `callPackage`. First of all, change +into each of your projects top-level directories and generate a `default.nix` +file with `cabal2nix`: + + $ cd ~/src/foo && cabal2nix . >default.nix + $ cd ~/src/bar && cabal2nix . >default.nix + +Then edit your `~/.nixpkgs/config.nix` file to register those builds in the +default Haskell package set: + + { + packageOverrides = super: let self = super.pkgs; in + { + haskellPackages = super.haskellPackages.override { + overrides = self: super: { + foo = self.callPackage ../src/foo {}; + bar = self.callPackage ../src/bar {}; + }; + }; + }; + } + +Once that's accomplished, `nix-env -f "<nixpkgs>" -qA haskellPackages` will +show your packages like any other package from Hackage, and you can build them + + $ nix-build "<nixpkgs>" -A haskellPackages.foo + +or enter an interactive shell environment suitable for building them: + + $ nix-shell "<nixpkgs>" -A haskellPackages.bar.env + +# Miscellaneous Topics + +## How to build with profiling enabled + +Every Haskell package set takes a function called `overrides` that you can use +to manipulate the package as much as you please. One useful application of this +feature is to replace the default `mkDerivation` function with one that enables +library profiling for all packages. To accomplish that, add configure the +following snippet in your `~/.nixpkgs/config.nix` file: + + { + packageOverrides = super: let self = super.pkgs; in + { + profiledHaskellPackages = self.haskellPackages.override { + overrides = self: super: { + mkDerivation = args: super.mkDerivation (args // { + enableLibraryProfiling = true; + }); + }; + }; + }; + } + +Then, replace instances of `haskellPackages` in the `cabal2nix`-generated +`default.nix` or `shell.nix` files with `profiledHaskellPackages`. + +## How to override package versions in a compiler-specific package set + +Nixpkgs provides the latest version of +[`ghc-events`](http://hackage.haskell.org/package/ghc-events), which is 0.4.4.0 +at the time of this writing. This is fine for users of GHC 7.10.x, but GHC +7.8.4 cannot compile that binary. Now, one way to solve that problem is to +register an older version of `ghc-events` in the 7.8.x-specific package set. +The first step is to generate Nix build instructions with `cabal2nix`: + + $ cabal2nix cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix + +Then add the override in `~/.nixpkgs/config.nix`: + + { + packageOverrides = super: let self = super.pkgs; in + { + haskell = super.haskell // { + packages = super.haskell.packages // { + ghc784 = super.haskell.packages.ghc784.override { + overrides = self: super: { + ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {}; + }; + }; + }; + }; + }; + } + +This code is a little crazy, no doubt, but it's necessary because the intuitive +version + + haskell.packages.ghc784 = super.haskell.packages.ghc784.override { + overrides = self: super: { + ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {}; + }; + }; + +doesn't do what we want it to: that code replaces the `haskell` package set in +Nixpkgs with one that contains only one entry,`packages`, which contains only +one entry `ghc784`. This override loses the `haskell.compiler` set, and it +loses the `haskell.packages.ghcXYZ` sets for all compilers but GHC 7.8.4. To +avoid that problem, we have to perform the convoluted little dance from above, +iterating over each step in hierarchy. + +Once it's accomplished, however, we can install a variant of `ghc-events` +that's compiled with GHC 7.8.4: + + nix-env -f "<nixpkgs>" -iA haskell.packages.ghc784.ghc-events + +Unfortunately, it turns out that this build fails again while executing the +test suite! Apparently, the release archive on Hackage is missing some data +files that the test suite requires, so we cannot run it. We accomplish that by +re-generating the Nix expression with the `--no-check` flag: + + $ cabal2nix --no-check cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix + +Now the builds succeeds. + +Of course, in the concrete example of `ghc-events` this whole exercise is not +an ideal solution, because `ghc-events` can analyze the output emitted by any +version of GHC later than 6.12 regardless of the compiler version that was used +to build the `ghc-events' executable, so strictly speaking there's no reason to +prefer one built with GHC 7.8.x in the first place. However, for users who +cannot use GHC 7.10.x at all for some reason, the approach of downgrading to an +older version might be useful. + +## How to recover from GHC's infamous non-deterministic library ID bug + +GHC and distributed build farms don't get along well: + + https://ghc.haskell.org/trac/ghc/ticket/4012 + +When you see an error like this one + + package foo-0.7.1.0 is broken due to missing package + text-1.2.0.4-98506efb1b9ada233bb5c2b2db516d91 + +then you have to download and re-install `foo` and all its dependents from +scratch: + + # nix-store -q --referrers /nix/store/*-haskell-text-1.2.0.4 \ + | xargs -L 1 nix-store --repair-path --option binary-caches http://hydra.nixos.org + +If you're using additional Hydra servers other than `hydra.nixos.org`, then it +might be necessary to purge the local caches that store data from those +machines to disable these binary channels for the duration of the previous +command, i.e. by running: + + rm /nix/var/nix/binary-cache-v3.sqlite + rm /nix/var/nix/manifests/* + rm /nix/var/nix/channel-cache/* + +## Builds on Darwin fail with `math.h` not found + +Users of GHC on Darwin have occasionally reported that builds fail, because the +compiler complains about a missing include file: + + fatal error: 'math.h' file not found + +The issue has been discussed at length in [ticket +6390](https://github.com/NixOS/nixpkgs/issues/6390), and so far no good +solution has been proposed. As a work-around, users who run into this problem +can configure the environment variables + + export NIX_CFLAGS_COMPILE="-idirafter /usr/include" + export NIX_CFLAGS_LINK="-L/usr/lib" + +in their `~/.bashrc` file to avoid the compiler error. + +## Using Stack together with Nix + + -- While building package zlib-0.5.4.2 using: + runhaskell -package=Cabal-1.22.4.0 -clear-package-db [... lots of flags ...] + Process exited with code: ExitFailure 1 + Logs have been written to: /home/foo/src/stack-ide/.stack-work/logs/zlib-0.5.4.2.log + + Configuring zlib-0.5.4.2... + Setup.hs: Missing dependency on a foreign library: + * Missing (or bad) header file: zlib.h + This problem can usually be solved by installing the system package that + provides this library (you may need the "-dev" version). If the library is + already installed but in a non-standard location then you can use the flags + --extra-include-dirs= and --extra-lib-dirs= to specify where it is. + If the header file does exist, it may contain errors that are caught by the C + compiler at the preprocessing stage. In this case you can re-run configure + with the verbosity flag -v3 to see the error messages. + +When you run the build inside of the nix-shell environment, the system +is configured to find libz.so without any special flags -- the compiler +and linker "just know" how to find it. Consequently, Cabal won't record +any search paths for libz.so in the package description, which means +that the package works fine inside of nix-shell, but once you leave the +shell the shared object can no longer be found. That issue is by no +means specific to Stack: you'll have that problem with any other +Haskell package that's built inside of nix-shell but run outside of that +environment. + +I suppose we could try to remedy the issue by wrapping `stack` or +`cabal` with a script that tries to find those kind of implicit search +paths and makes them explicit on the "cabal configure" command line. I +don't think anyone is working on that subject yet, though, because the +problem doesn't seem so bad in practice. + +You can remedy that issue in several ways. First of all, run + + $ nix-build --no-out-link "<nixpkgs>" -A zlib + /nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8 + +to find out the store path of the system's zlib library. Now, you can + +1) add that path (plus a "/lib" suffix) to your $LD_LIBRARY_PATH + environment variable to make sure your system linker finds libz.so + automatically. It's no pretty solution, but it will work. + +2) As a variant of (1), you can also install any number of system + libraries into your user's profile (or some other profile) and point + $LD_LIBRARY_PATH to that profile instead, so that you don't have to + list dozens of those store paths all over the place. + +3) The solution I prefer is to call stack with an appropriate + --extra-lib-dirs flag like so: + + $ stack --extra-lib-dirs=/nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8/lib build + + Typically, you'll need --extra-include-dirs as well. It's possible + to add those flag to the project's "stack.yaml" or your user's + global "~/.stack/global/stack.yaml" file so that you don't have to + specify them manually every time. + + The same thing applies to `cabal configure`, of course, if you're + building with `cabal-install` instead of Stack. + + +# Other resources + +- The Youtube video [Nix Loves Haskell](https://www.youtube.com/watch?v=BsBhi_r-OeE) + provides an introduction into Haskell NG aimed at beginners. The slides are + available at http://cryp.to/nixos-meetup-3-slides.pdf and also -- in a form + ready for cut & paste -- at + https://github.com/NixOS/cabal2nix/blob/master/doc/nixos-meetup-3-slides.md. + +- Another Youtube video is [Escaping Cabal Hell with Nix](https://www.youtube.com/watch?v=mQd3s57n_2Y), + which discusses the subject of Haskell development with Nix but also provides + a basic introduction to Nix as well, i.e. it's suitable for viewers with + almost no prior Nix experience. + +- Oliver Charles wrote a very nice [Tutorial how to develop Haskell packages with Nix](http://wiki.ocharles.org.uk/Nix). + +- The *Journey into the Haskell NG infrastructure* series of postings + describe the new Haskell infrastructure in great detail: + + - [Part 1](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015591.html) + explains the differences between the old and the new code and gives + instructions how to migrate to the new setup. + + - [Part 2](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015608.html) + looks in-depth at how to tweak and configure your setup by means of + overrides. + + - [Part 3](http://lists.science.uu.nl/pipermail/nix-dev/2015-April/016912.html) + describes the infrastructure that keeps the Haskell package set in Nixpkgs + up-to-date. diff --git a/doc/haskell-users-guide.xml b/doc/haskell-users-guide.xml deleted file mode 100644 index 2e9fd4b4ca0e0..0000000000000 --- a/doc/haskell-users-guide.xml +++ /dev/null @@ -1,912 +0,0 @@ -<chapter xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xml:id="users-guide-to-the-haskell-infrastructure"> - -<title>User's Guide to the Haskell Infrastructure</title> - -<section xml:id="how-to-install-haskell-packages"> - <title>How to install Haskell packages</title> - <para> - Nixpkgs distributes build instructions for all Haskell packages - registered on - <link xlink:href="http://hackage.haskell.org/">Hackage</link>, but - strangely enough normal Nix package lookups don't seem to discover - any of them, except for the default version of ghc, cabal-install, and stack: - </para> - <programlisting> -$ nix-env -i alex -error: selector ‘alex’ matches no derivations -$ nix-env -qa ghc -ghc-7.10.2 -</programlisting> - <para> - The Haskell package set is not registered in the top-level namespace - because it is <emphasis>huge</emphasis>. If all Haskell packages - were visible to these commands, then name-based search/install - operations would be much slower than they are now. We avoided that - by keeping all Haskell-related packages in a separate attribute set - called <literal>haskellPackages</literal>, which the following - command will list: - </para> - <programlisting> -$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages -haskellPackages.a50 a50-0.5 -haskellPackages.abacate haskell-abacate-0.0.0.0 -haskellPackages.abcBridge haskell-abcBridge-0.12 -haskellPackages.afv afv-0.1.1 -haskellPackages.alex alex-3.1.4 -haskellPackages.Allure Allure-0.4.101.1 -haskellPackages.alms alms-0.6.7 -[... some 8000 entries omitted ...] -</programlisting> - <para> - To install any of those packages into your profile, refer to them by - their attribute path (first column): - </para> - <programlisting> -$ nix-env -f "<nixpkgs>" -iA haskellPackages.Allure ... -</programlisting> - <para> - The attribute path of any Haskell packages corresponds to the name - of that particular package on Hackage: the package - <literal>cabal-install</literal> has the attribute - <literal>haskellPackages.cabal-install</literal>, and so on. - (Actually, this convention causes trouble with packages like - <literal>3dmodels</literal> and <literal>4Blocks</literal>, because - these names are invalid identifiers in the Nix language. The issue - of how to deal with these rare corner cases is currently - unresolved.) - </para> - <para> - Haskell packages who's Nix name (second column) begins with a - <literal>haskell-</literal> prefix are packages that provide a - library whereas packages without that prefix provide just - executables. Libraries may provide executables too, though: the - package <literal>haskell-pandoc</literal>, for example, installs - both a library and an application. You can install and use Haskell - executables just like any other program in Nixpkgs, but using - Haskell libraries for development is a bit trickier and we'll - address that subject in great detail in section - <link linkend="how-to-create-a-development-environment">How to - create a development environment</link>. - </para> - <para> - Attribute paths are deterministic inside of Nixpkgs, but the path - necessary to reach Nixpkgs varies from system to system. We dodged - that problem by giving <literal>nix-env</literal> an explicit - <literal>-f "<nixpkgs>"</literal> parameter, but if - you call <literal>nix-env</literal> without that flag, then chances - are the invocation fails: - </para> - <programlisting> -$ nix-env -iA haskellPackages.cabal-install -error: attribute ‘haskellPackages’ in selection path - ‘haskellPackages.cabal-install’ not found -</programlisting> - <para> - On NixOS, for example, Nixpkgs does <emphasis>not</emphasis> exist - in the top-level namespace by default. To figure out the proper - attribute path, it's easiest to query for the path of a well-known - Nixpkgs package, i.e.: - </para> - <programlisting> -$ nix-env -qaP coreutils -nixos.coreutils coreutils-8.23 -</programlisting> - <para> - If your system responds like that (most NixOS installations will), - then the attribute path to <literal>haskellPackages</literal> is - <literal>nixos.haskellPackages</literal>. Thus, if you want to - use <literal>nix-env</literal> without giving an explicit - <literal>-f</literal> flag, then that's the way to do it: - </para> - <programlisting> -$ nix-env -qaP -A nixos.haskellPackages -$ nix-env -iA nixos.haskellPackages.cabal-install -</programlisting> - <para> - Our current default compiler is GHC 7.10.x and the - <literal>haskellPackages</literal> set contains packages built with - that particular version. Nixpkgs contains the latest major release - of every GHC since 6.10.4, however, and there is a whole family of - package sets available that defines Hackage packages built with each - of those compilers, too: - </para> - <programlisting> -$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc6123 -$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc763 -</programlisting> - <para> - The name <literal>haskellPackages</literal> is really just a synonym - for <literal>haskell.packages.ghc7102</literal>, because we prefer - that package set internally and recommend it to our users as their - default choice, but ultimately you are free to compile your Haskell - packages with any GHC version you please. The following command - displays the complete list of available compilers: - </para> - <programlisting> -$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler -haskell.compiler.ghc6104 ghc-6.10.4 -haskell.compiler.ghc6123 ghc-6.12.3 -haskell.compiler.ghc704 ghc-7.0.4 -haskell.compiler.ghc722 ghc-7.2.2 -haskell.compiler.ghc742 ghc-7.4.2 -haskell.compiler.ghc763 ghc-7.6.3 -haskell.compiler.ghc784 ghc-7.8.4 -haskell.compiler.ghc7102 ghc-7.10.2 -haskell.compiler.ghcHEAD ghc-7.11.20150402 -haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704 -haskell.compiler.ghcjs ghcjs-0.1.0 -haskell.compiler.jhc jhc-0.8.2 -haskell.compiler.uhc uhc-1.1.9.0 -</programlisting> - <para> - We have no package sets for <literal>jhc</literal> or - <literal>uhc</literal> yet, unfortunately, but for every version of - GHC listed above, there exists a package set based on that compiler. - Also, the attributes <literal>haskell.compiler.ghcXYC</literal> and - <literal>haskell.packages.ghcXYC.ghc</literal> are synonymous for - the sake of convenience. - </para> -</section> -<section xml:id="how-to-create-a-development-environment"> - <title>How to create a development environment</title> - <section xml:id="how-to-install-a-compiler"> - <title>How to install a compiler</title> - <para> - A simple development environment consists of a Haskell compiler - and the tool <literal>cabal-install</literal>, and we saw in - section <link linkend="how-to-install-haskell-packages">How to - install Haskell packages</link> how you can install those programs - into your user profile: - </para> - <programlisting> -$ nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install -</programlisting> - <para> - Instead of the default package set - <literal>haskellPackages</literal>, you can also use the more - precise name <literal>haskell.compiler.ghc7102</literal>, which - has the advantage that it refers to the same GHC version - regardless of what Nixpkgs considers "default" at any - given time. - </para> - <para> - Once you've made those tools available in - <literal>$PATH</literal>, it's possible to build Hackage packages - the same way people without access to Nix do it all the time: - </para> - <programlisting> -$ cabal get lens-4.11 && cd lens-4.11 -$ cabal install -j --dependencies-only -$ cabal configure -$ cabal build -</programlisting> - <para> - If you enjoy working with Cabal sandboxes, then that's entirely - possible too: just execute the command - </para> - <programlisting> -$ cabal sandbox init -</programlisting> - <para> - before installing the required dependencies. - </para> - <para> - The <literal>nix-shell</literal> utility makes it easy to switch - to a different compiler version; just enter the Nix shell - environment with the command - </para> - <programlisting> -$ nix-shell -p haskell.compiler.ghc784 -</programlisting> - <para> - to bring GHC 7.8.4 into <literal>$PATH</literal>. Re-running - <literal>cabal configure</literal> switches your build to use that - compiler instead. If you're working on a project that doesn't - depend on any additional system libraries outside of GHC, then - it's sufficient even to run the <literal>cabal configure</literal> - command inside of the shell: - </para> - <programlisting> -$ nix-shell -p haskell.compiler.ghc784 --command "cabal configure" -</programlisting> - <para> - Afterwards, all other commands like <literal>cabal build</literal> - work just fine in any shell environment, because the configure - phase recorded the absolute paths to all required tools like GHC - in its build configuration inside of the <literal>dist/</literal> - directory. Please note, however, that - <literal>nix-collect-garbage</literal> can break such an - environment because the Nix store paths created by - <literal>nix-shell</literal> aren't "alive" anymore once - <literal>nix-shell</literal> has terminated. If you find that your - Haskell builds no longer work after garbage collection, then - you'll have to re-run <literal>cabal configure</literal> inside of - a new <literal>nix-shell</literal> environment. - </para> - </section> - <section xml:id="how-to-install-a-compiler-with-libraries"> - <title>How to install a compiler with libraries</title> - <para> - GHC expects to find all installed libraries inside of its own - <literal>lib</literal> directory. This approach works fine on - traditional Unix systems, but it doesn't work for Nix, because - GHC's store path is immutable once it's built. We cannot install - additional libraries into that location. As a consequence, our - copies of GHC don't know any packages except their own core - libraries, like <literal>base</literal>, - <literal>containers</literal>, <literal>Cabal</literal>, etc. - </para> - <para> - We can register additional libraries to GHC, however, using a - special build function called <literal>ghcWithPackages</literal>. - That function expects one argument: a function that maps from an - attribute set of Haskell packages to a list of packages, which - determines the libraries known to that particular version of GHC. - For example, the Nix expression - <literal>ghcWithPackages (pkgs: [pkgs.mtl])</literal> generates a - copy of GHC that has the <literal>mtl</literal> library registered - in addition to its normal core packages: - </para> - <programlisting> -$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.mtl])" - -[nix-shell:~]$ ghc-pkg list mtl -/nix/store/zy79...-ghc-7.10.2/lib/ghc-7.10.2/package.conf.d: - mtl-2.2.1 -</programlisting> - <para> - This function allows users to define their own development - environment by means of an override. After adding the following - snippet to <literal>~/.nixpkgs/config.nix</literal>, - </para> - <programlisting> -{ - packageOverrides = super: let self = super.pkgs; in - { - myHaskellEnv = self.haskell.packages.ghc7102.ghcWithPackages - (haskellPackages: with haskellPackages; [ - # libraries - arrows async cgi criterion - # tools - cabal-install haskintex - ]); - }; -} -</programlisting> - <para> - it's possible to install that compiler with - <literal>nix-env -f "<nixpkgs>" -iA myHaskellEnv</literal>. - If you'd like to switch that development environment to a - different version of GHC, just replace the - <literal>ghc7102</literal> bit in the previous definition with the - appropriate name. Of course, it's also possible to define any - number of these development environments! (You can't install two - of them into the same profile at the same time, though, because - that would result in file conflicts.) - </para> - <para> - The generated <literal>ghc</literal> program is a wrapper script - that re-directs the real GHC executable to use a new - <literal>lib</literal> directory --- one that we specifically - constructed to contain all those packages the user requested: - </para> - <programlisting> -$ cat $(type -p ghc) -#! /nix/store/xlxj...-bash-4.3-p33/bin/bash -e -export NIX_GHC=/nix/store/19sm...-ghc-7.10.2/bin/ghc -export NIX_GHCPKG=/nix/store/19sm...-ghc-7.10.2/bin/ghc-pkg -export NIX_GHC_DOCDIR=/nix/store/19sm...-ghc-7.10.2/share/doc/ghc/html -export NIX_GHC_LIBDIR=/nix/store/19sm...-ghc-7.10.2/lib/ghc-7.10.2 -exec /nix/store/j50p...-ghc-7.10.2/bin/ghc "-B$NIX_GHC_LIBDIR" "$@" -</programlisting> - <para> - The variables <literal>$NIX_GHC</literal>, - <literal>$NIX_GHCPKG</literal>, etc. point to the - <emphasis>new</emphasis> store path - <literal>ghcWithPackages</literal> constructed specifically for - this environment. The last line of the wrapper script then - executes the real <literal>ghc</literal>, but passes the path to - the new <literal>lib</literal> directory using GHC's - <literal>-B</literal> flag. - </para> - <para> - The purpose of those environment variables is to work around an - impurity in the popular - <link xlink:href="http://hackage.haskell.org/package/ghc-paths">ghc-paths</link> - library. That library promises to give its users access to GHC's - installation paths. Only, the library can't possible know that - path when it's compiled, because the path GHC considers its own is - determined only much later, when the user configures it through - <literal>ghcWithPackages</literal>. So we - <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/ghc-paths-nix.patch">patched - ghc-paths</link> to return the paths found in those environment - variables at run-time rather than trying to guess them at - compile-time. - </para> - <para> - To make sure that mechanism works properly all the time, we - recommend that you set those variables to meaningful values in - your shell environment, too, i.e. by adding the following code to - your <literal>~/.bashrc</literal>: - </para> - <programlisting> -if type >/dev/null 2>&1 -p ghc; then - eval "$(egrep ^export "$(type -p ghc)")" -fi -</programlisting> - <para> - If you are certain that you'll use only one GHC environment which - is located in your user profile, then you can use the following - code, too, which has the advantage that it doesn't contain any - paths from the Nix store, i.e. those settings always remain valid - even if a <literal>nix-env -u</literal> operation updates the GHC - environment in your profile: - </para> - <programlisting> -if [ -e ~/.nix-profile/bin/ghc ]; then - export NIX_GHC="$HOME/.nix-profile/bin/ghc" - export NIX_GHCPKG="$HOME/.nix-profile/bin/ghc-pkg" - export NIX_GHC_DOCDIR="$HOME/.nix-profile/share/doc/ghc/html" - export NIX_GHC_LIBDIR="$HOME/.nix-profile/lib/ghc-$($NIX_GHC --numeric-version)" -fi -</programlisting> - </section> - <section xml:id="how-to-install-a-compiler-with-indexes"> - <title>How to install a compiler with libraries, hoogle and documentation indexes</title> - <para> - If you plan to use your environment for interactive programming, - not just compiling random Haskell code, you might want to - replace <literal>ghcWithPackages</literal> in all the listings - above with <literal>ghcWithHoogle</literal>. - </para> - <para> - This environment generator not only produces an environment with - GHC and all the specified libraries, but also generates a - <literal>hoogle</literal> and <literal>haddock</literal> indexes - for all the packages, and provides a wrapper script around - <literal>hoogle</literal> binary that uses all those things. A - precise name for this thing would be - "<literal>ghcWithPackagesAndHoogleAndDocumentationIndexes</literal>", - which is, regrettably, too long and scary. - </para> - <para> - For example, installing the following environment - </para> - <programlisting> -{ - packageOverrides = super: let self = super.pkgs; in - { - myHaskellEnv = self.haskellPackages.ghcWithHoogle - (haskellPackages: with haskellPackages; [ - # libraries - arrows async cgi criterion - # tools - cabal-install haskintex - ]); - }; -} -</programlisting> - <para> - allows one to browse module documentation index <link - xlink:href="https://downloads.haskell.org/~ghc/latest/docs/html/libraries/index.html">not - too dissimilar to this</link> for all the specified packages and - their dependencies by directing a browser of choice to - <literal>~/.nix-profiles/share/doc/hoogle/index.html</literal> - (or - <literal>/run/current-system/sw/share/doc/hoogle/index.html</literal> - in case you put it in - <literal>environment.systemPackages</literal> in NixOS). - </para> - <para> - After you've marveled enough at that try adding the following to - your <literal>~/.ghc/ghci.conf</literal> - </para> - <programlisting> -:def hoogle \s -> return $ ":! hoogle search -cl --count=15 \"" ++ s ++ "\"" -:def doc \s -> return $ ":! hoogle search -cl --info \"" ++ s ++ "\"" -</programlisting> - <para> - and test it by typing into <literal>ghci</literal>: - </para> - <programlisting> -:hoogle a -> a -:doc a -> a -</programlisting> - <para> - Be sure to note the links to <literal>haddock</literal> files in - the output. With any modern and properly configured terminal - emulator you can just click those links to navigate there. - </para> - <para> - Finally, you can run - </para> - <programlisting> -hoogle server -p 8080 -</programlisting> - <para> - and navigate to <link xlink:href="http://localhost:8080/"/> for - your own local <link - xlink:href="https://www.haskell.org/hoogle/">Hoogle</link>. - Note, however, that Firefox and possibly other browsers disallow - navigation from <literal>http:</literal> to - <literal>file:</literal> URIs for security reasons, which might - be quite an inconvenience. See <link - xlink:href="http://kb.mozillazine.org/Links_to_local_pages_do_not_work">this - page</link> for workarounds. - </para> - </section> - <section xml:id="how-to-create-ad-hoc-environments-for-nix-shell"> - <title>How to create ad hoc environments for - <literal>nix-shell</literal></title> - <para> - The easiest way to create an ad hoc development environment is to - run <literal>nix-shell</literal> with the appropriate GHC - environment given on the command-line: - </para> - <programlisting> -nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [mtl pandoc])" -</programlisting> - <para> - For more sophisticated use-cases, however, it's more convenient to - save the desired configuration in a file called - <literal>shell.nix</literal> that looks like this: - </para> - <programlisting> -{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }: -let - inherit (nixpkgs) pkgs; - ghc = pkgs.haskell.packages.${compiler}.ghcWithPackages (ps: with ps; [ - monad-par mtl - ]); -in -pkgs.stdenv.mkDerivation { - name = "my-haskell-env-0"; - buildInputs = [ ghc ]; - shellHook = "eval $(egrep ^export ${ghc}/bin/ghc)"; -} -</programlisting> - <para> - Now run <literal>nix-shell</literal> --- or even - <literal>nix-shell --pure</literal> --- to enter a shell - environment that has the appropriate compiler in - <literal>$PATH</literal>. If you use <literal>--pure</literal>, - then add all other packages that your development environment - needs into the <literal>buildInputs</literal> attribute. If you'd - like to switch to a different compiler version, then pass an - appropriate <literal>compiler</literal> argument to the - expression, i.e. - <literal>nix-shell --argstr compiler ghc784</literal>. - </para> - <para> - If you need such an environment because you'd like to compile a - Hackage package outside of Nix --- i.e. because you're hacking on - the latest version from Git ---, then the package set provides - suitable nix-shell environments for you already! Every Haskell - package has an <literal>env</literal> attribute that provides a - shell environment suitable for compiling that particular package. - If you'd like to hack the <literal>lens</literal> library, for - example, then you just have to check out the source code and enter - the appropriate environment: - </para> - <programlisting> - $ cabal get lens-4.11 && cd lens-4.11 - Downloading lens-4.11... - Unpacking to lens-4.11/ - - $ nix-shell "<nixpkgs>" -A haskellPackages.lens.env - [nix-shell:/tmp/lens-4.11]$ -</programlisting> - <para> - At point, you can run <literal>cabal configure</literal>, - <literal>cabal build</literal>, and all the other development - commands. Note that you need <literal>cabal-install</literal> - installed in your <literal>$PATH</literal> already to use it here - --- the <literal>nix-shell</literal> environment does not provide - it. - </para> - </section> -</section> -<section xml:id="how-to-create-nix-builds-for-your-own-private-haskell-packages"> - <title>How to create Nix builds for your own private Haskell - packages</title> - <para> - If your own Haskell packages have build instructions for Cabal, then - you can convert those automatically into build instructions for Nix - using the <literal>cabal2nix</literal> utility, which you can - install into your profile by running - <literal>nix-env -i cabal2nix</literal>. - </para> - <section xml:id="how-to-build-a-stand-alone-project"> - <title>How to build a stand-alone project</title> - <para> - For example, let's assume that you're working on a private project - called <literal>foo</literal>. To generate a Nix build expression - for it, change into the project's top-level directory and run the - command: - </para> - <programlisting> -$ cabal2nix . >foo.nix -</programlisting> - <para> - Then write the following snippet into a file called - <literal>default.nix</literal>: - </para> - <programlisting> -{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }: -nixpkgs.pkgs.haskell.packages.${compiler}.callPackage ./foo.nix { } -</programlisting> - <para> - Finally, store the following code in a file called - <literal>shell.nix</literal>: - </para> - <programlisting> -{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }: -(import ./default.nix { inherit nixpkgs compiler; }).env -</programlisting> - <para> - At this point, you can run <literal>nix-build</literal> to have - Nix compile your project and install it into a Nix store path. The - local directory will contain a symlink called - <literal>result</literal> after <literal>nix-build</literal> - returns that points into that location. Of course, passing the - flag <literal>--argstr compiler ghc763</literal> allows switching - the build to any version of GHC currently supported. - </para> - <para> - Furthermore, you can call <literal>nix-shell</literal> to enter an - interactive development environment in which you can use - <literal>cabal configure</literal> and - <literal>cabal build</literal> to develop your code. That - environment will automatically contain a proper GHC derivation - with all the required libraries registered as well as all the - system-level libraries your package might need. - </para> - <para> - If your package does not depend on any system-level libraries, - then it's sufficient to run - </para> - <programlisting> -$ nix-shell --command "cabal configure" -</programlisting> - <para> - once to set up your build. <literal>cabal-install</literal> - determines the absolute paths to all resources required for the - build and writes them into a config file in the - <literal>dist/</literal> directory. Once that's done, you can run - <literal>cabal build</literal> and any other command for that - project even outside of the <literal>nix-shell</literal> - environment. This feature is particularly nice for those of us who - like to edit their code with an IDE, like Emacs' - <literal>haskell-mode</literal>, because it's not necessary to - start Emacs inside of nix-shell just to make it find out the - necessary settings for building the project; - <literal>cabal-install</literal> has already done that for us. - </para> - <para> - If you want to do some quick-and-dirty hacking and don't want to - bother setting up a <literal>default.nix</literal> and - <literal>shell.nix</literal> file manually, then you can use the - <literal>--shell</literal> flag offered by - <literal>cabal2nix</literal> to have it generate a stand-alone - <literal>nix-shell</literal> environment for you. With that - feature, running - </para> - <programlisting> -$ cabal2nix --shell . >shell.nix -$ nix-shell --command "cabal configure" -</programlisting> - <para> - is usually enough to set up a build environment for any given - Haskell package. You can even use that generated file to run - <literal>nix-build</literal>, too: - </para> - <programlisting> -$ nix-build shell.nix -</programlisting> - </section> - <section xml:id="how-to-build-projects-that-depend-on-each-other"> - <title>How to build projects that depend on each other</title> - <para> - If you have multiple private Haskell packages that depend on each - other, then you'll have to register those packages in the Nixpkgs - set to make them visible for the dependency resolution performed - by <literal>callPackage</literal>. First of all, change into each - of your projects top-level directories and generate a - <literal>default.nix</literal> file with - <literal>cabal2nix</literal>: - </para> - <programlisting> -$ cd ~/src/foo && cabal2nix . >default.nix -$ cd ~/src/bar && cabal2nix . >default.nix -</programlisting> - <para> - Then edit your <literal>~/.nixpkgs/config.nix</literal> file to - register those builds in the default Haskell package set: - </para> - <programlisting> - { - packageOverrides = super: let self = super.pkgs; in - { - haskellPackages = super.haskellPackages.override { - overrides = self: super: { - foo = self.callPackage ../src/foo {}; - bar = self.callPackage ../src/bar {}; - }; - }; - }; - } -</programlisting> - <para> - Once that's accomplished, - <literal>nix-env -f "<nixpkgs>" -qA haskellPackages</literal> - will show your packages like any other package from Hackage, and - you can build them - </para> - <programlisting> -$ nix-build "<nixpkgs>" -A haskellPackages.foo -</programlisting> - <para> - or enter an interactive shell environment suitable for building - them: - </para> - <programlisting> -$ nix-shell "<nixpkgs>" -A haskellPackages.bar.env -</programlisting> - </section> -</section> -<section xml:id="miscellaneous-topics"> - <title>Miscellaneous Topics</title> - <section xml:id="how-to-build-with-profiling-enabled"> - <title>How to build with profiling enabled</title> - <para> - Every Haskell package set takes a function called - <literal>overrides</literal> that you can use to manipulate the - package as much as you please. One useful application of this - feature is to replace the default <literal>mkDerivation</literal> - function with one that enables library profiling for all packages. - To accomplish that, add configure the following snippet in your - <literal>~/.nixpkgs/config.nix</literal> file: - </para> - <programlisting> -{ - packageOverrides = super: let self = super.pkgs; in - { - profiledHaskellPackages = self.haskellPackages.override { - overrides = self: super: { - mkDerivation = args: super.mkDerivation (args // { - enableLibraryProfiling = true; - }); - }; - }; - }; -} -</programlisting> - <para> - Then, replace instances of <literal>haskellPackages</literal> in the - <literal>cabal2nix</literal>-generated <literal>default.nix</literal> - or <literal>shell.nix</literal> files with - <literal>profiledHaskellPackages</literal>. - </para> - </section> - <section xml:id="how-to-override-package-versions-in-a-compiler-specific-package-set"> - <title>How to override package versions in a compiler-specific - package set</title> - <para> - Nixpkgs provides the latest version of - <link xlink:href="http://hackage.haskell.org/package/ghc-events"><literal>ghc-events</literal></link>, - which is 0.4.4.0 at the time of this writing. This is fine for - users of GHC 7.10.x, but GHC 7.8.4 cannot compile that binary. - Now, one way to solve that problem is to register an older version - of <literal>ghc-events</literal> in the 7.8.x-specific package - set. The first step is to generate Nix build instructions with - <literal>cabal2nix</literal>: - </para> - <programlisting> -$ cabal2nix cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix -</programlisting> - <para> - Then add the override in <literal>~/.nixpkgs/config.nix</literal>: - </para> - <programlisting> -{ - packageOverrides = super: let self = super.pkgs; in - { - haskell = super.haskell // { - packages = super.haskell.packages // { - ghc784 = super.haskell.packages.ghc784.override { - overrides = self: super: { - ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {}; - }; - }; - }; - }; - }; -} -</programlisting> - <para> - This code is a little crazy, no doubt, but it's necessary because - the intuitive version - </para> - <programlisting> -haskell.packages.ghc784 = super.haskell.packages.ghc784.override { - overrides = self: super: { - ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {}; - }; -}; -</programlisting> - <para> - doesn't do what we want it to: that code replaces the - <literal>haskell</literal> package set in Nixpkgs with one that - contains only one entry,<literal>packages</literal>, which - contains only one entry <literal>ghc784</literal>. This override - loses the <literal>haskell.compiler</literal> set, and it loses - the <literal>haskell.packages.ghcXYZ</literal> sets for all - compilers but GHC 7.8.4. To avoid that problem, we have to perform - the convoluted little dance from above, iterating over each step - in hierarchy. - </para> - <para> - Once it's accomplished, however, we can install a variant of - <literal>ghc-events</literal> that's compiled with GHC 7.8.4: - </para> - <programlisting> -nix-env -f "<nixpkgs>" -iA haskell.packages.ghc784.ghc-events -</programlisting> - <para> - Unfortunately, it turns out that this build fails again while - executing the test suite! Apparently, the release archive on - Hackage is missing some data files that the test suite requires, - so we cannot run it. We accomplish that by re-generating the Nix - expression with the <literal>--no-check</literal> flag: - </para> - <programlisting> -$ cabal2nix --no-check cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix -</programlisting> - <para> - Now the builds succeeds. - </para> - <para> - Of course, in the concrete example of - <literal>ghc-events</literal> this whole exercise is not an ideal - solution, because <literal>ghc-events</literal> can analyze the - output emitted by any version of GHC later than 6.12 regardless of - the compiler version that was used to build the `ghc-events' - executable, so strictly speaking there's no reason to prefer one - built with GHC 7.8.x in the first place. However, for users who - cannot use GHC 7.10.x at all for some reason, the approach of - downgrading to an older version might be useful. - </para> - </section> - <section xml:id="how-to-recover-from-ghcs-infamous-non-deterministic-library-id-bug"> - <title>How to recover from GHC's infamous non-deterministic library - ID bug</title> - <para> - GHC and distributed build farms don't get along well: - </para> - <programlisting> -https://ghc.haskell.org/trac/ghc/ticket/4012 -</programlisting> - <para> - When you see an error like this one - </para> - <programlisting> -package foo-0.7.1.0 is broken due to missing package -text-1.2.0.4-98506efb1b9ada233bb5c2b2db516d91 -</programlisting> - <para> - then you have to download and re-install <literal>foo</literal> - and all its dependents from scratch: - </para> - <programlisting> -# nix-store -q --referrers /nix/store/*-haskell-text-1.2.0.4 \ - | xargs -L 1 nix-store --repair-path --option binary-caches http://hydra.nixos.org -</programlisting> - <para> - If you're using additional Hydra servers other than - <literal>hydra.nixos.org</literal>, then it might be necessary to - purge the local caches that store data from those machines to - disable these binary channels for the duration of the previous - command, i.e. by running: - </para> - <programlisting> -rm /nix/var/nix/binary-cache-v3.sqlite -rm /nix/var/nix/manifests/* -rm /nix/var/nix/channel-cache/* -</programlisting> - </section> - <section xml:id="builds-on-darwin-fail-with-math.h-not-found"> - <title>Builds on Darwin fail with <literal>math.h</literal> not - found</title> - <para> - Users of GHC on Darwin have occasionally reported that builds - fail, because the compiler complains about a missing include file: - </para> - <programlisting> -fatal error: 'math.h' file not found -</programlisting> - <para> - The issue has been discussed at length in - <link xlink:href="https://github.com/NixOS/nixpkgs/issues/6390">ticket - 6390</link>, and so far no good solution has been proposed. As a - work-around, users who run into this problem can configure the - environment variables - </para> - <programlisting> -export NIX_CFLAGS_COMPILE="-idirafter /usr/include" -export NIX_CFLAGS_LINK="-L/usr/lib" -</programlisting> - <para> - in their <literal>~/.bashrc</literal> file to avoid the compiler - error. - </para> - </section> -</section> - -<section xml:id="other-resources"> - <title>Other resources</title> - <itemizedlist> - <listitem> - <para> - The Youtube video - <link xlink:href="https://www.youtube.com/watch?v=BsBhi_r-OeE">Nix - Loves Haskell</link> provides an introduction into Haskell NG - aimed at beginners. The slides are available at - http://cryp.to/nixos-meetup-3-slides.pdf and also -- in a form - ready for cut & paste -- at - https://github.com/NixOS/cabal2nix/blob/master/doc/nixos-meetup-3-slides.md. - </para> - </listitem> - <listitem> - <para> - Another Youtube video is - <link xlink:href="https://www.youtube.com/watch?v=mQd3s57n_2Y">Escaping - Cabal Hell with Nix</link>, which discusses the subject of - Haskell development with Nix but also provides a basic - introduction to Nix as well, i.e. it's suitable for viewers with - almost no prior Nix experience. - </para> - </listitem> - <listitem> - <para> - Oliver Charles wrote a very nice - <link xlink:href="http://wiki.ocharles.org.uk/Nix">Tutorial how to - develop Haskell packages with Nix</link>. - </para> - </listitem> - <listitem> - <para> - The <emphasis>Journey into the Haskell NG - infrastructure</emphasis> series of postings describe the new - Haskell infrastructure in great detail: - </para> - <itemizedlist> - <listitem> - <para> - <link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015591.html">Part - 1</link> explains the differences between the old and the - new code and gives instructions how to migrate to the new - setup. - </para> - </listitem> - <listitem> - <para> - <link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015608.html">Part - 2</link> looks in-depth at how to tweak and configure your - setup by means of overrides. - </para> - </listitem> - <listitem> - <para> - <link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-April/016912.html">Part - 3</link> describes the infrastructure that keeps the - Haskell package set in Nixpkgs up-to-date. - </para> - </listitem> - </itemizedlist> - </listitem> - </itemizedlist> -</section> - -</chapter> |