Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use the new haskell-ng infrastructure on NixOS?

How do I setup a simple Haskell development environment on NixOS using the new haskell-ng infrastructure?

like image 585
rzetterberg Avatar asked Mar 13 '15 13:03

rzetterberg


1 Answers

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.

The 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;
  }

More information

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

Update: Building dependencies with profiling enabled

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.

like image 119
rzetterberg Avatar answered Nov 10 '22 10:11

rzetterberg