forked from lix-project/lix
59707975a3
* Release notes.
760 lines
25 KiB
XML
760 lines
25 KiB
XML
<section xmlns="http://docbook.org/ns/docbook"
|
||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||
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 an attribute 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>attrs</replaceable></term>
|
||
|
||
<listitem><para>Return the names of the attributes in the
|
||
attribute set <replaceable>attrs</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 = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames attrs);</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 attribute 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.
|
||
However, in that case you should not write
|
||
|
||
<programlisting>
|
||
if builtins ? getEnv then __getEnv "PATH" else ""</programlisting>
|
||
|
||
This Nix expression will trigger an “undefined variable” error on
|
||
older Nix versions since <function>__getEnv</function> doesn’t
|
||
exist. <literal>builtins.getEnv</literal>, on the other hand, is
|
||
safe since <literal>builtins</literal> always exists and attribute
|
||
selection is lazy, so it’s only performed if the test
|
||
succeeds.</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.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.getAttr</function>
|
||
<replaceable>s</replaceable> <replaceable>attrs</replaceable></term>
|
||
|
||
<listitem><para><function>getAttr</function> returns the attribute
|
||
named <replaceable>s</replaceable> from the attribute set
|
||
<replaceable>attrs</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>attrs</replaceable></term>
|
||
|
||
<listitem><para><function>hasAttr</function> returns
|
||
<literal>true</literal> if the attribute set
|
||
<replaceable>attrs</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.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>. 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 an attribute 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.isAttrs</function>
|
||
<replaceable>e</replaceable></term>
|
||
|
||
<listitem><para>Return <literal>true</literal> if
|
||
<replaceable>e</replaceable> evaluates to an attribute 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>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.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 an attribute set from a list specifying
|
||
the names and values of each attribute. Each element of the list
|
||
should be an attribute 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.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>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>attrs</replaceable> <replaceable>list</replaceable></term>
|
||
|
||
<listitem><para>Remove the attributes listed in
|
||
<replaceable>list</replaceable> from the attribute set
|
||
<replaceable>attrs</replaceable>. The attributes don’t have to
|
||
exist in <replaceable>attrs</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.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
|
||
attribute 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>
|
||
|
||
|
||
</variablelist>
|
||
|
||
|
||
</section>
|