diff options
Diffstat (limited to 'doc/manual/expressions')
-rw-r--r-- | doc/manual/expressions/advanced-attributes.xml | 289 | ||||
-rw-r--r-- | doc/manual/expressions/arguments-variables.xml | 121 | ||||
-rw-r--r-- | doc/manual/expressions/build-script.xml | 119 | ||||
-rw-r--r-- | doc/manual/expressions/builder-syntax.xml | 119 | ||||
-rw-r--r-- | doc/manual/expressions/builtins.xml | 1196 | ||||
-rw-r--r-- | doc/manual/expressions/debug-build.xml | 34 | ||||
-rw-r--r-- | doc/manual/expressions/derivations.xml | 211 | ||||
-rw-r--r-- | doc/manual/expressions/expression-language.xml | 30 | ||||
-rw-r--r-- | doc/manual/expressions/expression-syntax.xml | 148 | ||||
-rw-r--r-- | doc/manual/expressions/generic-builder.xml | 98 | ||||
-rw-r--r-- | doc/manual/expressions/language-constructs.xml | 350 | ||||
-rw-r--r-- | doc/manual/expressions/language-operators.xml | 113 | ||||
-rw-r--r-- | doc/manual/expressions/language-values.xml | 309 | ||||
-rw-r--r-- | doc/manual/expressions/simple-building-testing.xml | 86 | ||||
-rw-r--r-- | doc/manual/expressions/simple-expression.xml | 47 | ||||
-rw-r--r-- | doc/manual/expressions/writing-nix-expressions.xml | 26 |
16 files changed, 3296 insertions, 0 deletions
diff --git a/doc/manual/expressions/advanced-attributes.xml b/doc/manual/expressions/advanced-attributes.xml new file mode 100644 index 000000000000..83ad6eefc8b1 --- /dev/null +++ b/doc/manual/expressions/advanced-attributes.xml @@ -0,0 +1,289 @@ +<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-advanced-attributes"> + +<title>Advanced Attributes</title> + +<para>Derivations can declare some infrequently used optional +attributes.</para> + +<variablelist> + + <varlistentry><term><varname>allowedReferences</varname></term> + + <listitem><para>The optional attribute + <varname>allowedReferences</varname> specifies a list of legal + references (dependencies) of the output of the builder. For + example, + +<programlisting> +allowedReferences = []; +</programlisting> + + enforces that the output of a derivation cannot have any runtime + dependencies on its inputs. To allow an output to have a runtime + dependency on itself, use <literal>"out"</literal> as a list item. + This is used in NixOS to check that generated files such as + initial ramdisks for booting Linux don’t have accidental + dependencies on other paths in the Nix store.</para></listitem> + + </varlistentry> + + + <varlistentry><term><varname>allowedRequisites</varname></term> + + <listitem><para>This attribute is similar to + <varname>allowedReferences</varname>, but it specifies the legal + requisites of the whole closure, so all the dependencies + recursively. For example, + +<programlisting> +allowedRequisites = [ foobar ]; +</programlisting> + + enforces that the output of a derivation cannot have any other + runtime dependency than <varname>foobar</varname>, and in addition + it enforces that <varname>foobar</varname> itself doesn't + introduce any other dependency itself.</para></listitem> + + </varlistentry> + + + <varlistentry><term><varname>exportReferencesGraph</varname></term> + + <listitem><para>This attribute allows builders access to the + references graph of their inputs. The attribute is a list of + inputs in the Nix store whose references graph the builder needs + to know. The value of this attribute should be a list of pairs + <literal>[ <replaceable>name1</replaceable> + <replaceable>path1</replaceable> <replaceable>name2</replaceable> + <replaceable>path2</replaceable> <replaceable>...</replaceable> + ]</literal>. The references graph of each + <replaceable>pathN</replaceable> will be stored in a text file + <replaceable>nameN</replaceable> in the temporary build directory. + The text files have the format used by <command>nix-store + --register-validity</command> (with the deriver fields left + empty). For example, when the following derivation is built: + +<programlisting> +derivation { + ... + exportReferencesGraph = [ "libfoo-graph" libfoo ]; +}; +</programlisting> + + the references graph of <literal>libfoo</literal> is placed in the + file <filename>libfoo-graph</filename> in the temporary build + directory.</para> + + <para><varname>exportReferencesGraph</varname> is useful for + builders that want to do something with the closure of a store + path. Examples include the builders in NixOS that generate the + initial ramdisk for booting Linux (a <command>cpio</command> + archive containing the closure of the boot script) and the + ISO-9660 image for the installation CD (which is populated with a + Nix store containing the closure of a bootable NixOS + configuration).</para></listitem> + + </varlistentry> + + + <varlistentry><term><varname>impureEnvVars</varname></term> + + <listitem><para>This attribute allows you to specify a list of + environment variables that should be passed from the environment + of the calling user to the builder. Usually, the environment is + cleared completely when the builder is executed, but with this + attribute you can allow specific environment variables to be + passed unmodified. For example, <function>fetchurl</function> in + Nixpkgs has the line + +<programlisting> +impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ]; +</programlisting> + + to make it use the proxy server configuration specified by the + user in the environment variables <envar>http_proxy</envar> and + friends.</para> + + <para>This attribute is only allowed in <link + linkend="fixed-output-drvs">fixed-output derivations</link>, where + impurities such as these are okay since (the hash of) the output + is known in advance. It is ignored for all other + derivations.</para></listitem> + + </varlistentry> + + + <varlistentry xml:id="fixed-output-drvs"> + <term><varname>outputHash</varname></term> + <term><varname>outputHashAlgo</varname></term> + <term><varname>outputHashMode</varname></term> + + <listitem><para>These attributes declare that the derivation is a + so-called <emphasis>fixed-output derivation</emphasis>, which + means that a cryptographic hash of the output is already known in + advance. When the build of a fixed-output derivation finishes, + Nix computes the cryptographic hash of the output and compares it + to the hash declared with these attributes. If there is a + mismatch, the build fails.</para> + + <para>The rationale for fixed-output derivations is derivations + such as those produced by the <function>fetchurl</function> + function. This function downloads a file from a given URL. To + ensure that the downloaded file has not been modified, the caller + must also specify a cryptographic hash of the file. For example, + +<programlisting> +fetchurl { + url = http://ftp.gnu.org/pub/gnu/hello/hello-2.1.1.tar.gz; + md5 = "70c9ccf9fac07f762c24f2df2290784d"; +} +</programlisting> + + It sometimes happens that the URL of the file changes, e.g., + because servers are reorganised or no longer available. We then + must update the call to <function>fetchurl</function>, e.g., + +<programlisting> +fetchurl { + url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz; + md5 = "70c9ccf9fac07f762c24f2df2290784d"; +} +</programlisting> + + If a <function>fetchurl</function> derivation was treated like a + normal derivation, the output paths of the derivation and + <emphasis>all derivations depending on it</emphasis> would change. + For instance, if we were to change the URL of the Glibc source + distribution in Nixpkgs (a package on which almost all other + packages depend) massive rebuilds would be needed. This is + unfortunate for a change which we know cannot have a real effect + as it propagates upwards through the dependency graph.</para> + + <para>For fixed-output derivations, on the other hand, the name of + the output path only depends on the <varname>outputHash*</varname> + and <varname>name</varname> attributes, while all other attributes + are ignored for the purpose of computing the output path. (The + <varname>name</varname> attribute is included because it is part + of the path.)</para> + + <para>As an example, here is the (simplified) Nix expression for + <varname>fetchurl</varname>: + +<programlisting> +{ stdenv, curl }: # The <command>curl</command> program is used for downloading. + +{ url, md5 }: + +stdenv.mkDerivation { + name = baseNameOf (toString url); + builder = ./builder.sh; + buildInputs = [ curl ]; + + # This is a fixed-output derivation; the output must be a regular + # file with MD5 hash <varname>md5</varname>. + outputHashMode = "flat"; + outputHashAlgo = "md5"; + outputHash = md5; + + inherit url; +} +</programlisting> + + </para> + + <para>The <varname>outputHashAlgo</varname> attribute specifies + the hash algorithm used to compute the hash. It can currently be + <literal>"md5"</literal>, <literal>"sha1"</literal> or + <literal>"sha256"</literal>.</para> + + <para>The <varname>outputHashMode</varname> attribute determines + how the hash is computed. It must be one of the following two + values: + + <variablelist> + + <varlistentry><term><literal>"flat"</literal></term> + + <listitem><para>The output must be a non-executable regular + file. If it isn’t, the build fails. The hash is simply + computed over the contents of that file (so it’s equal to what + Unix commands like <command>md5sum</command> or + <command>sha1sum</command> produce).</para> + + <para>This is the default.</para></listitem> + + </varlistentry> + + <varlistentry><term><literal>"recursive"</literal></term> + + <listitem><para>The hash is computed over the NAR archive dump + of the output (i.e., the result of <link + linkend="refsec-nix-store-dump"><command>nix-store + --dump</command></link>). In this case, the output can be + anything, including a directory tree.</para></listitem> + + </varlistentry> + + </variablelist> + + </para> + + <para>The <varname>outputHash</varname> attribute, finally, must + be a string containing the hash in either hexadecimal or base-32 + notation. (See the <link + linkend="sec-nix-hash"><command>nix-hash</command> command</link> + for information about converting to and from base-32 + notation.)</para></listitem> + + </varlistentry> + + + <varlistentry><term><varname>passAsFile</varname></term> + + <listitem><para>A list of names of attributes that should be + passed via files rather than environment variables. For example, + if you have + + <programlisting> +passAsFile = ["big"]; +big = "a very long string"; + </programlisting> + + then when the builder runs, the environment variable + <envar>bigPath</envar> will contain the absolute path to a + temporary file containing <literal>a very long + string</literal>. That is, for any attribute + <replaceable>x</replaceable> listed in + <varname>passAsFile</varname>, Nix will pass an environment + variable <envar><replaceable>x</replaceable>Path</envar> holding + the path of the file containing the value of attribute + <replaceable>x</replaceable>. This is useful when you need to pass + large strings to a builder, since most operating systems impose a + limit on the size of the environment (typically, a few hundred + kilobyte).</para></listitem> + + </varlistentry> + + + <varlistentry><term><varname>preferLocalBuild</varname></term> + + <listitem><para>If this attribute is set to + <literal>true</literal>, it has two effects. First, the + derivation will always be built, not substituted, even if a + substitute is available. Second, if <link + linkend="chap-distributed-builds">distributed building is + enabled</link>, then, if possible, the derivaton will be built + locally instead of forwarded to a remote machine. This is + appropriate for trivial builders where the cost of doing a + download or remote build would exceed the cost of building + locally.</para></listitem> + + </varlistentry> + +</variablelist> + +</section> diff --git a/doc/manual/expressions/arguments-variables.xml b/doc/manual/expressions/arguments-variables.xml new file mode 100644 index 000000000000..bf60cb7eef8a --- /dev/null +++ b/doc/manual/expressions/arguments-variables.xml @@ -0,0 +1,121 @@ +<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-arguments'> + +<title>Arguments and Variables</title> + +<example xml:id='ex-hello-composition'> + +<title>Composing GNU Hello +(<filename>all-packages.nix</filename>)</title> +<programlisting> +... + +rec { <co xml:id='ex-hello-composition-co-1' /> + + hello = import ../applications/misc/hello/ex-1 <co xml:id='ex-hello-composition-co-2' /> { <co xml:id='ex-hello-composition-co-3' /> + inherit fetchurl stdenv perl; + }; + + perl = import ../development/interpreters/perl { <co xml:id='ex-hello-composition-co-4' /> + inherit fetchurl stdenv; + }; + + fetchurl = import ../build-support/fetchurl { + inherit stdenv; ... + }; + + stdenv = ...; + +} +</programlisting> +</example> + +<para>The Nix expression in <xref linkend='ex-hello-nix' /> is a +function; it is missing some arguments that have to be filled in +somewhere. In the Nix Packages collection this is done in the file +<filename>pkgs/top-level/all-packages.nix</filename>, where all +Nix expressions for packages are imported and called with the +appropriate arguments. <xref linkend='ex-hello-composition' /> shows +some fragments of +<filename>all-packages.nix</filename>.</para> + +<calloutlist> + + <callout arearefs='ex-hello-composition-co-1'> + + <para>This file defines a set of attributes, all of which are + concrete derivations (i.e., not functions). In fact, we define a + <emphasis>mutually recursive</emphasis> set of attributes. That + is, the attributes can refer to each other. This is precisely + what we want since we want to <quote>plug</quote> the + various packages into each other.</para> + + </callout> + + <callout arearefs='ex-hello-composition-co-2'> + + <para>Here we <emphasis>import</emphasis> the Nix expression for + GNU Hello. The import operation just loads and returns the + specified Nix expression. In fact, we could just have put the + contents of <xref linkend='ex-hello-nix' /> in + <filename>all-packages.nix</filename> at this point. That + would be completely equivalent, but it would make the file rather + bulky.</para> + + <para>Note that we refer to + <filename>../applications/misc/hello/ex-1</filename>, not + <filename>../applications/misc/hello/ex-1/default.nix</filename>. + When you try to import a directory, Nix automatically appends + <filename>/default.nix</filename> to the file name.</para> + + </callout> + + <callout arearefs='ex-hello-composition-co-3'> + + <para>This is where the actual composition takes place. Here we + <emphasis>call</emphasis> the function imported from + <filename>../applications/misc/hello/ex-1</filename> with a set + containing the things that the function expects, namely + <varname>fetchurl</varname>, <varname>stdenv</varname>, and + <varname>perl</varname>. We use inherit again to use the + attributes defined in the surrounding scope (we could also have + written <literal>fetchurl = fetchurl;</literal>, etc.).</para> + + <para>The result of this function call is an actual derivation + that can be built by Nix (since when we fill in the arguments of + the function, what we get is its body, which is the call to + <varname>stdenv.mkDerivation</varname> in <xref + linkend='ex-hello-nix' />).</para> + + <note><para>Nixpkgs has a convenience function + <function>callPackage</function> that imports and calls a + function, filling in any missing arguments by passing the + corresponding attribute from the Nixpkgs set, like this: + +<programlisting> +hello = callPackage ../applications/misc/hello/ex-1 { }; +</programlisting> + + If necessary, you can set or override arguments: + +<programlisting> +hello = callPackage ../applications/misc/hello/ex-1 { stdenv = myStdenv; }; +</programlisting> + + </para></note> + + </callout> + + <callout arearefs='ex-hello-composition-co-4'> + + <para>Likewise, we have to instantiate Perl, + <varname>fetchurl</varname>, and the standard environment.</para> + + </callout> + +</calloutlist> + +</section> \ No newline at end of file diff --git a/doc/manual/expressions/build-script.xml b/doc/manual/expressions/build-script.xml new file mode 100644 index 000000000000..7bad8f808d58 --- /dev/null +++ b/doc/manual/expressions/build-script.xml @@ -0,0 +1,119 @@ +<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> + +<example xml:id='ex-hello-builder'><title>Build script for GNU Hello +(<filename>builder.sh</filename>)</title> +<programlisting> +source $stdenv/setup <co xml:id='ex-hello-builder-co-1' /> + +PATH=$perl/bin:$PATH <co xml:id='ex-hello-builder-co-2' /> + +tar xvfz $src <co xml:id='ex-hello-builder-co-3' /> +cd hello-* +./configure --prefix=$out <co xml:id='ex-hello-builder-co-4' /> +make <co xml:id='ex-hello-builder-co-5' /> +make install</programlisting> +</example> + +<para><xref linkend='ex-hello-builder' /> shows the builder referenced +from Hello's Nix expression (stored in +<filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>). +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> + +<calloutlist> + + <callout arearefs='ex-hello-builder-co-1'> + + <para>When Nix runs a builder, it initially completely clears the + environment (except for the attributes declared in the + derivation). For instance, the <envar>PATH</envar> variable is + empty<footnote><para>Actually, it's initialised to + <filename>/path-not-set</filename> to prevent Bash from setting it + to a default value.</para></footnote>. This is done to prevent + undeclared inputs from being used in the build process. If for + example the <envar>PATH</envar> 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 + <envar>stdenv</envar> 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> + + </callout> + + <callout arearefs='ex-hello-builder-co-2'> + + <para>Since Hello needs Perl, we have to make sure that Perl is in + the <envar>PATH</envar>. The <envar>perl</envar> environment + variable points to the location of the Perl package (since it + was passed in as an attribute to the derivation), so + <filename><replaceable>$perl</replaceable>/bin</filename> is the + directory containing the Perl interpreter.</para> + + </callout> + + <callout arearefs='ex-hello-builder-co-3'> + + <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 + <envar>src</envar> 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> + + </callout> + + <callout arearefs='ex-hello-builder-co-4'> + + <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 + <envar>out</envar> 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> + + </callout> + + <callout arearefs='ex-hello-builder-co-5'> + + <para>Finally we build Hello (<literal>make</literal>) and install + it into the location specified by <envar>out</envar> + (<literal>make install</literal>).</para> + + </callout> + +</calloutlist> + +<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> \ No newline at end of file diff --git a/doc/manual/expressions/builder-syntax.xml b/doc/manual/expressions/builder-syntax.xml new file mode 100644 index 000000000000..e51bade44e59 --- /dev/null +++ b/doc/manual/expressions/builder-syntax.xml @@ -0,0 +1,119 @@ +<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-builder-syntax'> + +<title>Builder Syntax</title> + +<example xml:id='ex-hello-builder'><title>Build script for GNU Hello +(<filename>builder.sh</filename>)</title> +<programlisting> +source $stdenv/setup <co xml:id='ex-hello-builder-co-1' /> + +PATH=$perl/bin:$PATH <co xml:id='ex-hello-builder-co-2' /> + +tar xvfz $src <co xml:id='ex-hello-builder-co-3' /> +cd hello-* +./configure --prefix=$out <co xml:id='ex-hello-builder-co-4' /> +make <co xml:id='ex-hello-builder-co-5' /> +make install</programlisting> +</example> + +<para><xref linkend='ex-hello-builder' /> shows the builder referenced +from Hello's Nix expression (stored in +<filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>). +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> + +<calloutlist> + + <callout arearefs='ex-hello-builder-co-1'> + + <para>When Nix runs a builder, it initially completely clears the + environment (except for the attributes declared in the + derivation). For instance, the <envar>PATH</envar> variable is + empty<footnote><para>Actually, it's initialised to + <filename>/path-not-set</filename> to prevent Bash from setting it + to a default value.</para></footnote>. This is done to prevent + undeclared inputs from being used in the build process. If for + example the <envar>PATH</envar> 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 + <envar>stdenv</envar> 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> + + </callout> + + <callout arearefs='ex-hello-builder-co-2'> + + <para>Since Hello needs Perl, we have to make sure that Perl is in + the <envar>PATH</envar>. The <envar>perl</envar> environment + variable points to the location of the Perl package (since it + was passed in as an attribute to the derivation), so + <filename><replaceable>$perl</replaceable>/bin</filename> is the + directory containing the Perl interpreter.</para> + + </callout> + + <callout arearefs='ex-hello-builder-co-3'> + + <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 + <envar>src</envar> 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> + + </callout> + + <callout arearefs='ex-hello-builder-co-4'> + + <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 + <envar>out</envar> 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> + + </callout> + + <callout arearefs='ex-hello-builder-co-5'> + + <para>Finally we build Hello (<literal>make</literal>) and install + it into the location specified by <envar>out</envar> + (<literal>make install</literal>).</para> + + </callout> + +</calloutlist> + +<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> \ No newline at end of file diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml new file mode 100644 index 000000000000..8a18b71008cb --- /dev/null +++ b/doc/manual/expressions/builtins.xml @@ -0,0 +1,1196 @@ +<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='ssec-builtins'> + +<title>Built-in Functions</title> + +<para>This section lists the functions and constants built into the +Nix expression evaluator. (The built-in function +<function>derivation</function> is discussed above.) Some built-ins, +such as <function>derivation</function>, are always in scope of every +Nix expression; you can just access them right away. But to prevent +polluting the namespace too much, most built-ins are not in scope. +Instead, you can access them through the <varname>builtins</varname> +built-in value, which is a set that contains all built-in functions +and values. For instance, <function>derivation</function> is also +available as <function>builtins.derivation</function>.</para> + + +<variablelist> + + + <varlistentry><term><function>abort</function> <replaceable>s</replaceable></term> + + <listitem><para>Abort Nix expression evaluation, print error + message <replaceable>s</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.add</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Return the sum of the numbers + <replaceable>e1</replaceable> and + <replaceable>e2</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.all</function> + <replaceable>pred</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Return <literal>true</literal> if the function + <replaceable>pred</replaceable> returns <literal>true</literal> + for all elements of <replaceable>list</replaceable>, + and <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.any</function> + <replaceable>pred</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Return <literal>true</literal> if the function + <replaceable>pred</replaceable> returns <literal>true</literal> + for at least one element of <replaceable>list</replaceable>, + and <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.attrNames</function> + <replaceable>set</replaceable></term> + + <listitem><para>Return the names of the attributes in the set + <replaceable>set</replaceable> in a sorted list. For instance, + <literal>builtins.attrNames { y = 1; x = "foo"; }</literal> + evaluates to <literal>[ "x" "y" ]</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.attrValues</function> + <replaceable>set</replaceable></term> + + <listitem><para>Return the values of the attributes in the set + <replaceable>set</replaceable> in the order corresponding to the + sorted attribute names.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>baseNameOf</function> <replaceable>s</replaceable></term> + + <listitem><para>Return the <emphasis>base name</emphasis> of the + string <replaceable>s</replaceable>, that is, everything following + the final slash in the string. This is similar to the GNU + <command>basename</command> command.</para></listitem> + + </varlistentry> + + + <varlistentry><term><varname>builtins</varname></term> + + <listitem><para>The set <varname>builtins</varname> contains all + the built-in functions and values. You can use + <varname>builtins</varname> to test for the availability of + features in the Nix installation, e.g., + +<programlisting> +if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting> + + This allows a Nix expression to fall back gracefully on older Nix + installations that don’t have the desired built-in + function.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.compareVersions</function> + <replaceable>s1</replaceable> <replaceable>s2</replaceable></term> + + <listitem><para>Compare two strings representing versions and + return <literal>-1</literal> if version + <replaceable>s1</replaceable> is older than version + <replaceable>s2</replaceable>, <literal>0</literal> if they are + the same, and <literal>1</literal> if + <replaceable>s1</replaceable> is newer than + <replaceable>s2</replaceable>. The version comparison algorithm + is the same as the one used by <link + linkend="ssec-version-comparisons"><command>nix-env + -u</command></link>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.concatLists</function> + <replaceable>lists</replaceable></term> + + <listitem><para>Concatenate a list of lists into a single + list.</para></listitem> + + </varlistentry> + + + <varlistentry + xml:id='builtin-currentSystem'><term><varname>builtins.currentSystem</varname></term> + + <listitem><para>The built-in value <varname>currentSystem</varname> + evaluates to the Nix platform identifier for the Nix installation + on which the expression is being evaluated, such as + <literal>"i686-linux"</literal> or + <literal>"x86_64-darwin"</literal>.</para></listitem> + + </varlistentry> + + + <!-- + <varlistentry><term><function>currentTime</function></term> + + <listitem><para>The built-in value <varname>currentTime</varname> + returns the current system time in seconds since 00:00:00 1/1/1970 + UTC. Due to the evaluation model of Nix expressions + (<emphasis>maximal laziness</emphasis>), it always yields the same + value within an execution of Nix.</para></listitem> + + </varlistentry> + --> + + + <!-- + <varlistentry><term><function>dependencyClosure</function></term> + + <listitem><para>TODO</para></listitem> + + </varlistentry> + --> + + + <varlistentry><term><function>builtins.deepSeq</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>This is like <literal>seq + <replaceable>e1</replaceable> + <replaceable>e2</replaceable></literal>, except that + <replaceable>e1</replaceable> is evaluated + <emphasis>deeply</emphasis>: if it’s a list or set, its elements + or attributes are also evaluated recursively.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>derivation</function> + <replaceable>attrs</replaceable></term> + + <listitem><para><function>derivation</function> is described in + <xref linkend='ssec-derivation' />.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>dirOf</function> <replaceable>s</replaceable></term> + + <listitem><para>Return the directory part of the string + <replaceable>s</replaceable>, that is, everything before the final + slash in the string. This is similar to the GNU + <command>dirname</command> command.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.div</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Return the quotient of the numbers + <replaceable>e1</replaceable> and + <replaceable>e2</replaceable>.</para></listitem> + + </varlistentry> + + <varlistentry><term><function>builtins.match</function> + <replaceable>regex</replaceable> <replaceable>str</replaceable></term> + + <listitem><para>Returns a list if + <replaceable>regex</replaceable> matches + <replaceable>str</replaceable> precisely, otherwise returns <literal>null</literal>. + Each item in the list is a regex group. + +<programlisting> +builtins.match "ab" "abc" +</programlisting> + +Evaluates to <literal>null</literal>. + +<programlisting> +builtins.match "abc" "abc" +</programlisting> + +Evaluates to <literal>[ ]</literal>. + +<programlisting> +builtins.match "a(b)(c)" "abc" +</programlisting> + +Evaluates to <literal>[ "b" "c" ]</literal>. + + + </para></listitem> + </varlistentry> + + <varlistentry><term><function>builtins.elem</function> + <replaceable>x</replaceable> <replaceable>xs</replaceable></term> + + <listitem><para>Return <literal>true</literal> if a value equal to + <replaceable>x</replaceable> occurs in the list + <replaceable>xs</replaceable>, and <literal>false</literal> + otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.elemAt</function> + <replaceable>xs</replaceable> <replaceable>n</replaceable></term> + + <listitem><para>Return element <replaceable>n</replaceable> from + the list <replaceable>xs</replaceable>. Elements are counted + starting from 0. A fatal error occurs in the index is out of + bounds.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.fetchurl</function> + <replaceable>url</replaceable></term> + + <listitem><para>Download the specified URL and return the path of + the downloaded file. This function is not available if <link + linkend="conf-restrict-eval">restricted evaluation mode</link> is + enabled.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>fetchTarball</function> + <replaceable>url</replaceable></term> + + <listitem><para>Download the specified URL, unpack it and return + the path of the unpacked tree. The file must be a tape archive + (<filename>.tar</filename>) compressed with + <literal>gzip</literal>, <literal>bzip2</literal> or + <literal>xz</literal>. The top-level path component of the files + in the tarball is removed, so it is best if the tarball contains a + single directory at top level. The typical use of the function is + to obtain external Nix expression dependencies, such as a + particular version of Nixpkgs, e.g. + +<programlisting> +with import (fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz) {}; + +stdenv.mkDerivation { … } +</programlisting> + + </para> + + <para>This function is not available if <link + linkend="conf-restrict-eval">restricted evaluation mode</link> is + enabled.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.filter</function> + <replaceable>f</replaceable> <replaceable>xs</replaceable></term> + + <listitem><para>Return a list consisting of the elements of + <replaceable>xs</replaceable> for which the function + <replaceable>f</replaceable> returns + <literal>true</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.filterSource</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem> + + <para>This function allows you to copy sources into the Nix + store while filtering certain files. For instance, suppose that + you want to use the directory <filename>source-dir</filename> as + an input to a Nix expression, e.g. + +<programlisting> +stdenv.mkDerivation { + ... + src = ./source-dir; +} +</programlisting> + + However, if <filename>source-dir</filename> is a Subversion + working copy, then all those annoying <filename>.svn</filename> + subdirectories will also be copied to the store. Worse, the + contents of those directories may change a lot, causing lots of + spurious rebuilds. With <function>filterSource</function> you + can filter out the <filename>.svn</filename> directories: + +<programlisting> + src = builtins.filterSource + (path: type: type != "directory" || baseNameOf path != ".svn") + ./source-dir; +</programlisting> + + </para> + + <para>Thus, the first argument <replaceable>e1</replaceable> + must be a predicate function that is called for each regular + file, directory or symlink in the source tree + <replaceable>e2</replaceable>. If the function returns + <literal>true</literal>, the file is copied to the Nix store, + otherwise it is omitted. The function is called with two + arguments. The first is the full path of the file. The second + is a string that identifies the type of the file, which is + either <literal>"regular"</literal>, + <literal>"directory"</literal>, <literal>"symlink"</literal> or + <literal>"unknown"</literal> (for other kinds of files such as + device nodes or fifos — but note that those cannot be copied to + the Nix store, so if the predicate returns + <literal>true</literal> for them, the copy will fail).</para> + + </listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.foldl’</function> + <replaceable>op</replaceable> <replaceable>nul</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Reduce a list by applying a binary operator, from + left to right, e.g. <literal>foldl’ op nul [x0 x1 x2 ...] = op (op + (op nul x0) x1) x2) ...</literal>. The operator is applied + strictly, i.e., its arguments are evaluated first. For example, + <literal>foldl’ (x: y: x + y) 0 [1 2 3]</literal> evaluates to + 6.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.functionArgs</function> + <replaceable>f</replaceable></term> + + <listitem><para> + Return a set containing the names of the formal arguments expected + by the function <replaceable>f</replaceable>. + The value of each attribute is a Boolean denoting whether the corresponding + argument has a default value. For instance, + <literal>functionArgs ({ x, y ? 123}: ...) = { x = false; y = true; }</literal>. + </para> + + <para>"Formal argument" here refers to the attributes pattern-matched by + the function. Plain lambdas are not included, e.g. + <literal>functionArgs (x: ...) = { }</literal>. + </para></listitem> + </varlistentry> + + + <varlistentry><term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term> + + <listitem><para>Convert a JSON string to a Nix + value. For example, + +<programlisting> +builtins.fromJSON ''{"x": [1, 2, 3], "y": null}'' +</programlisting> + + returns the value <literal>{ x = [ 1 2 3 ]; y = null; + }</literal>. Floating point numbers are not + supported.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.genList</function> + <replaceable>generator</replaceable> <replaceable>length</replaceable></term> + + <listitem><para>Generate list of size + <replaceable>length</replaceable>, with each element + <replaceable>i></replaceable> equal to the value returned by + <replaceable>generator</replaceable> <literal>i</literal>. For + example, + +<programlisting> +builtins.genList (x: x * x) 5 +</programlisting> + + returns the list <literal>[ 0 1 4 9 16 ]</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.getAttr</function> + <replaceable>s</replaceable> <replaceable>set</replaceable></term> + + <listitem><para><function>getAttr</function> returns the attribute + named <replaceable>s</replaceable> from + <replaceable>set</replaceable>. Evaluation aborts if the + attribute doesn’t exist. This is a dynamic version of the + <literal>.</literal> operator, since <replaceable>s</replaceable> + is an expression rather than an identifier.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.getEnv</function> + <replaceable>s</replaceable></term> + + <listitem><para><function>getEnv</function> returns the value of + the environment variable <replaceable>s</replaceable>, or an empty + string if the variable doesn’t exist. This function should be + used with care, as it can introduce all sorts of nasty environment + dependencies in your Nix expression.</para> + + <para><function>getEnv</function> is used in Nix Packages to + locate the file <filename>~/.nixpkgs/config.nix</filename>, which + contains user-local settings for Nix Packages. (That is, it does + a <literal>getEnv "HOME"</literal> to locate the user’s home + directory.)</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.hasAttr</function> + <replaceable>s</replaceable> <replaceable>set</replaceable></term> + + <listitem><para><function>hasAttr</function> returns + <literal>true</literal> if <replaceable>set</replaceable> has an + attribute named <replaceable>s</replaceable>, and + <literal>false</literal> otherwise. This is a dynamic version of + the <literal>?</literal> operator, since + <replaceable>s</replaceable> is an expression rather than an + identifier.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.hashString</function> + <replaceable>type</replaceable> <replaceable>s</replaceable></term> + + <listitem><para>Return a base-16 representation of the + cryptographic hash of string <replaceable>s</replaceable>. The + hash algorithm specified by <replaceable>type</replaceable> must + be one of <literal>"md5"</literal>, <literal>"sha1"</literal> or + <literal>"sha256"</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.head</function> + <replaceable>list</replaceable></term> + + <listitem><para>Return the first element of a list; abort + evaluation if the argument isn’t a list or is an empty list. You + can test whether a list is empty by comparing it with + <literal>[]</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>import</function> + <replaceable>path</replaceable></term> + + <listitem><para>Load, parse and return the Nix expression in the + file <replaceable>path</replaceable>. If <replaceable>path + </replaceable> is a directory, the file <filename>default.nix + </filename> in that directory is loaded. Evaluation aborts if the + file doesn’t exist or contains an incorrect Nix expression. + <function>import</function> implements Nix’s module system: you + can put any Nix expression (such as a set or a function) in a + separate file, and use it from Nix expressions in other + files.</para> + + <para>A Nix expression loaded by <function>import</function> must + not contain any <emphasis>free variables</emphasis> (identifiers + that are not defined in the Nix expression itself and are not + built-in). Therefore, it cannot refer to variables that are in + scope at the call site. For instance, if you have a calling + expression + +<programlisting> +rec { + x = 123; + y = import ./foo.nix; +}</programlisting> + + then the following <filename>foo.nix</filename> will give an + error: + +<programlisting> +x + 456</programlisting> + + since <varname>x</varname> is not in scope in + <filename>foo.nix</filename>. If you want <varname>x</varname> + to be available in <filename>foo.nix</filename>, you should pass + it as a function argument: + +<programlisting> +rec { + x = 123; + y = import ./foo.nix x; +}</programlisting> + + and + +<programlisting> +x: x + 456</programlisting> + + (The function argument doesn’t have to be called + <varname>x</varname> in <filename>foo.nix</filename>; any name + would work.)</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.intersectAttrs</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Return a set consisting of the attributes in the + set <replaceable>e2</replaceable> that also exist in the set + <replaceable>e1</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.isAttrs</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to a set, and + <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.isList</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to a list, and + <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.isFunction</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to a function, and + <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.isString</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to a string, and + <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.isInt</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to an int, and + <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.isBool</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to a bool, and + <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>isNull</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return <literal>true</literal> if + <replaceable>e</replaceable> evaluates to <literal>null</literal>, + and <literal>false</literal> otherwise.</para> + + <warning><para>This function is <emphasis>deprecated</emphasis>; + just write <literal>e == null</literal> instead.</para></warning> + + </listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.length</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return the length of the list + <replaceable>e</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.lessThan</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Return <literal>true</literal> if the number + <replaceable>e1</replaceable> is less than the number + <replaceable>e2</replaceable>, and <literal>false</literal> + otherwise. Evaluation aborts if either + <replaceable>e1</replaceable> or <replaceable>e2</replaceable> + does not evaluate to a number.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.listToAttrs</function> + <replaceable>e</replaceable></term> + + <listitem><para>Construct a set from a list specifying the names + and values of each attribute. Each element of the list should be + a set consisting of a string-valued attribute + <varname>name</varname> specifying the name of the attribute, and + an attribute <varname>value</varname> specifying its value. + Example: + +<programlisting> +builtins.listToAttrs + [ { name = "foo"; value = 123; } + { name = "bar"; value = 456; } + ] +</programlisting> + + evaluates to + +<programlisting> +{ foo = 123; bar = 456; } +</programlisting> + + </para></listitem> + + </varlistentry> + + <varlistentry><term><function>map</function> + <replaceable>f</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Apply the function <replaceable>f</replaceable> to + each element in the list <replaceable>list</replaceable>. For + example, + +<programlisting> +map (x: "foo" + x) [ "bar" "bla" "abc" ]</programlisting> + + evaluates to <literal>[ "foobar" "foobla" "fooabc" + ]</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.mul</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Return the product of the numbers + <replaceable>e1</replaceable> and + <replaceable>e2</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.parseDrvName</function> + <replaceable>s</replaceable></term> + + <listitem><para>Split the string <replaceable>s</replaceable> into + a package name and version. The package name is everything up to + but not including the first dash followed by a digit, and the + version is everything following that dash. The result is returned + in a set <literal>{ name, version }</literal>. Thus, + <literal>builtins.parseDrvName "nix-0.12pre12876"</literal> + returns <literal>{ name = "nix"; version = "0.12pre12876"; + }</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.pathExists</function> + <replaceable>path</replaceable></term> + + <listitem><para>Return <literal>true</literal> if the path + <replaceable>path</replaceable> exists, and + <literal>false</literal> otherwise. One application of this + function is to conditionally include a Nix expression containing + user configuration: + +<programlisting> +let + fileName = builtins.getEnv "CONFIG_FILE"; + config = + if fileName != "" && builtins.pathExists (builtins.toPath fileName) + then import (builtins.toPath fileName) + else { someSetting = false; }; <lineannotation># default configuration</lineannotation> +in config.someSetting</programlisting> + + (Note that <envar>CONFIG_FILE</envar> must be an absolute path for + this to work.)</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.readDir</function> + <replaceable>path</replaceable></term> + + <listitem><para>Return the contents of the directory + <replaceable>path</replaceable> as a set mapping directory entries + to the corresponding file type. For instance, if directory + <filename>A</filename> contains a regular file + <filename>B</filename> and another directory + <filename>C</filename>, then <literal>builtins.readDir + ./A</literal> will return the set + +<programlisting> +{ B = "regular"; C = "directory"; }</programlisting> + + The possible values for the file type are + <literal>"regular"</literal>, <literal>"directory"</literal>, + <literal>"symlink"</literal> and + <literal>"unknown"</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.readFile</function> + <replaceable>path</replaceable></term> + + <listitem><para>Return the contents of the file + <replaceable>path</replaceable> as a string.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>removeAttrs</function> + <replaceable>set</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Remove the attributes listed in + <replaceable>list</replaceable> from + <replaceable>set</replaceable>. The attributes don’t have to + exist in <replaceable>set</replaceable>. For instance, + +<programlisting> +removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</programlisting> + + evaluates to <literal>{ y = 2; }</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.replaceStrings</function> + <replaceable>from</replaceable> <replaceable>to</replaceable> <replaceable>s</replaceable></term> + + <listitem><para>Given string <replaceable>s</replaceable>, replace + every occurrence of the strings in <replaceable>from</replaceable> + with the corresponding string in + <replaceable>to</replaceable>. For example, + +<programlisting> +builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar" +</programlisting> + + evaluates to <literal>"fabir"</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.seq</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Evaluate <replaceable>e1</replaceable>, then + evaluate and return <replaceable>e2</replaceable>. This ensures + that a computation is strict in the value of + <replaceable>e1</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.sort</function> + <replaceable>comparator</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Return <replaceable>list</replaceable> in sorted + order. It repeatedly calls the function + <replaceable>comparator</replaceable> with two elements. The + comparator should return <literal>true</literal> if the first + element is less than the second, and <literal>false</literal> + otherwise. For example, + +<programlisting> +builtins.sort builtins.lessThan [ 483 249 526 147 42 77 ] +</programlisting> + + produces the list <literal>[ 42 77 147 249 483 526 + ]</literal>.</para> + + <para>This is a stable sort: it preserves the relative order of + elements deemed equal by the comparator.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.stringLength</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return the length of the string + <replaceable>e</replaceable>. If <replaceable>e</replaceable> is + not a string, evaluation is aborted.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.sub</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Return the difference between the numbers + <replaceable>e1</replaceable> and + <replaceable>e2</replaceable>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.substring</function> + <replaceable>start</replaceable> <replaceable>len</replaceable> + <replaceable>s</replaceable></term> + + <listitem><para>Return the substring of + <replaceable>s</replaceable> from character position + <replaceable>start</replaceable> (zero-based) up to but not + including <replaceable>start + len</replaceable>. If + <replaceable>start</replaceable> is greater than the length of the + string, an empty string is returned, and if <replaceable>start + + len</replaceable> lies beyond the end of the string, only the + substring up to the end of the string is returned. + <replaceable>start</replaceable> must be + non-negative. For example, + +<programlisting> +builtins.substring 0 3 "nixos" +</programlisting> + + evaluates to <literal>"nix"</literal>. + </para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.tail</function> + <replaceable>list</replaceable></term> + + <listitem><para>Return the second to last elements of a list; + abort evaluation if the argument isn’t a list or is an empty + list.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>throw</function> + <replaceable>s</replaceable></term> + + <listitem><para>Throw an error message + <replaceable>s</replaceable>. This usually aborts Nix expression + evaluation, but in <command>nix-env -qa</command> and other + commands that try to evaluate a set of derivations to get + information about those derivations, a derivation that throws an + error is silently skipped (which is not the case for + <function>abort</function>).</para></listitem> + + </varlistentry> + + + <varlistentry + xml:id='builtin-toFile'><term><function>builtins.toFile</function> + <replaceable>name</replaceable> <replaceable>s</replaceable></term> + + <listitem><para>Store the string <replaceable>s</replaceable> in a + file in the Nix store and return its path. The file has suffix + <replaceable>name</replaceable>. This file can be used as an + input to derivations. One application is to write builders + “inline”. For instance, the following Nix expression combines + <xref linkend='ex-hello-nix' /> and <xref + linkend='ex-hello-builder' /> into one file: + +<programlisting> +{ stdenv, fetchurl, perl }: + +stdenv.mkDerivation { + name = "hello-2.1.1"; + + builder = builtins.toFile "builder.sh" " + source $stdenv/setup + + PATH=$perl/bin:$PATH + + tar xvfz $src + cd hello-* + ./configure --prefix=$out + make + make install + "; + + src = fetchurl { + url = http://nix.cs.uu.nl/dist/tarballs/hello-2.1.1.tar.gz; + md5 = "70c9ccf9fac07f762c24f2df2290784d"; + }; + inherit perl; +}</programlisting> + + </para> + + <para>It is even possible for one file to refer to another, e.g., + +<programlisting> + builder = let + configFile = builtins.toFile "foo.conf" " + # This is some dummy configuration file. + <replaceable>...</replaceable> + "; + in builtins.toFile "builder.sh" " + source $stdenv/setup + <replaceable>...</replaceable> + cp ${configFile} $out/etc/foo.conf + ";</programlisting> + + Note that <literal>${configFile}</literal> is an antiquotation + (see <xref linkend='ssec-values' />), so the result of the + expression <literal>configFile</literal> (i.e., a path like + <filename>/nix/store/m7p7jfny445k...-foo.conf</filename>) will be + spliced into the resulting string.</para> + + <para>It is however <emphasis>not</emphasis> allowed to have files + mutually referring to each other, like so: + +<programlisting> +let + foo = builtins.toFile "foo" "...${bar}..."; + bar = builtins.toFile "bar" "...${foo}..."; +in foo</programlisting> + + This is not allowed because it would cause a cyclic dependency in + the computation of the cryptographic hashes for + <varname>foo</varname> and <varname>bar</varname>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.toJSON</function> <replaceable>e</replaceable></term> + + <listitem><para>Return a string containing a JSON representation + of <replaceable>e</replaceable>. Strings, integers, floats, booleans, + nulls and lists are mapped to their JSON equivalents. Sets + (except derivations) are represented as objects. Derivations are + translated to a JSON string containing the derivation’s output + path. Paths are copied to the store and represented as a JSON + string of the resulting store path.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.toPath</function> <replaceable>s</replaceable></term> + + <listitem><para>Convert the string value + <replaceable>s</replaceable> into a path value. The string + <replaceable>s</replaceable> must represent an absolute path + (i.e., must start with <literal>/</literal>). The path need not + exist. The resulting path is canonicalised, e.g., + <literal>builtins.toPath "//foo/xyzzy/../bar/"</literal> returns + <literal>/foo/bar</literal>.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>toString</function> <replaceable>e</replaceable></term> + + <listitem><para>Convert the expression + <replaceable>e</replaceable> to a string. + <replaceable>e</replaceable> can be:</para> + <itemizedlist> + <listitem><para>A string (in which case the string is returned unmodified).</para></listitem> + <listitem><para>A path (e.g., <literal>toString /foo/bar</literal> yields <literal>"/foo/bar"</literal>.</para></listitem> + <listitem><para>A set containing <literal>{ __toString = self: ...; }</literal>.</para></listitem> + <listitem><para>An integer.</para></listitem> + <listitem><para>A list, in which case the string representations of its elements are joined with spaces.</para></listitem> + <listitem><para>A Boolean (<literal>false</literal> yields <literal>""</literal>, <literal>true</literal> yields <literal>"1"</literal>.</para></listitem> + <listitem><para><literal>null</literal>, which yields the empty string.</para></listitem> + </itemizedlist> + </listitem> + + </varlistentry> + + + <varlistentry xml:id='builtin-toXML'><term><function>builtins.toXML</function> <replaceable>e</replaceable></term> + + <listitem><para>Return a string containing an XML representation + of <replaceable>e</replaceable>. The main application for + <function>toXML</function> is to communicate information with the + builder in a more structured format than plain environment + variables.</para> + + <!-- TODO: more formally describe the schema of the XML + representation --> + + <para><xref linkend='ex-toxml' /> shows an example where this is + the case. The builder is supposed to generate the configuration + file for a <link xlink:href='http://jetty.mortbay.org/'>Jetty + servlet container</link>. A servlet container contains a number + of servlets (<filename>*.war</filename> files) each exported under + a specific URI prefix. So the servlet configuration is a list of + sets containing the <varname>path</varname> and + <varname>war</varname> of the servlet (<xref + linkend='ex-toxml-co-servlets' />). This kind of information is + difficult to communicate with the normal method of passing + information through an environment variable, which just + concatenates everything together into a string (which might just + work in this case, but wouldn’t work if fields are optional or + contain lists themselves). Instead the Nix expression is + converted to an XML representation with + <function>toXML</function>, which is unambiguous and can easily be + processed with the appropriate tools. For instance, in the + example an XSLT stylesheet (<xref linkend='ex-toxml-co-stylesheet' + />) is applied to it (<xref linkend='ex-toxml-co-apply' />) to + generate the XML configuration file for the Jetty server. The XML + representation produced from <xref linkend='ex-toxml-co-servlets' + /> by <function>toXML</function> is shown in <xref + linkend='ex-toxml-result' />.</para> + + <para>Note that <xref linkend='ex-toxml' /> uses the <function + linkend='builtin-toFile'>toFile</function> built-in to write the + builder and the stylesheet “inline” in the Nix expression. The + path of the stylesheet is spliced into the builder at + <literal>xsltproc ${stylesheet} + <replaceable>...</replaceable></literal>.</para> + + <example xml:id='ex-toxml'><title>Passing information to a builder + using <function>toXML</function></title> + +<programlisting><![CDATA[ +{ stdenv, fetchurl, libxslt, jira, uberwiki }: + +stdenv.mkDerivation (rec { + name = "web-server"; + + buildInputs = [ libxslt ]; + + builder = builtins.toFile "builder.sh" " + source $stdenv/setup + mkdir $out + echo $servlets | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <co xml:id='ex-toxml-co-apply' /> <![CDATA[ + "; + + stylesheet = builtins.toFile "stylesheet.xsl"]]> <co xml:id='ex-toxml-co-stylesheet' /> <![CDATA[ + "<?xml version='1.0' encoding='UTF-8'?> + <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'> + <xsl:template match='/'> + <Configure> + <xsl:for-each select='/expr/list/attrs'> + <Call name='addWebApplication'> + <Arg><xsl:value-of select=\"attr[@name = 'path']/string/@value\" /></Arg> + <Arg><xsl:value-of select=\"attr[@name = 'war']/path/@value\" /></Arg> + </Call> + </xsl:for-each> + </Configure> + </xsl:template> + </xsl:stylesheet> + "; + + servlets = builtins.toXML []]> <co xml:id='ex-toxml-co-servlets' /> <![CDATA[ + { path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; } + { path = "/wiki"; war = uberwiki + "/uberwiki.war"; } + ]; +})]]></programlisting> + + </example> + + <example xml:id='ex-toxml-result'><title>XML representation produced by + <function>toXML</function></title> + +<programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?> +<expr> + <list> + <attrs> + <attr name="path"> + <string value="/bugtracker" /> + </attr> + <attr name="war"> + <path value="/nix/store/d1jh9pasa7k2...-jira/lib/atlassian-jira.war" /> + </attr> + </attrs> + <attrs> + <attr name="path"> + <string value="/wiki" /> + </attr> + <attr name="war"> + <path value="/nix/store/y6423b1yi4sx...-uberwiki/uberwiki.war" /> + </attr> + </attrs> + </list> +</expr>]]></programlisting> + + </example> + + </listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.trace</function> + <replaceable>e1</replaceable> <replaceable>e2</replaceable></term> + + <listitem><para>Evaluate <replaceable>e1</replaceable> and print its + abstract syntax representation on standard error. Then return + <replaceable>e2</replaceable>. This function is useful for + debugging.</para></listitem> + + </varlistentry> + + <varlistentry><term><function>builtins.tryEval</function> + <replaceable>e</replaceable></term> + + <listitem><para>Try to evaluate <replaceable>e</replaceable>. + Return a set containing the attributes <literal>success</literal> + (<literal>true</literal> if <replaceable>e</replaceable> evaluated + successfully, <literal>false</literal> if an error was thrown) and + <literal>value</literal>, equalling <replaceable>e</replaceable> + if successful and <literal>false</literal> otherwise. + </para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.typeOf</function> + <replaceable>e</replaceable></term> + + <listitem><para>Return a string representing the type of the value + <replaceable>e</replaceable>, namely <literal>"int"</literal>, + <literal>"bool"</literal>, <literal>"string"</literal>, + <literal>"path"</literal>, <literal>"null"</literal>, + <literal>"set"</literal>, <literal>"list"</literal> or + <literal>"lambda"</literal>.</para></listitem> + + </varlistentry> + + +</variablelist> + + +</section> diff --git a/doc/manual/expressions/debug-build.xml b/doc/manual/expressions/debug-build.xml new file mode 100644 index 000000000000..0c1f4e6719b2 --- /dev/null +++ b/doc/manual/expressions/debug-build.xml @@ -0,0 +1,34 @@ +<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-debug-build"> + +<title>Debugging Build Failures</title> + +<para>At the beginning of each phase of the build (such as unpacking, +building or installing), the set of all shell variables is written to +the file <filename>env-vars</filename> at the top-level build +directory. This is useful for debugging: it allows you to recreate +the environment in which a build was performed. For instance, if a +build fails, then assuming you used the <option>-K</option> flag, you +can go to the output directory and <quote>switch</quote> to the +environment of the builder: + +<screen> +$ nix-build -K ./foo.nix +... fails, keeping build directory `/tmp/nix-1234-0' + +$ cd /tmp/nix-1234-0 + +$ source env-vars + +<lineannotation>(edit some files...)</lineannotation> + +$ make + +<lineannotation>(execution continues with the same GCC, make, etc.)</lineannotation></screen> + +</para> + +</section> diff --git a/doc/manual/expressions/derivations.xml b/doc/manual/expressions/derivations.xml new file mode 100644 index 000000000000..5efe2213e370 --- /dev/null +++ b/doc/manual/expressions/derivations.xml @@ -0,0 +1,211 @@ +<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="ssec-derivation"> + +<title>Derivations</title> + +<para>The most important built-in function is +<function>derivation</function>, which is used to describe a single +derivation (a build action). It takes as input a set, the attributes +of which specify the inputs of the build.</para> + +<itemizedlist> + + <listitem xml:id="attr-system"><para>There must be an attribute named + <varname>system</varname> whose value must be a string specifying a + Nix platform identifier, such as <literal>"i686-linux"</literal> or + <literal>"x86_64-darwin"</literal><footnote><para>To figure out + your platform identifier, look at the line <quote>Checking for the + canonical Nix system name</quote> in the output of Nix's + <filename>configure</filename> script.</para></footnote> The build + can only be performed on a machine and operating system matching the + platform identifier. (Nix can automatically forward builds for + other platforms by forwarding them to other machines; see <xref + linkend='chap-distributed-builds' />.)</para></listitem> + + <listitem><para>There must be an attribute named + <varname>name</varname> whose value must be a string. This is used + as a symbolic name for the package by <command>nix-env</command>, + and it is appended to the output paths of the + derivation.</para></listitem> + + <listitem><para>There must be an attribute named + <varname>builder</varname> that identifies the program that is + executed to perform the build. It can be either a derivation or a + source (a local file reference, e.g., + <filename>./builder.sh</filename>).</para></listitem> + + <listitem><para>Every attribute is passed as an environment variable + to the builder. Attribute values are translated to environment + variables as follows: + + <itemizedlist> + + <listitem><para>Strings and numbers are just passed + verbatim.</para></listitem> + + <listitem><para>A <emphasis>path</emphasis> (e.g., + <filename>../foo/sources.tar</filename>) causes the referenced + file to be copied to the store; its location in the store is put + in the environment variable. The idea is that all sources + should reside in the Nix store, since all inputs to a derivation + should reside in the Nix store.</para></listitem> + + <listitem><para>A <emphasis>derivation</emphasis> causes that + derivation to be built prior to the present derivation; its + default output path is put in the environment + variable.</para></listitem> + + <listitem><para>Lists of the previous types are also allowed. + They are simply concatenated, separated by + spaces.</para></listitem> + + <listitem><para><literal>true</literal> is passed as the string + <literal>1</literal>, <literal>false</literal> and + <literal>null</literal> are passed as an empty string. + </para></listitem> + </itemizedlist> + + </para></listitem> + + <listitem><para>The optional attribute <varname>args</varname> + specifies command-line arguments to be passed to the builder. It + should be a list.</para></listitem> + + <listitem><para>The optional attribute <varname>outputs</varname> + specifies a list of symbolic outputs of the derivation. By default, + a derivation produces a single output path, denoted as + <literal>out</literal>. However, derivations can produce multiple + output paths. This is useful because it allows outputs to be + downloaded or garbage-collected separately. For instance, imagine a + library package that provides a dynamic library, header files, and + documentation. A program that links against the library doesn’t + need the header files and documentation at runtime, and it doesn’t + need the documentation at build time. Thus, the library package + could specify: +<programlisting> +outputs = [ "lib" "headers" "doc" ]; +</programlisting> + This will cause Nix to pass environment variables + <literal>lib</literal>, <literal>headers</literal> and + <literal>doc</literal> to the builder containing the intended store + paths of each output. The builder would typically do something like +<programlisting> +./configure --libdir=$lib/lib --includedir=$headers/include --docdir=$doc/share/doc +</programlisting> + for an Autoconf-style package. You can refer to each output of a + derivation by selecting it as an attribute, e.g. +<programlisting> +buildInputs = [ pkg.lib pkg.headers ]; +</programlisting> + The first element of <varname>output</varname> determines the + <emphasis>default output</emphasis>. Thus, you could also write +<programlisting> +buildInputs = [ pkg pkg.headers ]; +</programlisting> + since <literal>pkg</literal> is equivalent to + <literal>pkg.lib</literal>.</para></listitem> + +</itemizedlist> + +<para>The function <function>mkDerivation</function> in the Nixpkgs +standard environment is a wrapper around +<function>derivation</function> that adds a default value for +<varname>system</varname> and always uses Bash as the builder, to +which the supplied builder is passed as a command-line argument. See +the Nixpkgs manual for details.</para> + +<para>The builder is executed as follows: + +<itemizedlist> + + <listitem><para>A temporary directory is created under the directory + specified by <envar>TMPDIR</envar> (default + <filename>/tmp</filename>) where the build will take place. The + current directory is changed to this directory.</para></listitem> + + <listitem><para>The environment is cleared and set to the derivation + attributes, as specified above.</para></listitem> + + <listitem><para>In addition, the following variables are set: + + <itemizedlist> + + <listitem><para><envar>NIX_BUILD_TOP</envar> contains the path of + the temporary directory for this build.</para></listitem> + + <listitem><para>Also, <envar>TMPDIR</envar>, + <envar>TEMPDIR</envar>, <envar>TMP</envar>, <envar>TEMP</envar> + are set to point to the temporary directory. This is to prevent + the builder from accidentally writing temporary files anywhere + else. Doing so might cause interference by other + processes.</para></listitem> + + <listitem><para><envar>PATH</envar> is set to + <filename>/path-not-set</filename> to prevent shells from + initialising it to their built-in default value.</para></listitem> + + <listitem><para><envar>HOME</envar> is set to + <filename>/homeless-shelter</filename> to prevent programs from + using <filename>/etc/passwd</filename> or the like to find the + user's home directory, which could cause impurity. Usually, when + <envar>HOME</envar> is set, it is used as the location of the home + directory, even if it points to a non-existent + path.</para></listitem> + + <listitem><para><envar>NIX_STORE</envar> is set to the path of the + top-level Nix store directory (typically, + <filename>/nix/store</filename>).</para></listitem> + + <listitem><para>For each output declared in + <varname>outputs</varname>, the corresponding environment variable + is set to point to the intended path in the Nix store for that + output. Each output path is a concatenation of the cryptographic + hash of all build inputs, the <varname>name</varname> attribute + and the output name. (The output name is omitted if it’s + <literal>out</literal>.)</para></listitem> + + </itemizedlist> + + </para></listitem> + + <listitem><para>If an output path already exists, it is removed. + Also, locks are acquired to prevent multiple Nix instances from + performing the same build at the same time.</para></listitem> + + <listitem><para>A log of the combined standard output and error is + written to <filename>/nix/var/log/nix</filename>.</para></listitem> + + <listitem><para>The builder is executed with the arguments specified + by the attribute <varname>args</varname>. If it exits with exit + code 0, it is considered to have succeeded.</para></listitem> + + <listitem><para>The temporary directory is removed (unless the + <option>-K</option> option was specified).</para></listitem> + + <listitem><para>If the build was successful, Nix scans each output + path for references to input paths by looking for the hash parts of + the input paths. Since these are potential runtime dependencies, + Nix registers them as dependencies of the output + paths.</para></listitem> + + <listitem><para>After the build, Nix sets the last-modified + timestamp on all files in the build result to 1 (00:00:01 1/1/1970 + UTC), sets the group to the default group, and sets the mode of the + file to 0444 or 0555 (i.e., read-only, with execute permission + enabled if the file was originally executable). Note that possible + <literal>setuid</literal> and <literal>setgid</literal> bits are + cleared. Setuid and setgid programs are not currently supported by + Nix. This is because the Nix archives used in deployment have no + concept of ownership information, and because it makes the build + result dependent on the user performing the build.</para></listitem> + +</itemizedlist> + +</para> + +<xi:include href="advanced-attributes.xml" /> + +</section> diff --git a/doc/manual/expressions/expression-language.xml b/doc/manual/expressions/expression-language.xml new file mode 100644 index 000000000000..240ef80f1463 --- /dev/null +++ b/doc/manual/expressions/expression-language.xml @@ -0,0 +1,30 @@ +<chapter 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="ch-expression-language"> + +<title>Nix Expression Language</title> + +<para>The Nix expression language is a pure, lazy, functional +language. Purity means that operations in the language don't have +side-effects (for instance, there is no variable assignment). +Laziness means that arguments to functions are evaluated only when +they are needed. Functional means that functions are +<quote>normal</quote> values that can be passed around and manipulated +in interesting ways. The language is not a full-featured, general +purpose language. Its main job is to describe packages, +compositions of packages, and the variability within +packages.</para> + +<para>This section presents the various features of the +language.</para> + +<xi:include href="language-values.xml" /> +<xi:include href="language-constructs.xml" /> +<xi:include href="language-operators.xml" /> +<xi:include href="derivations.xml" /> +<xi:include href="builtins.xml" /> + + +</chapter> diff --git a/doc/manual/expressions/expression-syntax.xml b/doc/manual/expressions/expression-syntax.xml new file mode 100644 index 000000000000..6f1a3a10c4e4 --- /dev/null +++ b/doc/manual/expressions/expression-syntax.xml @@ -0,0 +1,148 @@ +<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-expression-syntax'> + +<title>Expression Syntax</title> + +<example xml:id='ex-hello-nix'><title>Nix expression for GNU Hello +(<filename>default.nix</filename>)</title> +<programlisting> +{ stdenv, fetchurl, perl }: <co xml:id='ex-hello-nix-co-1' /> + +stdenv.mkDerivation { <co xml:id='ex-hello-nix-co-2' /> + name = "hello-2.1.1"; <co xml:id='ex-hello-nix-co-3' /> + builder = ./builder.sh; <co xml:id='ex-hello-nix-co-4' /> + src = fetchurl { <co xml:id='ex-hello-nix-co-5' /> + url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz; + md5 = "70c9ccf9fac07f762c24f2df2290784d"; + }; + inherit perl; <co xml:id='ex-hello-nix-co-6' /> +}</programlisting> +</example> + +<para><xref linkend='ex-hello-nix' /> shows a Nix expression for GNU +Hello. It's actually already in the Nix Packages collection in +<filename>pkgs/applications/misc/hello/ex-1/default.nix</filename>. +It is customary to place each package in a separate directory and call +the single Nix expression in that directory +<filename>default.nix</filename>. The file has the following elements +(referenced from the figure by number): + +<calloutlist> + + <callout arearefs='ex-hello-nix-co-1'> + + <para>This states that the expression is a + <emphasis>function</emphasis> that expects to be called with three + arguments: <varname>stdenv</varname>, <varname>fetchurl</varname>, + and <varname>perl</varname>. They are needed to build Hello, but + we don't know how to build them here; that's why they are function + arguments. <varname>stdenv</varname> is a package that is used + by almost all Nix Packages packages; it provides a + <quote>standard</quote> environment consisting of the things you + would expect in a basic Unix environment: a C/C++ compiler (GCC, + to be precise), the Bash shell, fundamental Unix tools such as + <command>cp</command>, <command>grep</command>, + <command>tar</command>, etc. <varname>fetchurl</varname> is a + function that downloads files. <varname>perl</varname> is the + Perl interpreter.</para> + + <para>Nix functions generally have the form <literal>{ x, y, ..., + z }: e</literal> where <varname>x</varname>, <varname>y</varname>, + etc. are the names of the expected arguments, and where + <replaceable>e</replaceable> is the body of the function. So + here, the entire remainder of the file is the body of the + function; when given the required arguments, the body should + describe how to build an instance of the Hello package.</para> + + </callout> + + <callout arearefs='ex-hello-nix-co-2'> + + <para>So we have to build a package. Building something from + other stuff is called a <emphasis>derivation</emphasis> in Nix (as + opposed to sources, which are built by humans instead of + computers). We perform a derivation by calling + <varname>stdenv.mkDerivation</varname>. + <varname>mkDerivation</varname> is a function provided by + <varname>stdenv</varname> that builds a package from a set of + <emphasis>attributes</emphasis>. A set is just a list of + key/value pairs where each key is a string and each value is an + arbitrary Nix expression. They take the general form <literal>{ + <replaceable>name1</replaceable> = + <replaceable>expr1</replaceable>; <replaceable>...</replaceable> + <replaceable>nameN</replaceable> = + <replaceable>exprN</replaceable>; }</literal>.</para> + + </callout> + + <callout arearefs='ex-hello-nix-co-3'> + + <para>The attribute <varname>name</varname> specifies the symbolic + name and version of the package. Nix doesn't really care about + these things, but they are used by for instance <command>nix-env + -q</command> to show a <quote>human-readable</quote> name for + packages. This attribute is required by + <varname>mkDerivation</varname>.</para> + + </callout> + + <callout arearefs='ex-hello-nix-co-4'> + + <para>The attribute <varname>builder</varname> specifies the + builder. This attribute can sometimes be omitted, in which case + <varname>mkDerivation</varname> will fill in a default builder + (which does a <literal>configure; make; make install</literal>, in + essence). Hello is sufficiently simple that the default builder + would suffice, but in this case, we will show an actual builder + for educational purposes. The value + <command>./builder.sh</command> refers to the shell script shown + in <xref linkend='ex-hello-builder' />, discussed below.</para> + + </callout> + + <callout arearefs='ex-hello-nix-co-5'> + + <para>The builder has to know what the sources of the package + are. Here, the attribute <varname>src</varname> is bound to the + result of a call to the <command>fetchurl</command> function. + Given a URL and an MD5 hash of the expected contents of the file + at that URL, this function builds a derivation that downloads the + file and checks its hash. So the sources are a dependency that + like all other dependencies is built before Hello itself is + built.</para> + + <para>Instead of <varname>src</varname> any other name could have + been used, and in fact there can be any number of sources (bound + to different attributes). However, <varname>src</varname> is + customary, and it's also expected by the default builder (which we + don't use in this example).</para> + + </callout> + + <callout arearefs='ex-hello-nix-co-6'> + + <para>Since the derivation requires Perl, we have to pass the + value of the <varname>perl</varname> function argument to the + builder. All attributes in the set are actually passed as + environment variables to the builder, so declaring an attribute + + <programlisting> +perl = perl;</programlisting> + + will do the trick: it binds an attribute <varname>perl</varname> + to the function argument which also happens to be called + <varname>perl</varname>. However, it looks a bit silly, so there + is a shorter syntax. The <literal>inherit</literal> keyword + causes the specified attributes to be bound to whatever variables + with the same name happen to be in scope.</para> + + </callout> + +</calloutlist> + +</para> + +</section> \ No newline at end of file diff --git a/doc/manual/expressions/generic-builder.xml b/doc/manual/expressions/generic-builder.xml new file mode 100644 index 000000000000..db7ff405d8b1 --- /dev/null +++ b/doc/manual/expressions/generic-builder.xml @@ -0,0 +1,98 @@ +<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-generic-builder'> + +<title>Generic Builder Syntax</title> + +<para>Recall from <xref linkend='ex-hello-builder' /> that the builder +looked something like this: + +<programlisting> +PATH=$perl/bin:$PATH +tar xvfz $src +cd hello-* +./configure --prefix=$out +make +make install</programlisting> + +The builders for almost all Unix packages look like this — set up some +environment variables, unpack the sources, configure, build, and +install. For this reason the standard environment provides some Bash +functions that automate the build process. A builder using the +generic build facilities in shown in <xref linkend='ex-hello-builder2' +/>.</para> + +<example xml:id='ex-hello-builder2'><title>Build script using the generic +build functions</title> +<programlisting> +buildInputs="$perl" <co xml:id='ex-hello-builder2-co-1' /> + +source $stdenv/setup <co xml:id='ex-hello-builder2-co-2' /> + +genericBuild <co xml:id='ex-hello-builder2-co-3' /></programlisting> +</example> + +<calloutlist> + + <callout arearefs='ex-hello-builder2-co-1'> + + <para>The <envar>buildInputs</envar> variable tells + <filename>setup</filename> to use the indicated packages as + <quote>inputs</quote>. This means that if a package provides a + <filename>bin</filename> subdirectory, it's added to + <envar>PATH</envar>; if it has a <filename>include</filename> + subdirectory, it's added to GCC's header search path; and so + on.<footnote><para>How does it work? <filename>setup</filename> + tries to source the file + <filename><replaceable>pkg</replaceable>/nix-support/setup-hook</filename> + of all dependencies. These “setup hooks” can then set up whatever + environment variables they want; for instance, the setup hook for + Perl sets the <envar>PERL5LIB</envar> environment variable to + contain the <filename>lib/site_perl</filename> directories of all + inputs.</para></footnote> + </para> + + </callout> + + <callout arearefs='ex-hello-builder2-co-2'> + + <para>The function <function>genericBuild</function> is defined in + the file <literal>$stdenv/setup</literal>.</para> + + </callout> + + <callout arearefs='ex-hello-builder2-co-3'> + + <para>The final step calls the shell function + <function>genericBuild</function>, which performs the steps that + were done explicitly in <xref linkend='ex-hello-builder' />. The + generic builder is smart enough to figure out whether to unpack + the sources using <command>gzip</command>, + <command>bzip2</command>, etc. It can be customised in many ways; + see the Nixpkgs manual for details.</para> + + </callout> + +</calloutlist> + +<para>Discerning readers will note that the +<envar>buildInputs</envar> could just as well have been set in the Nix +expression, like this: + +<programlisting> + buildInputs = [ perl ];</programlisting> + +The <varname>perl</varname> attribute can then be removed, and the +builder becomes even shorter: + +<programlisting> +source $stdenv/setup +genericBuild</programlisting> + +In fact, <varname>mkDerivation</varname> provides a default builder +that looks exactly like that, so it is actually possible to omit the +builder for Hello entirely.</para> + +</section> diff --git a/doc/manual/expressions/language-constructs.xml b/doc/manual/expressions/language-constructs.xml new file mode 100644 index 000000000000..fe69dba837a1 --- /dev/null +++ b/doc/manual/expressions/language-constructs.xml @@ -0,0 +1,350 @@ +<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-constructs"> + +<title>Language Constructs</title> + +<simplesect><title>Recursive sets</title> + +<para>Recursive sets are just normal sets, but the attributes can +refer to each other. For example, + +<programlisting> +rec { + x = y; + y = 123; +}.x +</programlisting> + +evaluates to <literal>123</literal>. Note that without +<literal>rec</literal> the binding <literal>x = y;</literal> would +refer to the variable <varname>y</varname> in the surrounding scope, +if one exists, and would be invalid if no such variable exists. That +is, in a normal (non-recursive) set, attributes are not added to the +lexical scope; in a recursive set, they are.</para> + +<para>Recursive sets of course introduce the danger of infinite +recursion. For example, + +<programlisting> +rec { + x = y; + y = x; +}.x</programlisting> + +does not terminate<footnote><para>Actually, Nix detects infinite +recursion in this case and aborts (<quote>infinite recursion +encountered</quote>).</para></footnote>.</para> + +</simplesect> + + +<simplesect><title>Let-expressions</title> + +<para>A let-expression allows you define local variables for an +expression. For instance, + +<programlisting> +let + x = "foo"; + y = "bar"; +in x + y</programlisting> + +evaluates to <literal>"foobar"</literal>. + +</para> + +</simplesect> + + +<simplesect><title>Inheriting attributes</title> + +<para>When defining a set it is often convenient to copy variables +from the surrounding lexical scope (e.g., when you want to propagate +attributes). This can be shortened using the +<literal>inherit</literal> keyword. For instance, + +<programlisting> +let x = 123; in +{ inherit x; + y = 456; +}</programlisting> + +evaluates to <literal>{ x = 123; y = 456; }</literal>. (Note that +this works because <varname>x</varname> is added to the lexical scope +by the <literal>let</literal> construct.) It is also possible to +inherit attributes from another set. For instance, in this fragment +from <filename>all-packages.nix</filename>, + +<programlisting> + graphviz = (import ../tools/graphics/graphviz) { + inherit fetchurl stdenv libpng libjpeg expat x11 yacc; + inherit (xlibs) libXaw; + }; + + xlibs = { + libX11 = ...; + libXaw = ...; + ... + } + + libpng = ...; + libjpg = ...; + ...</programlisting> + +the set used in the function call to the function defined in +<filename>../tools/graphics/graphviz</filename> inherits a number of +variables from the surrounding scope (<varname>fetchurl</varname> +... <varname>yacc</varname>), but also inherits +<varname>libXaw</varname> (the X Athena Widgets) from the +<varname>xlibs</varname> (X11 client-side libraries) set.</para> + +</simplesect> + + +<simplesect xml:id="ss-functions"><title>Functions</title> + +<para>Functions have the following form: + +<programlisting> +<replaceable>pattern</replaceable>: <replaceable>body</replaceable></programlisting> + +The pattern specifies what the argument of the function must look +like, and binds variables in the body to (parts of) the +argument. There are three kinds of patterns:</para> + +<itemizedlist> + + + <listitem><para>If a pattern is a single identifier, then the + function matches any argument. Example: + + <programlisting> +let negate = x: !x; + concat = x: y: x + y; +in if negate true then concat "foo" "bar" else ""</programlisting> + + Note that <function>concat</function> is a function that takes one + argument and returns a function that takes another argument. This + allows partial parameterisation (i.e., only filling some of the + arguments of a function); e.g., + + <programlisting> +map (concat "foo") [ "bar" "bla" "abc" ]</programlisting> + + evaluates to <literal>[ "foobar" "foobla" + "fooabc" ]</literal>.</para></listitem> + + + <listitem><para>A <emphasis>set pattern</emphasis> of the form + <literal>{ name1, name2, …, nameN }</literal> matches a set + containing the listed attributes, and binds the values of those + attributes to variables in the function body. For example, the + function + +<programlisting> +{ x, y, z }: z + y + x</programlisting> + + can only be called with a set containing exactly the attributes + <varname>x</varname>, <varname>y</varname> and + <varname>z</varname>. No other attributes are allowed. If you want + to allow additional arguments, you can use an ellipsis + (<literal>...</literal>): + +<programlisting> +{ x, y, z, ... }: z + y + x</programlisting> + + This works on any set that contains at least the three named + attributes.</para> + + <para>It is possible to provide <emphasis>default values</emphasis> + for attributes, in which case they are allowed to be missing. A + default value is specified by writing + <literal><replaceable>name</replaceable> ? + <replaceable>e</replaceable></literal>, where + <replaceable>e</replaceable> is an arbitrary expression. For example, + +<programlisting> +{ x, y ? "foo", z ? "bar" }: z + y + x</programlisting> + + specifies a function that only requires an attribute named + <varname>x</varname>, but optionally accepts <varname>y</varname> + and <varname>z</varname>.</para></listitem> + + + <listitem><para>An <literal>@</literal>-pattern provides a means of referring + to the whole value being matched: + +<programlisting> args@{ x, y, z, ... }: z + y + x + args.a</programlisting> + +but can also be written as: + +<programlisting> { x, y, z, ... } @ args: z + y + x + args.a</programlisting> + + Here <varname>args</varname> is bound to the entire argument, which + is further matched against the pattern <literal>{ x, y, z, + ... }</literal>. <literal>@</literal>-pattern makes mainly sense with an + ellipsis(<literal>...</literal>) as you can access attribute names as + <literal>a</literal>, using <literal>args.a</literal>, which was given as an + additional attribute to the function. + </para></listitem> + +</itemizedlist> + +<para>Note that functions do not have names. If you want to give them +a name, you can bind them to an attribute, e.g., + +<programlisting> +let concat = { x, y }: x + y; +in concat { x = "foo"; y = "bar"; }</programlisting> + +</para> + +</simplesect> + + +<simplesect><title>Conditionals</title> + +<para>Conditionals look like this: + +<programlisting> +if <replaceable>e1</replaceable> then <replaceable>e2</replaceable> else <replaceable>e3</replaceable></programlisting> + +where <replaceable>e1</replaceable> is an expression that should +evaluate to a Boolean value (<literal>true</literal> or +<literal>false</literal>).</para> + +</simplesect> + + +<simplesect><title>Assertions</title> + +<para>Assertions are generally used to check that certain requirements +on or between features and dependencies hold. They look like this: + +<programlisting> +assert <replaceable>e1</replaceable>; <replaceable>e2</replaceable></programlisting> + +where <replaceable>e1</replaceable> is an expression that should +evaluate to a Boolean value. If it evaluates to +<literal>true</literal>, <replaceable>e2</replaceable> is returned; +otherwise expression evaluation is aborted and a backtrace is printed.</para> + +<example xml:id='ex-subversion-nix'><title>Nix expression for Subversion</title> +<programlisting> +{ localServer ? false +, httpServer ? false +, sslSupport ? false +, pythonBindings ? false +, javaSwigBindings ? false +, javahlBindings ? false +, stdenv, fetchurl +, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null +}: + +assert localServer -> db4 != null; <co xml:id='ex-subversion-nix-co-1' /> +assert httpServer -> httpd != null && httpd.expat == expat; <co xml:id='ex-subversion-nix-co-2' /> +assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); <co xml:id='ex-subversion-nix-co-3' /> +assert pythonBindings -> swig != null && swig.pythonSupport; +assert javaSwigBindings -> swig != null && swig.javaSupport; +assert javahlBindings -> j2sdk != null; + +stdenv.mkDerivation { + name = "subversion-1.1.1"; + ... + openssl = if sslSupport then openssl else null; <co xml:id='ex-subversion-nix-co-4' /> + ... +}</programlisting> +</example> + +<para><xref linkend='ex-subversion-nix' /> show how assertions are +used in the Nix expression for Subversion.</para> + +<calloutlist> + + <callout arearefs='ex-subversion-nix-co-1'> + <para>This assertion states that if Subversion is to have support + for local repositories, then Berkeley DB is needed. So if the + Subversion function is called with the + <varname>localServer</varname> argument set to + <literal>true</literal> but the <varname>db4</varname> argument + set to <literal>null</literal>, then the evaluation fails.</para> + </callout> + + <callout arearefs='ex-subversion-nix-co-2'> + <para>This is a more subtle condition: if Subversion is built with + Apache (<literal>httpServer</literal>) support, then the Expat + library (an XML library) used by Subversion should be same as the + one used by Apache. This is because in this configuration + Subversion code ends up being linked with Apache code, and if the + Expat libraries do not match, a build- or runtime link error or + incompatibility might occur.</para> + </callout> + + <callout arearefs='ex-subversion-nix-co-3'> + <para>This assertion says that in order for Subversion to have SSL + support (so that it can access <literal>https</literal> URLs), an + OpenSSL library must be passed. Additionally, it says that + <emphasis>if</emphasis> Apache support is enabled, then Apache's + OpenSSL should match Subversion's. (Note that if Apache support + is not enabled, we don't care about Apache's OpenSSL.)</para> + </callout> + + <callout arearefs='ex-subversion-nix-co-4'> + <para>The conditional here is not really related to assertions, + but is worth pointing out: it ensures that if SSL support is + disabled, then the Subversion derivation is not dependent on + OpenSSL, even if a non-<literal>null</literal> value was passed. + This prevents an unnecessary rebuild of Subversion if OpenSSL + changes.</para> + </callout> + +</calloutlist> + +</simplesect> + + + +<simplesect><title>With-expressions</title> + +<para>A <emphasis>with-expression</emphasis>, + +<programlisting> +with <replaceable>e1</replaceable>; <replaceable>e2</replaceable></programlisting> + +introduces the set <replaceable>e1</replaceable> into the lexical +scope of the expression <replaceable>e2</replaceable>. For instance, + +<programlisting> +let as = { x = "foo"; y = "bar"; }; +in with as; x + y</programlisting> + +evaluates to <literal>"foobar"</literal> since the +<literal>with</literal> adds the <varname>x</varname> and +<varname>y</varname> attributes of <varname>as</varname> to the +lexical scope in the expression <literal>x + y</literal>. The most +common use of <literal>with</literal> is in conjunction with the +<function>import</function> function. E.g., + +<programlisting> +with (import ./definitions.nix); ...</programlisting> + +makes all attributes defined in the file +<filename>definitions.nix</filename> available as if they were defined +locally in a <literal>rec</literal>-expression.</para> + +</simplesect> + + +<simplesect><title>Comments</title> + +<para>Comments can be single-line, started with a <literal>#</literal> +character, or inline/multi-line, enclosed within <literal>/* +... */</literal>.</para> + +</simplesect> + + +</section> diff --git a/doc/manual/expressions/language-operators.xml b/doc/manual/expressions/language-operators.xml new file mode 100644 index 000000000000..a3323ced4c50 --- /dev/null +++ b/doc/manual/expressions/language-operators.xml @@ -0,0 +1,113 @@ +<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-language-operators"> + +<title>Operators</title> + +<para><xref linkend='table-operators' /> lists the operators in the +Nix expression language, in order of precedence (from strongest to +weakest binding).</para> + +<table xml:id='table-operators'> + <title>Operators</title> + <tgroup cols='3'> + <thead> + <row> + <entry>Syntax</entry> + <entry>Associativity</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><replaceable>e</replaceable> <literal>.</literal> + <replaceable>attrpath</replaceable> + [ <literal>or</literal> <replaceable>def</replaceable> ] + </entry> + <entry>none</entry> + <entry>Select attribute denoted by the attribute path + <replaceable>attrpath</replaceable> from set + <replaceable>e</replaceable>. (An attribute path is a + dot-separated list of attribute names.) If the attribute + doesn’t exist, return <replaceable>def</replaceable> if + provided, otherwise abort evaluation.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <replaceable>e2</replaceable></entry> + <entry>left</entry> + <entry>Call function <replaceable>e1</replaceable> with + argument <replaceable>e2</replaceable>.</entry> + </row> + <row> + <entry><replaceable>e</replaceable> <literal>?</literal> + <replaceable>attrpath</replaceable></entry> + <entry>none</entry> + <entry>Test whether set <replaceable>e</replaceable> contains + the attribute denoted by <replaceable>attrpath</replaceable>; + return <literal>true</literal> or + <literal>false</literal>.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>++</literal> <replaceable>e2</replaceable></entry> + <entry>right</entry> + <entry>List concatenation.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>+</literal> <replaceable>e2</replaceable></entry> + <entry>left</entry> + <entry>String or path concatenation.</entry> + </row> + <row> + <entry><literal>!</literal> <replaceable>e</replaceable></entry> + <entry>left</entry> + <entry>Boolean negation.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>//</literal> + <replaceable>e2</replaceable></entry> + <entry>right</entry> + <entry>Return a set consisting of the attributes in + <replaceable>e1</replaceable> and + <replaceable>e2</replaceable> (with the latter taking + precedence over the former in case of equally named + attributes).</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>==</literal> + <replaceable>e2</replaceable></entry> + <entry>none</entry> + <entry>Equality.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>!=</literal> + <replaceable>e2</replaceable></entry> + <entry>none</entry> + <entry>Inequality.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>&&</literal> + <replaceable>e2</replaceable></entry> + <entry>left</entry> + <entry>Logical AND.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>||</literal> + <replaceable>e2</replaceable></entry> + <entry>left</entry> + <entry>Logical OR.</entry> + </row> + <row> + <entry><replaceable>e1</replaceable> <literal>-></literal> + <replaceable>e2</replaceable></entry> + <entry>none</entry> + <entry>Logical implication (equivalent to + <literal>!<replaceable>e1</replaceable> || + <replaceable>e2</replaceable></literal>).</entry> + </row> + </tbody> + </tgroup> +</table> + +</section> \ No newline at end of file diff --git a/doc/manual/expressions/language-values.xml b/doc/manual/expressions/language-values.xml new file mode 100644 index 000000000000..67da688a4fc5 --- /dev/null +++ b/doc/manual/expressions/language-values.xml @@ -0,0 +1,309 @@ +<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='ssec-values'> + +<title>Values</title> + + +<simplesect><title>Simple Values</title> + +<para>Nix has the following basic data types: + +<itemizedlist> + + <listitem> + + <para><emphasis>Strings</emphasis> can be written in three + ways.</para> + + <para>The most common way is to enclose the string between double + quotes, e.g., <literal>"foo bar"</literal>. Strings can span + multiple lines. The special characters <literal>"</literal> and + <literal>\</literal> and the character sequence + <literal>${</literal> must be escaped by prefixing them with a + backslash (<literal>\</literal>). Newlines, carriage returns and + tabs can be written as <literal>\n</literal>, + <literal>\r</literal> and <literal>\t</literal>, + respectively.</para> + + <para>You can include the result of an expression into a string by + enclosing it in + <literal>${<replaceable>...</replaceable>}</literal>, a feature + known as <emphasis>antiquotation</emphasis>. The enclosed + expression must evaluate to something that can be coerced into a + string (meaning that it must be a string, a path, or a + derivation). For instance, rather than writing + +<programlisting> +"--with-freetype2-library=" + freetype + "/lib"</programlisting> + + (where <varname>freetype</varname> is a derivation), you can + instead write the more natural + +<programlisting> +"--with-freetype2-library=${freetype}/lib"</programlisting> + + The latter is automatically translated to the former. A more + complicated example (from the Nix expression for <link + xlink:href='http://www.trolltech.com/products/qt'>Qt</link>): + +<programlisting> +configureFlags = " + -system-zlib -system-libpng -system-libjpeg + ${if openglSupport then "-dlopen-opengl + -L${mesa}/lib -I${mesa}/include + -L${libXmu}/lib -I${libXmu}/include" else ""} + ${if threadSupport then "-thread" else "-no-thread"} +";</programlisting> + + Note that Nix expressions and strings can be arbitrarily nested; + in this case the outer string contains various antiquotations that + themselves contain strings (e.g., <literal>"-thread"</literal>), + some of which in turn contain expressions (e.g., + <literal>${mesa}</literal>).</para> + + <para>The second way to write string literals is as an + <emphasis>indented string</emphasis>, which is enclosed between + pairs of <emphasis>double single-quotes</emphasis>, like so: + +<programlisting> +'' + This is the first line. + This is the second line. + This is the third line. +''</programlisting> + + This kind of string literal intelligently strips indentation from + the start of each line. To be precise, it strips from each line a + number of spaces equal to the minimal indentation of the string as + a whole (disregarding the indentation of empty lines). For + instance, the first and second line are indented two space, while + the third line is indented four spaces. Thus, two spaces are + stripped from each line, so the resulting string is + +<programlisting> +"This is the first line.\nThis is the second line.\n This is the third line.\n"</programlisting> + + </para> + + <para>Note that the whitespace and newline following the opening + <literal>''</literal> is ignored if there is no non-whitespace + text on the initial line.</para> + + <para>Antiquotation + (<literal>${<replaceable>expr</replaceable>}</literal>) is + supported in indented strings.</para> + + <para>Since <literal>${</literal> and <literal>''</literal> have + special meaning in indented strings, you need a way to quote them. + <literal>${</literal> can be escaped by prefixing it with + <literal>''</literal> (that is, two single quotes), i.e., + <literal>''${</literal>. <literal>''</literal> can be escaped by + prefixing it with <literal>'</literal>, i.e., + <literal>'''</literal>. Finally, linefeed, carriage-return and + tab characters can be written as <literal>''\n</literal>, + <literal>''\r</literal>, <literal>''\t</literal>.</para> + + <para>Indented strings are primarily useful in that they allow + multi-line string literals to follow the indentation of the + enclosing Nix expression, and that less escaping is typically + necessary for strings representing languages such as shell scripts + and configuration files because <literal>''</literal> is much less + common than <literal>"</literal>. Example: + +<programlisting> +stdenv.mkDerivation { + <replaceable>...</replaceable> + postInstall = + '' + mkdir $out/bin $out/etc + cp foo $out/bin + echo "Hello World" > $out/etc/foo.conf + ${if enableBar then "cp bar $out/bin" else ""} + ''; + <replaceable>...</replaceable> +} +</programlisting> + + </para> + + <para>Finally, as a convenience, <emphasis>URIs</emphasis> as + defined in appendix B of <link + xlink:href='http://www.ietf.org/rfc/rfc2396.txt'>RFC 2396</link> + can be written <emphasis>as is</emphasis>, without quotes. For + instance, the string + <literal>"http://example.org/foo.tar.bz2"</literal> + can also be written as + <literal>http://example.org/foo.tar.bz2</literal>.</para> + + </listitem> + + <listitem><para>Numbers, which can be <emphasis>integers</emphasis> (like + <literal>123</literal>) or <emphasis>floating point</emphasis> (like + <literal>123.43</literal> or <literal>.27e13</literal>).</para> + + <para>Numbers are type-compatible: pure integer operations will always + return integers, whereas any operation involving at least one floating point + number will have a floating point number as a result.</para></listitem> + + <listitem><para><emphasis>Paths</emphasis>, e.g., + <filename>/bin/sh</filename> or <filename>./builder.sh</filename>. + A path must contain at least one slash to be recognised as such; for + instance, <filename>builder.sh</filename> is not a + path<footnote><para>It's parsed as an expression that selects the + attribute <varname>sh</varname> from the variable + <varname>builder</varname>.</para></footnote>. If the file name is + relative, i.e., if it does not begin with a slash, it is made + absolute at parse time relative to the directory of the Nix + expression that contained it. For instance, if a Nix expression in + <filename>/foo/bar/bla.nix</filename> refers to + <filename>../xyzzy/fnord.nix</filename>, the absolute path is + <filename>/foo/xyzzy/fnord.nix</filename>.</para> + + <para>If the first component of a path is a <literal>~</literal>, + it is interpreted as if the rest of the path were relative to the + user's home directory. e.g. <filename>~/foo</filename> would be + equivalent to <filename>/home/edolstra/foo</filename> for a user + whose home directory is <filename>/home/edolstra</filename>. + </para> + + <para>Paths can also be specified between angle brackets, e.g. + <literal><nixpkgs></literal>. This means that the directories + listed in the environment variable + <envar linkend="env-NIX_PATH">NIX_PATH</envar> will be searched + for the given file or directory name. + </para> + + </listitem> + + <listitem><para><emphasis>Booleans</emphasis> with values + <literal>true</literal> and + <literal>false</literal>.</para></listitem> + + <listitem><para>The null value, denoted as + <literal>null</literal>.</para></listitem> + +</itemizedlist> + +</para> + +</simplesect> + + +<simplesect><title>Lists</title> + +<para>Lists are formed by enclosing a whitespace-separated list of +values between square brackets. For example, + +<programlisting> +[ 123 ./foo.nix "abc" (f { x = y; }) ]</programlisting> + +defines a list of four elements, the last being the result of a call +to the function <varname>f</varname>. Note that function calls have +to be enclosed in parentheses. If they had been omitted, e.g., + +<programlisting> +[ 123 ./foo.nix "abc" f { x = y; } ]</programlisting> + +the result would be a list of five elements, the fourth one being a +function and the fifth being a set.</para> + +<para>Note that lists are only lazy in values, and they are strict in length. +</para> + +</simplesect> + + +<simplesect><title>Sets</title> + +<para>Sets are really the core of the language, since ultimately the +Nix language is all about creating derivations, which are really just +sets of attributes to be passed to build scripts.</para> + +<para>Sets are just a list of name/value pairs (called +<emphasis>attributes</emphasis>) enclosed in curly brackets, where +each value is an arbitrary expression terminated by a semicolon. For +example: + +<programlisting> +{ x = 123; + text = "Hello"; + y = f { bla = 456; }; +}</programlisting> + +This defines a set with attributes named <varname>x</varname>, +<varname>text</varname>, <varname>y</varname>. The order of the +attributes is irrelevant. An attribute name may only occur +once.</para> + +<para>Attributes can be selected from a set using the +<literal>.</literal> operator. For instance, + +<programlisting> +{ a = "Foo"; b = "Bar"; }.a</programlisting> + +evaluates to <literal>"Foo"</literal>. It is possible to provide a +default value in an attribute selection using the +<literal>or</literal> keyword. For example, + +<programlisting> +{ a = "Foo"; b = "Bar"; }.c or "Xyzzy"</programlisting> + +will evaluate to <literal>"Xyzzy"</literal> because there is no +<varname>c</varname> attribute in the set.</para> + +<para>You can use arbitrary double-quoted strings as attribute +names: + +<programlisting> +{ "foo ${bar}" = 123; "nix-1.0" = 456; }."foo ${bar}" +</programlisting> + +This will evaluate to <literal>123</literal> (Assuming +<literal>bar</literal> is antiquotable). In the case where an +attribute name is just a single antiquotation, the quotes can be +dropped: + +<programlisting> +{ foo = 123; }.${bar} or 456 </programlisting> + +This will evaluate to <literal>123</literal> if +<literal>bar</literal> evaluates to <literal>"foo"</literal> when +coerced to a string and <literal>456</literal> otherwise (again +assuming <literal>bar</literal> is antiquotable).</para> + +<para>In the special case where an attribute name inside of a set declaration +evaluates to <literal>null</literal> (which is normally an error, as +<literal>null</literal> is not antiquotable), that attribute is simply not +added to the set: + +<programlisting> +{ ${if foo then "bar" else null} = true; }</programlisting> + +This will evaluate to <literal>{}</literal> if <literal>foo</literal> +evaluates to <literal>false</literal>.</para> + +<para>A set that has a <literal>__functor</literal> attribute whose value +is callable (i.e. is itself a function or a set with a +<literal>__functor</literal> attribute whose value is callable) can be +applied as if it were a function, with the set itself passed in first +, e.g., + +<programlisting> +let add = { __functor = self: x: x + self.x; }; + inc = add // { x = 1; }; +in inc 1 +</programlisting> + +evaluates to <literal>2</literal>. This can be used to attach metadata to a +function without the caller needing to treat it specially, or to implement +a form of object-oriented programming, for example. + +</para> + +</simplesect> + + +</section> diff --git a/doc/manual/expressions/simple-building-testing.xml b/doc/manual/expressions/simple-building-testing.xml new file mode 100644 index 000000000000..bd3901a13351 --- /dev/null +++ b/doc/manual/expressions/simple-building-testing.xml @@ -0,0 +1,86 @@ +<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-building-simple'> + +<title>Building and Testing</title> + +<para>You can now try to build Hello. Of course, you could do +<literal>nix-env -i hello</literal>, but you may not want to install a +possibly broken package just yet. The best way to test the package is by +using the command <command linkend="sec-nix-build">nix-build</command>, +which builds a Nix expression and creates a symlink named +<filename>result</filename> in the current directory: + +<screen> +$ nix-build -A hello +building path `/nix/store/632d2b22514d...-hello-2.1.1' +hello-2.1.1/ +hello-2.1.1/intl/ +hello-2.1.1/intl/ChangeLog +<replaceable>...</replaceable> + +$ ls -l result +lrwxrwxrwx ... 2006-09-29 10:43 result -> /nix/store/632d2b22514d...-hello-2.1.1 + +$ ./result/bin/hello +Hello, world!</screen> + +The <link linkend='opt-attr'><option>-A</option></link> option selects +the <literal>hello</literal> attribute. This is faster than using the +symbolic package name specified by the <literal>name</literal> +attribute (which also happens to be <literal>hello</literal>) and is +unambiguous (there can be multiple packages with the symbolic name +<literal>hello</literal>, but there can be only one attribute in a set +named <literal>hello</literal>).</para> + +<para><command>nix-build</command> registers the +<filename>./result</filename> symlink as a garbage collection root, so +unless and until you delete the <filename>./result</filename> symlink, +the output of the build will be safely kept on your system. You can +use <command>nix-build</command>’s <option +linkend='opt-out-link'>-o</option> switch to give the symlink another +name.</para> + +<para>Nix has a transactional semantics. Once a build finishes +successfully, Nix makes a note of this in its database: it registers +that the path denoted by <envar>out</envar> is now +<quote>valid</quote>. If you try to build the derivation again, Nix +will see that the path is already valid and finish immediately. If a +build fails, either because it returns a non-zero exit code, because +Nix or the builder are killed, or because the machine crashes, then +the output paths will not be registered as valid. If you try to build +the derivation again, Nix will remove the output paths if they exist +(e.g., because the builder died half-way through <literal>make +install</literal>) and try again. Note that there is no +<quote>negative caching</quote>: Nix doesn't remember that a build +failed, and so a failed build can always be repeated. This is because +Nix cannot distinguish between permanent failures (e.g., a compiler +error due to a syntax error in the source) and transient failures +(e.g., a disk full condition).</para> + +<para>Nix also performs locking. If you run multiple Nix builds +simultaneously, and they try to build the same derivation, the first +Nix instance that gets there will perform the build, while the others +block (or perform other derivations if available) until the build +finishes: + +<screen> +$ nix-build -A hello +waiting for lock on `/nix/store/0h5b7hp8d4hqfrw8igvx97x1xawrjnac-hello-2.1.1x'</screen> + +So it is always safe to run multiple instances of Nix in parallel +(which isn’t the case with, say, <command>make</command>).</para> + +<para>If you have a system with multiple CPUs, you may want to have +Nix build different derivations in parallel (insofar as possible). +Just pass the option <link linkend='opt-max-jobs'><option>-j +<replaceable>N</replaceable></option></link>, where +<replaceable>N</replaceable> is the maximum number of jobs to be run +in parallel, or set. Typically this should be the number of +CPUs.</para> + +<xi:include href="debug-build.xml" /> + +</section> diff --git a/doc/manual/expressions/simple-expression.xml b/doc/manual/expressions/simple-expression.xml new file mode 100644 index 000000000000..29fd872eea19 --- /dev/null +++ b/doc/manual/expressions/simple-expression.xml @@ -0,0 +1,47 @@ +<chapter 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="ch-simple-expression"> + +<title>A Simple Nix Expression</title> + +<para>This section shows how to add and test the <link +xlink:href='http://www.gnu.org/software/hello/hello.html'>GNU Hello +package</link> to the Nix Packages collection. Hello is a program +that prints out the text <quote>Hello, world!</quote>.</para> + +<para>To add a package to the Nix Packages collection, you generally +need to do three things: + +<orderedlist> + + <listitem><para>Write a Nix expression for the package. This is a + file that describes all the inputs involved in building the package, + such as dependencies, sources, and so on.</para></listitem> + + <listitem><para>Write a <emphasis>builder</emphasis>. This is a + shell script<footnote><para>In fact, it can be written in any + language, but typically it's a <command>bash</command> shell + script.</para></footnote> that actually builds the package from + the inputs.</para></listitem> + + <listitem><para>Add the package to the file + <filename>pkgs/top-level/all-packages.nix</filename>. The Nix + expression written in the first step is a + <emphasis>function</emphasis>; it requires other packages in order + to build it. In this step you put it all together, i.e., you call + the function with the right arguments to build the actual + package.</para></listitem> + +</orderedlist> + +</para> + +<xi:include href="expression-syntax.xml" /> +<xi:include href="build-script.xml" /> +<xi:include href="arguments-variables.xml" /> +<xi:include href="simple-building-testing.xml" /> +<xi:include href="generic-builder.xml" /> + +</chapter> diff --git a/doc/manual/expressions/writing-nix-expressions.xml b/doc/manual/expressions/writing-nix-expressions.xml new file mode 100644 index 000000000000..6646dddf0842 --- /dev/null +++ b/doc/manual/expressions/writing-nix-expressions.xml @@ -0,0 +1,26 @@ +<part 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='chap-writing-nix-expressions'> + +<title>Writing Nix Expressions</title> + +<partintro> +<para>This chapter shows you how to write Nix expressions, which +instruct Nix how to build packages. It starts with a +simple example (a Nix expression for GNU Hello), and then moves +on to a more in-depth look at the Nix expression language.</para> + +<note><para>This chapter is mostly about the Nix expression language. +For more extensive information on adding packages to the Nix Packages +collection (such as functions in the standard environment and coding +conventions), please consult <link +xlink:href="http://nixos.org/nixpkgs/manual/">its +manual</link>.</para></note> +</partintro> + +<xi:include href="simple-expression.xml" /> +<xi:include href="expression-language.xml" /> + +</part> |