aboutsummaryrefslogtreecommitdiff
path: root/doc/manual/writing-nix-expressions.xml
blob: eb366c249c326301762819fa4dacf41b146399a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<chapter id='chap-writing-nix-expressions'><title>Writing Nix Expressions</title>

<sect1><title>A simple Nix expression</title>

<para>This section shows how to write simple Nix expressions  the
things that describe how to build a package.</para>

<example id='ex-hello-nix'><title>Nix expression for GNU Hello</title>
<programlisting>
{stdenv, fetchurl, perl}: <co id='ex-hello-nix-co-1' />

derivation { <co id='ex-hello-nix-co-2' />
  name = "hello-2.1.1"; <co id='ex-hello-nix-co-3' />
  system = stdenv.system; <co id='ex-hello-nix-co-4' />
  builder = ./builder.sh; <co id='ex-hello-nix-co-5' />
  src = fetchurl { <co id='ex-hello-nix-co-6' />
    url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
    md5 = "70c9ccf9fac07f762c24f2df2290784d";
  };
  stdenv = stdenv; <co id='ex-hello-nix-co-7' />
  perl = perl;
}</programlisting>
</example>

<para>A simple Nix expression is shown in <xref linkend='ex-hello-nix'
/>. It describes how to the build the <ulink
url='http://www.gnu.org/directory/GNU/hello.html'>GNU Hello
package</ulink>.  This package has several dependencies.  First, it
requires a number of other packages, such as a C compiler, standard
Unix shell tools, and Perl.  Rather than have this Nix expression
refer to and use specific versions of these packages, it should be
generic; that is, it should be a <emphasis>function</emphasis> that
takes the required packages as inputs and yield a build of the GNU
Hello package as a result.  This Nix expression defines a function
with three arguments <xref linkend='ex-hello-nix-co-1' />, namely:

  <orderedlist>
    <listitem><para><varname>stdenv</varname>, which should be a
    <emphasis>standard environment package</emphasis>.  The standard
    environment is a set of tools and other components that would be
    expected in a fairly minimal Unix-like environment: a C compiler
    and linker, Unix shell tools, and so on.</para></listitem>
    
    <listitem><para><varname>fetchurl</varname>, which should be a
    function that given parameters <varname>url</varname> and
    <varname>md5</varname>, will fetch a file from the specified
    location and check that this file has the given MD5 hash code.
    The hash is required because build operations must be
    <emphasis>pure</emphasis>: given the same inputs they should
    always yield the same output.  Since network resources can change
    at any time, we must in some way guarantee what the result will
    be.</para></listitem>
    
    <listitem><para><varname>perl</varname>, which should be a Perl
    interpreter.</para></listitem>
    
  </orderedlist>
</para>

<para>The remainder of the file is the body of the function, which
happens to be a <emphasis>derivation</emphasis> <xref
linkend='ex-hello-nix-co-2' />, which is the built-in function
<varname>derivation</varname> applied to a set of attributes that
encode all the necessary information for building the GNU Hello
package.</para>

<example><title>Build script (<filename>builder.sh</filename>) for GNU
Hello</title>
<programlisting>
#! /bin/sh

buildinputs="$perl"
. $stdenv/setup || exit 1

tar xvfz $src || exit 1
cd hello-* || exit 1
./configure --prefix=$out || exit 1
make || exit 1
make install || exit 1</programlisting>
</example>

</sect1>


<sect1><title>A more complex Nix expression</title>

<example id='ex-svn-nix'><title>Nix expression for Subversion</title>
<programlisting>
{ localServer ? false <co id='ex-svn-nix-co-1' />
, httpServer ? false
, sslSupport ? false
, swigBindings ? false
, stdenv, fetchurl
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null
}:

assert !isNull expat; <co id='ex-svn-nix-co-2' />
assert localServer -> !isNull db4;
assert httpServer -> !isNull httpd &amp;&amp; httpd.expat == expat; <co id='ex-svn-nix-co-3' />
assert sslSupport -> !isNull openssl &amp;&amp; (httpServer -> httpd.openssl == openssl);
assert swigBindings -> !isNull swig;

derivation {
  name = "subversion-0.32.1";
  system = stdenv.system;

  builder = ./builder.sh;
  src = fetchurl {
    url = http://svn.collab.net/tarballs/subversion-0.32.1.tar.gz;
    md5 = "b06717a8ef50db4b5c4d380af00bd901";
  };

  localServer = localServer;
  httpServer = httpServer;
  sslSupport = sslSupport;
  swigBindings = swigBindings;

  stdenv = stdenv;
  openssl = if sslSupport then openssl else null; <co id='ex-svn-nix-co-4' />
  httpd = if httpServer then httpd else null;
  expat = expat;
  db4 = if localServer then db4 else null;
  swig = if swigBindings then swig else null;
}</programlisting>
</example>

<para>This example shows several features.  Default parameters <xref
linkend='ex-svn-nix-co-1'/> can be used to simplify call sites: if an
argument that has a default is omitted, its default value is
used.</para>

<para>You can use <emphasis>assertions</emphasis> to test whether
arguments satisfy certain constraints.  The simple assertion <xref
linkend='ex-svn-nix-co-2'/> tests whether the <varname>expat</varname>
argument is not a null value.  The more complex assertion <xref
linkend='ex-svn-nix-co-3'/> says that if Subversion is built with
Apache support, then <varname>httpd</varname> (the Apache package)
must not be null and it must have been built using the same instance
of the <varname>expat</varname> library as was passed to the
Subversion expression.  This is since the Subversion code is
dynamically linked against the Apache code and they both use Expat,
they must be linked against the same instance  otherwise a conflict
might occur.</para>

</sect1>


</chapter>