on edd1d21 help sign in
haskell.nix/docs/user-guide.md
310 lines 11 kB history raw
1# User Guide
3[Haskell.nix][] can be use for two different use cases:
5### Use 1 : to build a specific package from hackage or a [stackage][] lts or nightly set.
7To build a package, say [lens][], from a stackage snapshot, say [lts-13.28][],
8you could run
9```bash
10nix build '(with import <nixpkgs> (import ./. {}).nixpkgsArgs; haskell-nix.snapshots."lts-13.28").lens.components.library'
11```
12which would build the [lens][] library component from the lens package as fixed
13by the [lts-13.28][] stackage snapshot.
15To build any package from hackage, say [lens][], in version, say 4.17.1, you
16could run
17```bash
18nix build '(with import <nixpkgs> (import ./. {}).nixpkgsArgs; (haskell-nix.hackage-package { name = "lens"; version = "4.17.1"; })).components.library'
19```
20which would build the [lens][] library component from the [lens-4.17.1][] package
21from hackage. The dependencies would be solved against the most recent
22[hackage-index-state][] that comes via the [hackage.nix][] pin with your
23[haskell.nix][] checkout. A specific one can be specified as well:
24```bash
25nix build '(with import <nixpkgs> (import ./. {}).nixpkgsArgs; (haskell-nix.hackage-package { name = "lens"; version = "4.17.1"; index-state = "2019-07-14T00:00:00Z"; })).components.library'
26```
27which would use the hackage index as of `2019-07-14T00:00:00Z` to produce a build plan
28for the [lens-4.17.1][] package.
31### Use 2 : to build a stack or cabal project.
33So you want to use [Haskell.nix][] with your stack or cabal project. The
34general approach will be to pick the right tool from `nix-tools` and
35produce a `pkgs.nix` expression. Getting a copy of the `nix-tools`
36(and potentially the [Haskell.nix][] source), will then equip us to
37produce derivations that we can `nix build`.
39[haskell.nix]: https://github.com/input-output-hk/haskell.nix
40[stackage]: https://stackage.org
41[lts-13.28]: https://www.stackage.org/lts-13.28
42[lens]: https://hackage.haskell.org/package/lens
43[lens-4.17.1]: https://hackage.haskell.org/package/lens-4.17.1
44[hackage.nix]: https://github.com/input-output-hk/hackage.nix
45[hackage-index-state]: https://github.com/input-output-hk/hackage.nix/blob/master/index-state-hashes.nix
47## Installing `nix-tools`
49To build the latest `nix-tools` and store the result at `./nt`, run:
51```bash
52nix build 'let haskellNix = import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}; in (import haskellNix.sources.nixpkgs-2003 haskellNix.nixpkgsArgs).haskell-nix.nix-tools' --out-link nt
53```
55If you would like to then install `nix-tools` into your profile, run:
57```bash
58nix-env -i ./nt
59```
61## Getting the [Haskell.nix][] source (optional)
63The [Haskell.nix][] and `nix-tools` source will be useful if you would
64like to contribute improvements, or read the source code to fully
65understand something that the documentation doesn't cover.
67```bash
68git clone https://github.com/input-output-hk/nix-tools
69git clone https://github.com/input-output-hk/haskell.nix
70cd haskell.nix
71nix build -f . haskell-nix.nix-tools --out-link nt
72```
74## Setting up the Cachix binary cache
76CI pushes to [cachix](https://cachix.org) so you can benefit from the cache if
77you pin a combination of `haskell.nix` and `nixpkgs` built by CI. You'll need
78to configure the [iohk cachix](https://iohk.cachix.org) as a
79`substituter` for `nix` and add the public key found at the url to
80`trusted-public-keys`.
82## Using [Haskell.nix][] with your project
84The easiest way to get a hold of [Haskell.nix][] is with
85[`fetchTarball`](https://nixos.org/nix/manual/#ssec-builtins).
87```nix
88import <nixpkgs> (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs
89```
91### Using your cabal.project file
93If your project has a `cabal.project` you can add a `default.nix` like this:
95```nix
96{ pkgs ? import <nixpkgs> (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs
97, compiler-nix-name ? "ghc865"
98}:
99 pkgs.haskell-nix.cabalProject {
100 src = pkgs.haskell-nix.haskellLib.cleanGit { src = ./.; };
101 inherit compiler-nix-name;
102 # pkg-def-extras = [
103 # # Additional packages ontop of all those listed in `cabal.project`
104 # ];
105 # modules = [{
106 # # Specific package overrides would go here for example:
107 # packages.cbors.package.ghcOptions = "-Werror";
108 # packages.cbors.patches = [ ./one.patch ];
109 # packages.cbors.flags.optimize-gmp = false;
110 # # It may be better to set flags in `cabal.project` instead
111 # # (`plan-to-nix` will include them as defaults).
112 # }];
113 }
114```
116Note: The `cleanGit` call will exclude any files not in the index file
117in the local `.git` directory. This is extremely useful as it avoids
118unwanted builds (for instance when the contents of `dist-newstyle` are
119modified by cabal). It is important that `src` is the root directory
120of the repo (so `cleanGit` can find the `.git` directory). If the project
121is not at the root of the repo, then also pass `subDir` to `cleanGit` with the
122location of the project relative to `src` as a string ([more information
123on using cleanGit](clean-git.md)). For example:
125```
126 src = pkgs.haskell-nix.haskellLib.cleanGit
127 { src = ./.; subDir = "subdir/another-subdir"; };
128```
130If you want to use a custom filtering function, don't use the built-in nix `filterSource` function.
131Due to some technicalities about how filtering and the nix store work, it will cause all components in
132your project to be rebuilt any time any part of the project source changes. Use `cleanSourceWith` instead:
134```
135 src = pkgs.haskell-nix.haskellLib.cleanSourceWith
136 { src = ./.; filter = myFilterFunction; };
137```
139Note that `cleanSourceWith` will also take the `subDir` argument.
141You can build a component from your project with `nix-build` (in this
142case the `hello` executable in a `helloworld` package):
144```bash
145nix-build -A helloworld.components.exes.hello
146```
148For interactive development you can run:
150```bash
151nix-shell -A shellFor
152```
154The resulting shell will include all the dependencies of the local packages
155listed in your `cabal.project` file (but it will not build those local
156packages).
158Inside the shell use `cabal new-build` and `cabal new-repl` to work on the
159cabal project as you normally would. They will use the packages provided
160by nix whenever possible.
162It is a good idea to add `write-ghc-environment-files: never` to your
163`cabal.project` file to prevent unwanted `.ghc.environment.*` files
164(they will prevent subsequent `nix-shell` invocations from working
165properly).
167Adding an `index-state` to your `cabal.project` can pin the plan used so that
168the same packages will be built each time (until you change the index-state
169or one of the constraints in your local `.cabal` files).
171### Using your stack.yaml file
173If your project has a `stack.yaml` you can add a `default.nix` like this:
175```nix
176{ pkgs ? import <nixpkgs> (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs
177}:
178 pkgs.haskell-nix.stackProject {
179 src = pkgs.haskell-nix.haskellLib.cleanGit { src = ./.; };
180 # pkg-def-extras = [
181 # # Additional packages ontop of all those listed in `stack.yaml`
182 # ];
183 # modules = [
184 # # Specific package overrides would go here for example:
185 # packages.cbors.package.ghcOptions = "-Werror";
186 # packages.cbors.patches = [ ./one.patch ];
187 # packages.cbors.flags.optimize-gmp = false;
188 # # It may be better to set flags in `stack.yaml` instead
189 # # (`stack-to-nix` will include them as defaults).
190 # ];
191 }
192```
194You can build a component from your project with `nix-build` (in this
195case the `hello` executable in a `helloworld` package):
197```bash
198nix-build -A helloworld.components.exes.hello
199```
201### Pinning the [Haskell.nix][] version
203For simplicity's sake we will use `fetchTarball` for the examples in
204this documentation. This will always get the latest version, and is
205similar to an auto-updating Nix channel.
207However, in your own project, you may wish to pin [Haskell.nix][] (as
208you would pin Nixpkgs). This will make your builds reproducable, more
209predictable, and faster (because the fixed version is cached).
211One way of doing this is to use `nix-prefetch-git` to get a JSON file
212with a revision and SHA-256 hash of [Haskell.nix][].
214```
215$ nix-prefetch-git --quiet https://github.com/input-output-hk/haskell.nix | tee haskell-nix-src.json
217 "url": "https://github.com/input-output-hk/haskell.nix",
218 "rev": "f1a94a4c82a2ab999a67c3b84269da78d89f0075",
219 "date": "2019-06-05T01:06:12+00:00",
220 "sha256": "0ggxsppjlb6q6a83y12cwgrdnqnw1s128rpibgzs5p1966bdfqla",
221 "fetchSubmodules": false
223```
225(The `tee` command is just to show you the result.)
226Use the following expression to import that version:
228```nix
229{ nixpkgs ? <nixpkgs> }:
231let
232 spec = builtins.fromJSON (builtins.readFile ./haskell-nix-src.json);
233 haskell-nix-src = (import nixpkgs {}).fetchgit {
234 name = "haskell-lib";
235 inherit (spec) url rev sha256 fetchSubmodules;
236 };
237in
238 import nixpkgs (import haskell-nix-src)
239```
241There are other possible schemes for pinning. See
242[`haskell.nix/lib/fetch-external.nix`](https://github.com/input-output-hk/haskell.nix/blob/master/lib/fetch-external.nix),
243the [niv](https://github.com/nmattia/niv) tool, or the Nix Flakes
244proposal.
246### Overriding the Hackage version
248Sometimes you might want to use a chosen version of Haskell.nix with a
249recent update of Hackage or Stackage. This can be done with JSON pins:
251```bash
252nix-prefetch-git https://github.com/input-output-hk/hackage.nix | tee hackage-src.json
253nix-prefetch-git https://github.com/input-output-hk/stackage.nix | tee stackage-src.json
254```
256The resulting JSON files will correspond to the latest revision of
257[hackage.nix][] and [stackage.nix][]. See
258[Architecture](architecture.md) for more information about how
259these Git repositories correspond to the actual Hackage and Stackage.
261[hackage.nix]: https://github.com/input-output-hk/hackage.nix
262[stackage.nix]: https://github.com/input-output-hk/stackage.nix
264```nix
265{ pkgs ? import <nixpkgs> (haskellNixArgs // { overlays = haskellNixArgs.overlays ++ [
266 (self: super: {
267 haskell-nix = super.haskell-nix // {
268 hackageSourceJSON = ./hackage-src.json;
269 stackageSourceJSON = ./stackage-src.json;
270 };
271 })]; })
272, haskellNixArgs ? (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs
273}:
274 pkgs
275```
277## Using `nix repl`
279It's sometimes useful to load [Haskell.nix][] in the REPL to explore
280attrsets and try examples.
282```
283# example.nix
284{ nixpkgs ? <nixpkgs> }:
285rec {
286 haskell = import nixpkgs (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs;
287 pkgNames = haskell.pkgs.lib.attrNames haskell.haskell-nix.snapshots."lts-13.18";
289```
291Load the example file:
293```
294$ nix repl '<nixpkgs>' example.nix
295Welcome to Nix version 2.3pre6631_e58a7144. Type :? for help.
297Loading '<nixpkgs>'...
298Added 10403 variables.
300Loading 'example2.nix'...
301Added 2 variables.
303nix-repl> lib.take 5 pkgNames
304[ "ALUT" "ANum" "Allure" "Boolean" "BoundedChan" ]
306nix-repl>
307```
309Now that you have `nix-tools` and are able to import [Haskell.nix][],
310you can continue to the next chapter.