git.iko.soy/typeable/cabal2nix
on master help sign in
Add hal8.md to the doc hierarchy.

My intention is to develop that article into a Haskell-centric introduction to Nix.

commit4cff2dec09a0880d95dd6bba424aed9a94aadaf4 authorPeter Simons <simons@cryp.to> dateWed 3 Apr 2013, 01:14 (14 years ago) parent4099ddd
3 files changed+235
doc/.gitignore+5 doc/GNUmakefile+22 doc/hal8.md+208
doc/.gitignorenew file+5
@@ -0,0 +1,5 @@
1+/hal8.aux
2+/hal8.html
3+/hal8.log
4+/hal8.out
5+/hal8.pdf
doc/GNUmakefilenew file+22
@@ -0,0 +1,22 @@
1+# doc/GNUmakefile
2+
3+PANDOC_FLAGS := --smart -V papersize:"a4paper"
4+
5+.PHONY: all clean
6+
7+all: hal8.pdf hal8.html
8+
9+%.tex : %.md
10+ pandoc -s $(PANDOC_FLAGS) -f markdown -t latex $< >$@
11+
12+%.html : %.md
13+ pandoc -s $(PANDOC_FLAGS) -f markdown -t html $< >$@
14+
15+%.pdf : %.tex
16+ pdflatex $<
17+ while grep -i >/dev/null "rerun to.*get.*right" $*.log; do \
18+ pdflatex $<; \
19+ done
20+
21+clean:
22+ @rm -f hal8.aux hal8.html hal8.log hal8.out hal8.pdf hal8.toc
doc/hal8.mdnew file+208
@@ -0,0 +1,208 @@
1+% Managing the Haskell Dependency Hell with Nix
2+% Peter Simons
3+% 2013-04-02
4+
5+# Abstract
6+
7+The Nix package manager has proven very well suited for managing sophisticated
8+Haskell development environments. It has out-of-the-box support for installing
9+Haskell Platforms 2009.2.0.2, 2010.1.0.0, 2010.2.0.0, 2011.2.0.0, 2011.2.0.1,
10+2011.4.0.0, 2012.2.0.0, and 2012.4.0.0 on any machine running Linux or Darwin.
11+Furthermore, Nix provides easy access to well over 700 popular Haskell packages
12+from Hackage. Developers can use Nix to automate building and testing of their
13+Haskell packages, either by running those builds locally on-demand, or by
14+relying on the Continuous Integration service Hydra. Last but not least,
15+Haskell programmers will probably enjoy the fact that Nix packages are written
16+in a language that is, essentially, lazily evaluated lambda calculus.
17+
18+This presentation introduces the principles of the Nix package manager, and
19+provides a hands-on tour through its essential features, teaching Haskell
20+developers how to
21+
22+ - manage their working environment with Nix,
23+ - extend the Nix packages database with their own packages, and
24+ - utilize the advanced continuous integration features.
25+
26+# Introduction
27+
28+Purely functional programming languages like Haskell encourage software
29+engineers to write re-usable code. As of today, the Haskell community's central
30+repository "Hackage" registers 5015 packages, 3944 of which provide function
31+libraries. This means that approximately 78% of all Haskell packages are
32+intended to be re-used by other developers. For Haskell programmers, this is a
33+good situation to be in! There is a lot of re-usable code out there, and the
34+pool to choose from is growing steadily.
35+
36+However, the fact that Haskell packages re-use each other a lot comes at a
37+price: a phenomenon lovingly referred to as "dependency hell". The task of
38+installing a Haskell package includes the installation of all its dependencies
39+(and their respective dependencies). Updating a Haskell package typically
40+requires updates of that package's dependencies as well. And if a package is
41+de-installed, then chances are that some of its dependencies become unused in
42+the process and ought to be de-installed, too.
43+
44+Many Haskell programmers turn to Cabal for help --- only to find that Cabal
45+doesn't really address those tasks. Cabal can install a package, alright, but
46+it cannot perform reliable updates or clean up the system after a
47+de-installation. Arguably, Cabal doesn't even address the installation part
48+satisfactorily, because it is unaware of all software outside of the domain of
49+Haskell. The package "hsdns", for example, needs the GNU ADNS library installed
50+to compile, but Cabal doesn't know anything about GNU ADNS. It cannot install
51+that library as part of the hsdns build. All it can do is abort with an error
52+message, saying "the adns library is missing", but it's the users problem to
53+remedy that situation somehow.
54+
55+Traditional package managers like `apt-get`, `rpm`, `pacman`, or `BSD ports`
56+are designed to solve exactly those issues. These programs are really good at
57+installing system packages. They know how to keep the installation up-to-date
58+without breaking anything, and they know how clean-up after themselves when a
59+package has been removed. Yet, those package managers are somewhat unprepared
60+for the complexity of Haskell's package system. For example, most package
61+managers assume that for any given package `A`, only one version of `A` can be
62+installed at the same time. This is certainly not true for Haskell, where
63+oftentimes a whole zoo of mutually incompatible library versions need to be
64+installed at the same time to build all installation targets. The same problem
65+applies to the installation of the compiler. Developers who care about portable
66+code need many different versions of GHC installed in parallel, so that their
67+code can be tested with different compiler variants, but the ability to manage
68+an installation of this complexity is far out of the reach of traditional
69+package managers.
70+
71+# The Nix Package Manager
72+
73+Nix [1] is a package manager very much like `apt-get` or `rpm`. At the same
74+time, Nix differs from traditional package managers, because it breaks with the
75+established Unix file system layout. Instead of installing executable programs
76+into `/usr/bin` and libraries into `/usr/lib`, Nix installs every package into
77+a directory hierarchy of its own. For example, all files that belong to the
78+package GHC 7.6.2 reside underneath the prefix:
79+
80+ $ ls /nix/store/f2c7ia72ial5y8h5k1w7z5n87xnr5gm6-ghc-7.6.2/
81+ bin lib share
82+
83+This installation scheme allows any number of GHC versions to co-exist, because
84+they live in completely different places:
85+
86+ $ ls /nix/store/*-ghc-*/bin/ghc
87+ /nix/store/cczdxjhrx27wmf4rpk4rk70zabw2fggd-ghc-6.10.4/bin/ghc
88+ /nix/store/n6ygpkh29dfp9di27l70681k7llnhama-ghc-6.12.3/bin/ghc
89+ /nix/store/frziw92yvb0rgm7sx7zzsmgy7cyl16d9-ghc-7.0.4/bin/ghc
90+ /nix/store/82lkfs5c4l41p244apv7q5dmd91h712d-ghc-7.4.2/bin/ghc
91+ /nix/store/ch0cq5l0l8p7g80skifivrg4d40s8sdm-ghc-7.6.2/bin/ghc
92+
93+Furthermore, packages compiled by Nix generally don't refer to any system path
94+outside of `/nix/store`. GHC depends on system libraries like glibc, libgmp,
95+and curses, but all those dependencies are satisfied entirely within Nix:
96+
97+ $ ldd ghc
98+ /nix/store/ml128hlikbl14q4cwviafpaskskx1a3f-ncurses-5.9/lib/libncursesw.so.5
99+ /nix/store/zpr8jdx10napidkyz62f3nzl5fm87jyr-glibc-2.17/lib/librt.so.1
100+ /nix/store/zpr8jdx10napidkyz62f3nzl5fm87jyr-glibc-2.17/lib/libutil.so.1
101+ /nix/store/zpr8jdx10napidkyz62f3nzl5fm87jyr-glibc-2.17/lib/libdl.so.2
102+ /nix/store/zpr8jdx10napidkyz62f3nzl5fm87jyr-glibc-2.17/lib/libm.so.6
103+ /nix/store/zpr8jdx10napidkyz62f3nzl5fm87jyr-glibc-2.17/lib/libpthread.so.0
104+ /nix/store/zpr8jdx10napidkyz62f3nzl5fm87jyr-glibc-2.17/lib/libc.so.6
105+ /nix/store/989njbbf770sxyqqpyrw2m0cbfdynzbb-gmp-5.0.5/lib/libgmp.so.10
106+
107+The `/nix/store` hierarchy is completely self-contained. A Haskell development
108+environment that's been created on one machine can be copied to any other
109+machine simply by running "`rsync -a /nix other-machine:/`".
110+
111+A quick glance at the store paths shown above reveals yet another powerful
112+feature. The exact path used to store an installed package contains a
113+cryptographic hash that uniquely identifies
114+
115+ 1. the shell command sequence that built this particular package and
116+ 2. all other store paths that this package depends on.
117+
118+Suppose that GHC 7.6.2 would be compiled two times. The first build uses GCC
119+version 4.6.3 to build the Haskell compiler, but the second build uses GCC 4.7.
120+Then the results of those two builds would be stored in paths like
121+
122+ - `/nix/store/ch0cq5l0l8p7g80skifivrg4d40s8sdm-ghc-7.6.2` and
123+ - `/nix/store/f2c7ia72ial5y8h5k1w7z5n87xnr5gm6-ghc-7.6.2`.
124+
125+The cryptographic hashes assigned to those two paths differs because both
126+variants of GHC 7.6.2 have different dependencies (GCC 4.6.3 and 4.7
127+respectively). Because of this approach, Nix is able to satisfy the
128+requirements of the Haskell package system, which needs to keep multiple
129+versions of the same package around concurrently. Nix can easily do that,
130+simply by having a separate store path for each variant of the package.
131+
132+These capabilities make Nix rather well suited for maintaining sophisticated
133+Haskell development environments, and the remainder of this article is intended
134+to provide a hands-on tutorial of how to use Nix for exactly that purpose.
135+
136+# Installing the Haskell Platform
137+
138+The installation procedure of Nix itself is fairly straightforward.
139+Ready-to-use binary packages are available for many Linux platforms
140+(particularly on x86, x86_64, and PowerPC), for Mac OS X, and for FreeBSD.
141+Furthermore, Nix can be compiled from source code on any POSIX-like operating
142+system. Detailed installation instructions can be found at [2].
143+
144+Once Nix itself is installed, it can be used to obtain an up-to-date copy of
145+the Nix package database by running:
146+
147+ $ nix-channel --add http://nixos.org/channels/nixpkgs-unstable
148+ $ nix-channel --update
149+
150+Now, it is possible to see the entire set of packages known to Nix by running:
151+
152+ $ nix-env -qaP '*'
153+ pkgs.pong3d 3dpong-0.5.0
154+ pkgs.rdf4store 4store-v1.1.5
155+ pkgs.foursuite 4suite-1.0.2
156+ ... ...
157+
158+The output consists of two columns. The right hand-side shows the
159+human-readable name and version of the package. The left hand-side shows a
160+unique identifier for that particular package in the Nix package database. Both
161+identifiers can be used to install packages:
162+
163+ $ nix-env -i 3dpong-0.5.0 # install by name
164+ $ nix-env -iA pkgs.pong3d # install by attribute
165+
166+Now, to install the Haskell Platform, we first need to make up our mind which
167+version we want, because there are plenty to choose from. The command
168+
169+ $ nix-env -qaP '*' | grep haskell-platform
170+
171+shows that all of the versions 2009.2.0.2, 2010.1.0.0, 2010.2.0.0, 2011.2.0.0,
172+2011.2.0.1, 2011.4.0.0, 2012.2.0.0, and 2012.4.0.0 are available, and each of
173+those versions of Haskell Platform can be compiled with GHC versions 6.10.4,
174+6.12.1, 6.12.2, 6.12.3, 7.0.1, 7.0.2, 7.0.3, 7.0.4, 7.2.1, 7.2.2, 7.4.1, 7.4.2,
175+7.6.1, and 7.6.2 respectively!
176+
177+For the sake of the example, let's just choose the latest official version:
178+
179+ $ nix-env -iA haskellPackages.haskellPlatform
180+ installing `haskell-haskell-platform-ghc7.4.2-2012.4.0.0'
181+ ...
182+ building path(s) `/nix/store/j1gq9xciqj3390himzi3p9xcln9hnxl4-user-environment'
183+ created 1159 symlinks in user environment
184+
185+When that command is run for the first time, it will download and install a
186+*lot* of packages, because the Haskell Platform depends on many other things
187+such as the Linux kernel headers, glibc, GCC, GMP, Perl, and so on. Of course,
188+these packages will be re-used when installing a different version of the
189+Haskell Platform later, so one doesn't have to worry that every single install
190+is going to be that expensive.
191+
192+In its last step, `nix-env` creates a "user environment" at
193+`$HOME/.nix-profile`, which simplies use of the installed packages a lot. That
194+environment uses symlinks to create a view of the Nix store that combines those
195+packages that have been installed into a single hierarchy. For example, the
196+path `~/.nix-profile/bin/ghc` will be a symlink to
197+`/nix/store/vlx3ikjjxlfvqjjlx74cg07p79y43mdq-ghc-7.4.2/bin/ghc`. The path
198+`~/.nix-profile/bin/alex`, on the other hand, points to
199+`/nix/store/7rfilvshj9wzm3rx86m4mkpf76l24fhs-alex-3.0.2/bin/alex`. The binaries
200+`alex` and `ghc` live in different store paths, but the user environment joins
201+all those paths into a single hierarchy. This means that it is sufficient to
202+add `$HOME/.nix-profile/bin` to `$PATH` to use the Haskell Platform from Nix.
203+
204+# References
205+
206+[1] Nix, the purely functional package manager: <http://nixos.org/nix/>
207+
208+[2] Nix Installation Instructions: <http://hydra.nixos.org/build/4480483/download/1/manual/#chap-installation>