on e94de40 help sign in
haskell.nix/docs/dev/manually-generating-nix-expressions.md
179 lines 5.3 kB history raw
1# Manually generating Nix expressions
3We believe that imports from derivations (IFDs) provide tremendous
4value in nix and the aversion towards them stems mostly from
5poor tooling and ci support for them. We do not believe
6that poor tooling or ci support should cripple nix capability
7of abstraction. Hence haskell.nix makes excessive use of
8IFDs.
10We do note however that there are users who prefer to
11have IFD-free expressions. For this group of users we
12detail how to expand the IFD dependent high level functions
13into their IFD free building blocks.
15The general structure will be the same, independent of the use of
16Stack or Cabal.
18Let us assume for now that we have already generated a `pkgs.nix`
19expression (see the links bellow). The following file then produces a package set:
21```nix
22# default.nix
23let
24 # Import the Haskell.nix library,
25 pkgs = import <nixpkgs> (import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}).nixpkgsArgs;
27 # Import the file you will create in the stack-to-nix or cabal-to-nix step.
28 my-pkgs = import ./pkgs.nix;
30 # Stack projects use this:
31 pkgSet = pkgs.haskell-nix.mkStackPkgSet {
32 stack-pkgs = my-pkgs;
33 pkg-def-extras = [
34 # these extras will provide additional packages
35 # ontop of the package set. E.g. extra-deps
36 # for stack packages. or local packages for
37 # cabal.projects
38 ];
39 modules = [
40 # specific package overrides would go here
41 # example:
42 # packages.cbors.package.ghcOptions = "-Werror";
43 # packages.cbors.patches = [ ./one.patch ];
44 # packages.cbors.flags.optimize-gmp = false;
45 # It may be better to set flags in stack.yaml instead
46 # (`stack-to-nix` will include them as defaults).
47 ];
48 };
50 # Cabal projects use this:
51 pkgSet = pkgs.haskell-nix.mkCabalProjectPkgSet {
52 plan-pkgs = my-pkgs;
53 pkg-def-extras = [];
54 modules = [
55 # specific package overrides would go here
56 # example:
57 # packages.cbors.package.ghcOptions = "-Werror";
58 # packages.cbors.patches = [ ./one.patch ];
59 # packages.cbors.flags.optimize-gmp = false;
60 # It may be better to set flags in `cabal.project` instead
61 # (`plan-to-nix` will include them as defaults).
62 ];
63 };
65in pkgSet.config.hsPkgs // { _config = pkgSet.config; }
66```
68With this setup you can then start building the components of
69interest:
71```bash
72nix build -f default.nix $pkg.components.library
73```
75to build the library for `$pkg` or
77```bash
78nix build -f default.nix $pkg.components.exes.$exe
79```
81to build a specific executable. The same holds for test suites and benchmarks.
83## Using Stack
85With [nix-tools installed](./installing-nix-tools.md), we can simply run the
86following command on a stack project:
88```bash
89stack-to-nix --output . --stack-yaml stack.yaml
90```
92This will produce a `pkgs.nix` file that looks like the following:
93```nix
95 resolver = "lts-12.17";
96 extras = hackage:
97 {
98 packages = {
99 "o-clock" = hackage.o-clock."0.1.1".revisions.default;
100 ...
101 } // {
102 my-package = ./my-package.nix;
103 ...
104 };
105 };
107```
109This file contains the stackage resolver, as well as set of extra
110packages. The extras specifies which `extra-deps` (here:
111`o-clock-0.1.1`) we wanted to add over the stackage snapshot, and what
112local packages we want (here: `my-package`).
114## Using Cabal
116### Generating `plan.json`
118To get a plan, you need Cabal and GHC. See the [How to install a
119compiler section of the Nixpkgs Manual][compiler] for information
120about how to choose a specific compiler version.
122[compiler]: https://nixos.org/nixpkgs/manual/#how-to-install-a-compiler
124!!! note "Cabal version"
125 The minimum Cabal version is 2.4. This version is available
126 in the NixOS 19.03 release.
128For this example, we will run a `nix-shell` with the default GHC
129version for Nixpkgs.
131```bash
132nix-shell -p haskellPackages.cabal-install haskellPackages.ghc \
133 --run "cabal new-configure"
134```
136If all goes well, you should now have the file
137`dist-newstyle/cache/plan.json`.
139!!! tip "Specifying the GHC version"
140 To use a specific compiler version, replace `haskellPackages.ghc`
141 with something like `haskell-nix.compiler.ghc865`. The given compiler
142 must exist in your Nixpkgs version, of course. See also the
143 [Nixpkgs Manual][compiler].
145### Using `plan-to-nix`
147With [nix-tools installed](./installing-nix-tools.md), we can then run the
148following command on a Cabal project and its build plan. Omit the
149`--cabal-project` option if you don't have a project file.
151```bash
152# convert the plan.json file into a pkgs.nix file
153plan-to-nix --output . \
154 --plan-json dist-newstyle/cache/plan.json
155 --cabal-project cabal.project
156```
158This will produce a `pkgs.nix` file that looks like the following:
160```nix
162 pkgs = hackage:
163 {
164 packages = {
165 "o-clock" = hackage.o-clock."0.1.1".revisions.default;
166 ...
167 };
168 compiler = { ... };
169 };
171 extras = hackage:
172 { packages = { my-package = ./.plan.nix/my-package.nix; }; };
174```
176It has converted Cabal's build plan into a Nix expression that selects
177dependencies from `hackage.nix`. All local packages in the project are
178generated with `cabal-to-nix` and added to the package set
179description.