aboutsummaryrefslogtreecommitdiff
path: root/doc/manual/expressions/build-script.xml
blob: 5c55954fc3e6f409b941024183b68995b67d65bc (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
<section xmlns="http://docbook.org/ns/docbook"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      version="5.0"
      xml:id='sec-build-script'>

<title>Build Script</title>

<para>Here is the builder referenced
from Hello's Nix expression (stored in
<filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>):</para>

<programlisting>
source $stdenv/setup ①

PATH=$perl/bin:$PATH ②

tar xvfz $src ③
cd hello-*
./configure --prefix=$out ④
make ⑤
make install</programlisting>

<para>The builder can actually be made a lot shorter by using the
<emphasis>generic builder</emphasis> functions provided by
<varname>stdenv</varname>, but here we write out the build steps to
elucidate what a builder does.  It performs the following
steps:</para>

<orderedlist>

  <listitem>

    <para>When Nix runs a builder, it initially completely clears the
    environment (except for the attributes declared in the
    derivation).  This is done to prevent undeclared inputs from being
    used in the build process. If for example the
    <literal>PATH</literal> contained <filename>/usr/bin</filename>,
    then you might accidentally use
    <filename>/usr/bin/gcc</filename>.</para>

    <para>So the first step is to set up the environment.  This is
    done by calling the <filename>setup</filename> script of the
    standard environment.  The environment variable
    <literal>stdenv</literal> points to the location of the standard
    environment being used.  (It wasn't specified explicitly as an
    attribute in <xref linkend='ex-hello-nix' />, but
    <varname>mkDerivation</varname> adds it automatically.)</para>

  </listitem>

  <listitem>

    <para>Since Hello needs Perl, we have to make sure that Perl is in
    the <literal>PATH</literal>.  The <literal>perl</literal> environment
    variable points to the location of the Perl package (since it
    was passed in as an attribute to the derivation), so
    <filename><emphasis>$perl</emphasis>/bin</filename> is the
    directory containing the Perl interpreter.</para>

  </listitem>

  <listitem>

    <para>Now we have to unpack the sources.  The
    <varname>src</varname> attribute was bound to the result of
    fetching the Hello source tarball from the network, so the
    <literal>src</literal> environment variable points to the location in
    the Nix store to which the tarball was downloaded.  After
    unpacking, we <command>cd</command> to the resulting source
    directory.</para>

    <para>The whole build is performed in a temporary directory
    created in <varname>/tmp</varname>, by the way.  This directory is
    removed after the builder finishes, so there is no need to clean
    up the sources afterwards.  Also, the temporary directory is
    always newly created, so you don't have to worry about files from
    previous builds interfering with the current build.</para>

  </listitem>

  <listitem>

    <para>GNU Hello is a typical Autoconf-based package, so we first
    have to run its <filename>configure</filename> script.  In Nix
    every package is stored in a separate location in the Nix store,
    for instance
    <filename>/nix/store/9a54ba97fb71b65fda531012d0443ce2-hello-2.1.1</filename>.
    Nix computes this path by cryptographically hashing all attributes
    of the derivation.  The path is passed to the builder through the
    <literal>out</literal> environment variable.  So here we give
    <filename>configure</filename> the parameter
    <literal>--prefix=$out</literal> to cause Hello to be installed in
    the expected location.</para>

  </listitem>

  <listitem>

    <para>Finally we build Hello (<literal>make</literal>) and install
    it into the location specified by <literal>out</literal>
    (<literal>make install</literal>).</para>

  </listitem>

</orderedlist>

<para>If you are wondering about the absence of error checking on the
result of various commands called in the builder: this is because the
shell script is evaluated with Bash's <option>-e</option> option,
which causes the script to be aborted if any command fails without an
error check.</para>

</section>