aboutsummaryrefslogtreecommitdiff
path: root/doc/manual/expressions/builtins.xml
diff options
context:
space:
mode:
authorMikey Ariel <mariel@redhat.com>2014-08-27 18:41:09 +0200
committerMikey Ariel <mariel@redhat.com>2014-08-27 18:41:09 +0200
commit8901acc97664aa8ebf687ee904428aa57a5192be (patch)
treef7bfefccbc2a08cc49eb37b424758a6158b29b58 /doc/manual/expressions/builtins.xml
parent3f0a4bf0e7254edddaa864d23893d98da23c2977 (diff)
Restructuring the Nix manual
Diffstat (limited to 'doc/manual/expressions/builtins.xml')
-rw-r--r--doc/manual/expressions/builtins.xml950
1 files changed, 950 insertions, 0 deletions
diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml
new file mode 100644
index 000000000..4edb3a1a7
--- /dev/null
+++ b/doc/manual/expressions/builtins.xml
@@ -0,0 +1,950 @@
+<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 integers
+ <replaceable>e1</replaceable> and
+ <replaceable>e2</replaceable>.</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>. There is no built-in
+ function <function>attrValues</function>, but you can easily
+ define it yourself:
+
+<programlisting>
+attrValues = set: map (name: builtins.getAttr name set) (builtins.attrNames set);</programlisting>
+
+ </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>"powerpc-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>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 integers
+ <replaceable>e1</replaceable> and
+ <replaceable>e2</replaceable>.</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.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.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.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 integer
+ <replaceable>e1</replaceable> is less than the integer
+ <replaceable>e2</replaceable>, and <literal>false</literal>
+ otherwise. Evaluation aborts if either
+ <replaceable>e1</replaceable> or <replaceable>e2</replaceable>
+ does not evaluate to an integer.</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 integers
+ <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 != "" &amp;&amp; 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>relativise</function></term>
+
+ <listitem><para>TODO</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,
+
+<screen>
+removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</screen>
+
+ evaluates to <literal>{ y = 2; }</literal>.</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 integers
+ <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.</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, 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 a string (in which case
+ <function>toString</function> is a no-op) or a path (e.g.,
+ <literal>toString /foo/bar</literal> yields
+ <literal>"/foo/bar"</literal>.</para></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.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>