Some Nix how-to's

Generate Nix derivation using cabal2nix manually

nix-shell --packages cabal2nix --run "cabal2nix ." > default.nix

This will create a default.nix file that will look somewhat like this:

{ mkDerivation, base, stdenv }:
mkDerivation {
  pname = "yourCabalProjectName";
  version = "0.1.0";
  src = ./.;
  isLibrary = false;
  isExecutable = true;
  executableHaskellDepends = [ base ];
  license = "unknown";
  hydraPlatforms = stdenv.lib.platforms.none;
}

Now create release.nix file with the following contents:

let
  pkgs = import <nixpkgs> {};
in
  pkgs.haskellPackages.callPackage ./default.nix { }

Now you can do nix-build release.nix to compile your project using Cabal.

Note: This method will require to re-generate default.nix every time you change your Cabal project file. If you don't want to do this, use the method described in the next section.

Links

Automatically generate Nix derivation from Cabal project

Create default.nix file with the following content:

{ pkgs ? import <nixpkgs> {} }:
let
  haskellPackages = pkgs.haskellPackages.override (old: {
    overrides = pkgs.lib.composeExtensions (old.overrides or (_: _: { }))
      (self: super: {
        project = haskellPackages.callCabal2nix "chat" ./. {};
        # Additional overrides go here.
      });
  });
in {
  project = haskellPackages.project;
  haskellPackages = haskellPackages;
  pkgs = pkgs;
}

Pin nixpkgs version

Note: See the relations between nixpkgs versions and GHC versions here: https://tldr.brick.do/eb0cd436-b62b-427d-be2c-8e3dc0087ed2

If you want to pin pkgs version to a released nixpkgs version, e.g. 20.09, do the following (replace nixos-20.09 with master if you just want the latest nixpkgs):

git ls-remote https://github.com/nixos/nixpkgs nixos-20.09

This will give you the following output:

e065200fc90175a8f6e50e76ef10a48786126e1c        refs/heads/nixos-20.09

Where e065200fc90175a8f6e50e76ef10a48786126e1c is your revison hash. Now modify your default.nix file so it looks like this:

{ pkgs ? import (builtins.fetchGit {
  name = "nixos-20.09-2020-12-29";
  url = "https://github.com/nixos/nixpkgs";
  ref = "refs/heads/nixos-20.09";
  rev = "e065200fc90175a8f6e50e76ef10a48786126e1c";
}) {} }:
let
  haskellPackages = pkgs.haskellPackages.override (old: {
    overrides = pkgs.lib.composeExtensions (old.overrides or (_: _: { }))
      (self: super: {
        project = haskellPackages.callCabal2nix "chat" ./. {};
        # Additional overrides go here.
      });
  });
in {
  project = haskellPackages.project;
  haskellPackages = haskellPackages;
  pkgs = pkgs;
}

That's it. By the way, you can omit ref if it's refs/heads/master.

Links

Configure Nix shell

Just put the following code snippet into a shell.nix file to enable cabal-install, haskell-language-server and ormolu when running nix-shell:

let 
  release = import ./release.nix;
  shell = with release; with release.pkgs; haskellPackages.shellFor {
    # withHoogle = true;
    packages = p: [project];
    buildInputs = with haskellPackages; [
      ormolu
      haskell-language-server
      cabal-install
    ];
  };
in
  if release.pkgs.lib.inNixShell then shell else release.project

Note: withHoogle = true is currently commented because of a bug in nixpkgs.

Links

Enable HLS in VS Code

Once you've configured Nix shell with haskell-language-server, just open VS Code inside Nix shell:

nix-shell
code .

Override Cabal dependency

TODO

Links

Add built binaries to $PATH with direnv

Supposing direnv is already installed, do the following in your project root:

direnv allow .
echo "PATH_add result/bin" > .envrc

That's it!

TODO: what use nix does?

Create a Docker image

TODO

Note: You can't build Docker images with Nix on macOS natively, to do that you'll have to create a Docker container (via a simple Dockerfile, not via Nix) and then inside it build a Docker image with Nix.

Links

Remove unused derivations

TODO

Links


Changelog

  • 2021-01-01 Added section about Nix shell configuration
  • 2020-12-29 Created post