From be63be9d042839f1c85de7d75ca957c9cff6be57 Mon Sep 17 00:00:00 2001 From: Mathieu Boespflug Date: Sun, 13 Dec 2015 18:20:12 +0100 Subject: [PATCH 1/5] haskell: add buildStackProject. For building environments for Stack projects. --- pkgs/build-support/haskell/stack.nix | 40 ++++++++++++++++++++++++++++ pkgs/top-level/haskell-packages.nix | 2 ++ 2 files changed, 42 insertions(+) create mode 100644 pkgs/build-support/haskell/stack.nix diff --git a/pkgs/build-support/haskell/stack.nix b/pkgs/build-support/haskell/stack.nix new file mode 100644 index 00000000000..80b70203955 --- /dev/null +++ b/pkgs/build-support/haskell/stack.nix @@ -0,0 +1,40 @@ +{ stdenv, ghc, pkgconfig, glibcLocales }: + +with stdenv.lib; + +{ buildInputs ? [] +, extraArgs ? [] +, LD_LIBRARY_PATH ? "" +, ... +}@args: + +stdenv.mkDerivation (args // { + + buildInputs = + buildInputs ++ + optional stdenv.isLinux glibcLocales ++ + [ ghc pkgconfig ]; + + STACK_IN_NIX_SHELL=1; + STACK_IN_NIX_EXTRA_ARGS = + concatMap (pkg: ["--extra-lib-dirs=${pkg}/lib" + "--extra-include-dirs=${pkg}/include"]) buildInputs ++ + extraArgs; + + # XXX: workaround for https://ghc.haskell.org/trac/ghc/ticket/11042. + LD_LIBRARY_PATH = "${makeLibraryPath buildInputs}:${LD_LIBRARY_PATH}"; + + preferLocalBuild = true; + + configurePhase = args.configurePhase or "stack setup"; + + buildPhase = args.buildPhase or "stack build"; + + checkPhase = args.checkPhase or "stack test"; + + doCheck = args.doCheck or true; + + installPhase = args.installPhase or '' + stack --local-bin-path=$out/bin build --copy-bins + ''; +}) diff --git a/pkgs/top-level/haskell-packages.nix b/pkgs/top-level/haskell-packages.nix index 928541cd9df..9b7bdd01505 100644 --- a/pkgs/top-level/haskell-packages.nix +++ b/pkgs/top-level/haskell-packages.nix @@ -4,6 +4,8 @@ rec { lib = import ../development/haskell-modules/lib.nix { inherit pkgs; }; + buildStackProject = callPackage ../build-support/haskell/stack.nix { }; + compiler = { ghc6102Binary = callPackage ../development/compilers/ghc/6.10.2-binary.nix { gmp = pkgs.gmp4; }; From ff9cba94f68428ebe31a057892ae32de85d76bfb Mon Sep 17 00:00:00 2001 From: Mathieu Boespflug Date: Sun, 17 Jan 2016 20:59:20 +0100 Subject: [PATCH 2/5] haskell: Rename file where buildStackProject is defined. --- .../haskell-modules/generic-stack-builder.nix} | 0 pkgs/top-level/haskell-packages.nix | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename pkgs/{build-support/haskell/stack.nix => development/haskell-modules/generic-stack-builder.nix} (100%) diff --git a/pkgs/build-support/haskell/stack.nix b/pkgs/development/haskell-modules/generic-stack-builder.nix similarity index 100% rename from pkgs/build-support/haskell/stack.nix rename to pkgs/development/haskell-modules/generic-stack-builder.nix diff --git a/pkgs/top-level/haskell-packages.nix b/pkgs/top-level/haskell-packages.nix index 9b7bdd01505..540343aa02d 100644 --- a/pkgs/top-level/haskell-packages.nix +++ b/pkgs/top-level/haskell-packages.nix @@ -4,7 +4,7 @@ rec { lib = import ../development/haskell-modules/lib.nix { inherit pkgs; }; - buildStackProject = callPackage ../build-support/haskell/stack.nix { }; + buildStackProject = callPackage ../development/haskell-modules/generic-stack-builder.nix { }; compiler = { From 01f384b8b44b869c41125297f04820d9665d356d Mon Sep 17 00:00:00 2001 From: Mathieu Boespflug Date: Sun, 17 Jan 2016 21:09:16 +0100 Subject: [PATCH 3/5] haskell: Add documentation for haskell.buildStackProject to user guide. This section documents introduces Stack's primitive Nix support as well. --- doc/haskell-users-guide.md | 73 ++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/doc/haskell-users-guide.md b/doc/haskell-users-guide.md index b9b2fe9e3bc..1fc80d5b690 100644 --- a/doc/haskell-users-guide.md +++ b/doc/haskell-users-guide.md @@ -117,9 +117,10 @@ Also, the attributes `haskell.compiler.ghcXYC` and ### 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: +A simple development environment consists of a Haskell compiler and one or both +of the tools `cabal-install` and `stack`. We saw in section +[How to install Haskell packages] how you can install those programs into your +user profile: $ nix-env -f "" -iA haskellPackages.ghc haskellPackages.cabal-install @@ -148,10 +149,16 @@ 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: +to bring GHC 7.8.4 into `$PATH`. Alternatively, you can use Stack instead of +`nix-shell` directly to select compiler versions and other build tools +per-project. It uses `nix-shell` under the hood when Nix support is turned on. +See [How to build a Haskell project using Stack]. + +If you're using `cabal-install`, re-running `cabal configure` inside the spawned +shell 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 even sufficient to just run the `cabal configure` command inside of +the shell: $ nix-shell -p haskell.compiler.ghc784 --command "cabal configure" @@ -320,6 +327,58 @@ 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 build a Haskell project using Stack + +[Stack][http://haskellstack.org] is a popular build tool for Haskell projects. +It has first-class support for Nix. Stack can optionally use Nix to +automatically select the right version of GHC and other build tools to build, +test and execute apps in an existing project downloaded from somewhere on the +Internet. Pass the `--nix` flag to any `stack` command to do so, e.g. + + $ git clone --recursive http://github.com/yesodweb/wai + $ cd wai + $ stack --nix build + +If you want `stack` to use Nix by default, you can add a `nix` section to the +`stack.yaml` file, as explained in the [Stack documentation][stack-nix-doc]. For +example: + + nix: + enable: true + packages: [pkgconfig zeromq zlib] + +The example configuration snippet above tells Stack to create an ad hoc +environment for `nix-shell` as in the below section, in which the `pkgconfig`, +`zeromq` and `zlib` packages from Nixpkgs are available. All `stack` commands +will implicitly be executed inside this ad hoc environment. + +Some projects have more sophisticated needs. For examples, some ad hoc +environments might need to expose Nixpkgs packages compiled in a certain way, or +with extra environment variables. In these cases, you'll need a `shell` field +instead of `packages`: + + nix: + enable: true + shell-file: shell.nix + +For more on how to write a `shell.nix` file see the below section. You'll need +to express a derivation. Note that Nixpkgs ships with a convenience wrapper +function around `mkDerivation` called `haskell.buildStackProject` to help you +create this derivation in exactly the way Stack expects. All of the same inputs +as `mkDerivation` can be provided. For example, to build a Stack project that +including packages that link against a version of the R library compiled with +special options turned on: + + with (import { }); + + let R = pkgs.R.override { enableStrictBarrier = true; }; + in + haskell.buildStackProject { + name = "HaskellR"; + buildInputs = [ R zeromq zlib ]; + } + +[stack-nix-doc]: http://docs.haskellstack.org/en/stable/nix_integration.html ### How to create ad hoc environments for `nix-shell` From 6f09628c321e19f999eb6f2f59fde829723a5c2d Mon Sep 17 00:00:00 2001 From: Mathieu Boespflug Date: Sun, 17 Jan 2016 21:19:14 +0100 Subject: [PATCH 4/5] haskell: tell users to use Stack's nix support when missing system library. --- doc/haskell-users-guide.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/doc/haskell-users-guide.md b/doc/haskell-users-guide.md index 1fc80d5b690..da923db602d 100644 --- a/doc/haskell-users-guide.md +++ b/doc/haskell-users-guide.md @@ -664,7 +664,7 @@ can configure the environment variables in their `~/.bashrc` file to avoid the compiler error. -### Using Stack together with Nix +### Builds using Stack complain about missing system libraries -- While building package zlib-0.5.4.2 using: runhaskell -package=Cabal-1.22.4.0 -clear-package-db [... lots of flags ...] @@ -692,13 +692,16 @@ 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 this issue in several ways. The easiest is to add a `nix` section +to the `stack.yaml` like the following: -You can remedy that issue in several ways. First of all, run + nix: + enable: true + packages: [ zlib ] + +Stack's Nix support knows to add `${zlib}/lib` and `${zlib}/include` as an +`--extra-lib-dirs` and `extra-include-dirs`, respectively. Alternatively, you +can achieve the same effect by hand. First of all, run $ nix-build --no-out-link "" -A zlib /nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8 @@ -722,7 +725,8 @@ to find out the store path of the system's zlib library. Now, you can 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. + specify them manually every time. But again, you're likely better off using + Stack's Nix support instead. The same thing applies to `cabal configure`, of course, if you're building with `cabal-install` instead of Stack. From 7fedb7c9922ec3c715851c54f689c949fae14da9 Mon Sep 17 00:00:00 2001 From: Mathieu Boespflug Date: Fri, 4 Mar 2016 21:24:42 +0100 Subject: [PATCH 5/5] Move `buildStackProject` to `haskell.lib`. --- doc/haskell-users-guide.md | 4 ++-- pkgs/development/haskell-modules/lib.nix | 2 ++ pkgs/top-level/haskell-packages.nix | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/haskell-users-guide.md b/doc/haskell-users-guide.md index da923db602d..ce61295e567 100644 --- a/doc/haskell-users-guide.md +++ b/doc/haskell-users-guide.md @@ -363,7 +363,7 @@ instead of `packages`: For more on how to write a `shell.nix` file see the below section. You'll need to express a derivation. Note that Nixpkgs ships with a convenience wrapper -function around `mkDerivation` called `haskell.buildStackProject` to help you +function around `mkDerivation` called `haskell.lib.buildStackProject` to help you create this derivation in exactly the way Stack expects. All of the same inputs as `mkDerivation` can be provided. For example, to build a Stack project that including packages that link against a version of the R library compiled with @@ -373,7 +373,7 @@ special options turned on: let R = pkgs.R.override { enableStrictBarrier = true; }; in - haskell.buildStackProject { + haskell.lib.buildStackProject { name = "HaskellR"; buildInputs = [ R zeromq zlib ]; } diff --git a/pkgs/development/haskell-modules/lib.nix b/pkgs/development/haskell-modules/lib.nix index a3e1b56104d..51adb582e54 100644 --- a/pkgs/development/haskell-modules/lib.nix +++ b/pkgs/development/haskell-modules/lib.nix @@ -81,6 +81,8 @@ rec { buildStrictly = pkg: buildFromSdist (appendConfigureFlag pkg "--ghc-option=-Wall --ghc-option=-Werror"); + buildStackProject = callPackage ../development/haskell-modules/generic-stack-builder.nix { }; + triggerRebuild = drv: i: overrideCabal drv (drv: { postUnpack = ": trigger rebuild ${toString i}"; }); #FIXME: throw this away sometime in the future. added 2015-08-18 diff --git a/pkgs/top-level/haskell-packages.nix b/pkgs/top-level/haskell-packages.nix index 540343aa02d..928541cd9df 100644 --- a/pkgs/top-level/haskell-packages.nix +++ b/pkgs/top-level/haskell-packages.nix @@ -4,8 +4,6 @@ rec { lib = import ../development/haskell-modules/lib.nix { inherit pkgs; }; - buildStackProject = callPackage ../development/haskell-modules/generic-stack-builder.nix { }; - compiler = { ghc6102Binary = callPackage ../development/compilers/ghc/6.10.2-binary.nix { gmp = pkgs.gmp4; };