diff options
Diffstat (limited to 'doc/manual/writing-nix-expressions.xml')
-rw-r--r-- | doc/manual/writing-nix-expressions.xml | 586 |
1 files changed, 3 insertions, 583 deletions
diff --git a/doc/manual/writing-nix-expressions.xml b/doc/manual/writing-nix-expressions.xml index ce6c1f4addc3..c4bc35cc7e68 100644 --- a/doc/manual/writing-nix-expressions.xml +++ b/doc/manual/writing-nix-expressions.xml @@ -1,6 +1,7 @@ <chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" - xml:id='chap-writing-nix-expressions'> + xml:id='chap-writing-nix-expressions' + xmlns:xi="http://www.w3.org/2001/XInclude"> <title>Writing Nix Expressions</title> @@ -1339,589 +1340,8 @@ command-line argument. See <xref linkend='sec-standard-environment' </section> -<section><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.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.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>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>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>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.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 - 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> - - -</variablelist> - -</section> +<xi:include href="builtins.xml" /> </section> |