How do I setup a simple Haskell development environment on NixOS using the new haskell-ng infrastructure?
Here's one way of doing it on a per project basis. I'm developing a Yesod webbapp so I'm using my current setup as an example.
In my project folder I have two files: default.nix
(specifies how to build my project) and shell.nix
(specifies how to setup build inputs).
This way I can just run nix-shell
and it drops me into an environment which has ghc installed with the provided packages and paths setup.
default.nix
{ stdenv, haskellPackages }:
let
env = haskellPackages.ghcWithPackages (p: with p; [
aeson
bytestring
cabal-install
classy-prelude
classy-prelude-conduit
classy-prelude-yesod
conduit
containers
data-default
directory
fast-logger
file-embed
hjsmin
http-conduit
monad-control
monad-logger
persistent
persistent-postgresql
persistent-template
safe
shakespeare
template-haskell
text
time
unordered-containers
vector
wai-extra
wai-logger
warp
yaml
yesod
yesod-auth
yesod-bin
yesod-core
yesod-form
yesod-static
]);
in
stdenv.mkDerivation {
name = "project-name";
buildInputs = [env];
shellHook = ''
export NIX_GHC="${env}/bin/ghc"
export NIX_GHCPKG="${env}/bin/ghc-pkg"
export NIX_GHC_DOCDIR="${env}/share/doc/ghc/html"
export NIX_GHC_LIBDIR=$( $NIX_GHC --print-libdir )
'';
}
shell.nix
{ pkgs ? (import <nixpkgs> {}) }:
(import ./default.nix) {
stdenv = pkgs.stdenv;
haskellPackages = pkgs.haskellPackages;
}
For more information you can read:
A Journey into the Haskell NG infrastructure: Part I
A Journey into the Haskell NG infrastructure: Part II
Those links explains how haskell-ng works and what will happen in the future.
If you want to dig into the source of the haskell-ng infrastructure I suggest:
The file where haskellPackages is defined
The haskell packages module
The haskell-module folder
All packages in haskell-ng are defined in hackage-packages.nix. They are built using cabal.mkDerivation
.
If you want to override how a package is built you need to override how mkDerivation
is called on that package. In the Haskell Wiki you have information on how to do that.. Basically you define a new haskellPackages
with the overrides you want for each package:
let haskellPackages' = haskellPackages.override {
overrides = self: super: {
fullstop = super.fullstop.override {
mkDerivation = (attrs: self.mkDerivation (attrs // { doCheck = false; }));
};
};
};
This can be quite tedious to do, therefor there are helper functions in the file lib.nix in haskell-modules
that you can use.
The file haskell-ng
imports lib.nix
and exposes it. And haskell-ng
is exposed as a top-level package so you can access the lib functions easily.
Say we have a package that want to enable profiling on the text library we can do something like this:
{ pkgs ? (import <nixpkgs> {}).pkgs }:
let
lib = pkgs.haskell-ng.lib;
env = pkgs.haskellPackages.ghcWithPackages (p: with p; [
(lib.enableLibraryProfiling text)
]);
in
pkgs.stdenv.mkDerivation {
name = "hello-world-wide-web";
buildInputs = [env];
shellHook = ''
export NIX_GHC="${env}/bin/ghc"
export NIX_GHCPKG="${env}/bin/ghc-pkg"
export NIX_GHC_DOCDIR="${env}/share/doc/ghc/html"
export NIX_GHC_LIBDIR=$( $NIX_GHC --print-libdir )
'';
}
I found this information this weekend by going through the nix source for haskell-ng and testing it. I'm still quite new to NixOS and nix so there could be a better way of doing this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With