Getting started
haskell.nix
can automatically translate your Cabal or Stack project and its dependencies into Nix code.
The first steps are to ensure you have Nix installed and the binary cache set up on your machine.
Then you have the choice to set-up your project using the experimental Flake feature or Niv, which are 2 ways to pin nixpkgs
with Nix.
If you have an existing Haskell project that you want to build with haskell.nix
, you might prefer to use hix
. hix
is a more easy and user-friendly way to use haskell.nix
, using it reduce considerably the size of the Nix expression you will have to maintain in your project codebase.
Setting up the binary cache
IMPORTANT: you must do this or you will build several copies of GHC!
You can configure Nix to use our binary cache, which is pushed to by CI, so should contain the artifacts that you need.
You need to add the following sections to /etc/nix/nix.conf
or, if you are a trusted user, ~/.config/nix/nix.conf
(if you don't know what a "trusted user" is, you probably want to do the former). [...]
denote any existing entries.
extra-trusted-public-keys = [...] hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= [...]
extra-substituters = [...] https://cache.iog.io [...]
If you're running NixOS, you need to add/update the following in your /etc/nixos/configuration.nix
files instead.
# Binary Cache for haskell.nix
nix.settings.trusted-public-keys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
];
nix.settings.substituters = [
"https://cache.iog.io"
];
NixOS-21.11 and older use slightly different settings.
# Binary Cache for haskell.nix
nix.binaryCachePublicKeys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
];
nix.binaryCaches = [
"https://cache.iog.io"
];
This can be tricky to get setup properly. If you're still having trouble getting cache hits, consult the corresponding troubleshooting section.
Create a project using Flakes
This section assumes you choose to uses the experimental flakes features, and so that you have added experimental-features = [ "nix-command" "flakes" ];
in your Nix configuration. You can look at the Wiki for more instructions.
The following nix flake init
command creates a template hello
package containing a flake.nix
and nix/hix.nix
file. The project can be used with
regular nix
tools. This template is defined in the NixOS/templates repository.
nix flake init --template templates#haskell-nix --impure
# `--impure` is required by `builtins.currentSystem`
nix develop
cabal build
To view the contents of the flake run:
nix flake show
To build a component with nix:
nix build .#hello:exe:hello
To build and run a component:
nix run .#hello:exe:hello
Scaffolding
The following code could be capy-pasted and will work with stack.yaml
and cabal.project
based projects.
Edit your flake.nix
as:```nix
{
description = "A very basic flake";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils, haskellNix }:
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
let
overlays = [ haskellNix.overlay
(final: _prev: {
# This overlay adds our project to pkgs
helloProject =
final.haskell-nix.project' {
src = ./.;
compiler-nix-name = "ghc96";
# This is used by nix develop .
to open a shell for use with
# cabal
, hlint
and haskell-language-server
shell.tools = {
cabal = {};
# hlint = {};
# haskell-language-server = {};
};
# Non-Haskell shell tools go here
shell.buildInputs = with pkgs; [
nixpkgs-fmt
];
# This adds js-unknown-ghcjs-cabal
to the shell.
# shell.crossPlatforms = p: [p.ghcjs];
};
})
];
pkgs = import nixpkgs { inherit system overlays; inherit (haskellNix) config; };
flake = pkgs.helloProject.flake {
# This adds support for nix build .#js-unknown-ghcjs:hello:exe:hello
# crossPlatforms = p: [p.ghcjs];
};
in flake // {
# Built by nix build .
packages.default = flake.packages."hello:exe:hello";
});
}
> **Note:** Git dependencies
>
> If you have git dependencies in your project, you'll need to [calculate sha256 hashes for them](./source-repository-hashes.md).
## Working with a project
Top-level attributes are Haskell packages (incl. dependencies) part of your project.
This section will show side by side the commands using Flakes experimental `new-command` API and legacy Nix commands.
To build the library component of a package in the project run:
```shell
nix build .#your-package-name:lib:your-package-name
There are also other components such as exes
, tests
, benchmarks
and all
.
To build an executable:
nix build .#your-package-name:exe:your-exe-name
Flakes provide a devShell
attribute that allow you to spawn a developer shell, here with cabal
, hlint
and haskell-language-server
:
nix develop .
cabal repl your-package-name:lib:your-package-name
cabal build your-package-name
To open a shell for use with stack
see the following issue.
Getting started with Hix
Hix is a command line tool that provides an easy way to add haskell.nix
support to existing haskell projects.
The hix init
command adds a flake.nix
and nix/hix.nix
file. After that the project can be used with regular nix
tools.
For instance to run cabal build
on the hello
package from hackage:
cabal unpack hello
cd hello-1.0.0.2
nix run "github:input-output-hk/haskell.nix#hix" -- init
nix develop
cabal build
To view the contents of the flake run:
nix flake show
To build a component with nix:
nix build .#hello:exe:hello
To build and run a component:
nix run .#hello:exe:hello
Installing Hix
To use the other Hix features first install Hix with:
nix-env -iA hix -f https://github.com/input-output-hk/haskell.nix/tarball/master
To update run to the latest version run:
hix update
Using hix develop
, hix flake
, hix build
and hix run
These commands work the same as the nix
versions without using the flake.nix
. Instead a boiler plate haskell.nix
flake.nix
file is added to .hix-flake/flake.nix
and used from there.
The is can be useful if the project already includes a flake.nix
or if you do not intend to maintain one.
Then all of these should work without the need to run hix init
:
hix develop
hix flake show
hix build .#hello:exe:hello
hix run .#hello:exe:hello
Using hix-shell
and hix-build
These commands behave like nix-build
and hix-shell
would if a boiler plate default.nix
and shell.nix
we present.
hix-shell --run 'cabal build all'
hix-build -A hsPkgs.hello.components.exes.hello
Going forward
Read through project function reference to see how the API works.
There are a number of things to explore further in the tutorials section.