Get rid of callouts since Markdown doesn't support them

This commit is contained in:
Eelco Dolstra 2020-07-23 13:58:49 +02:00
parent efff6cf163
commit 13df1faf25
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
12 changed files with 233 additions and 251 deletions

View file

@ -6,20 +6,25 @@
<title>Arguments and Variables</title> <title>Arguments and Variables</title>
<example xml:id='ex-hello-composition'> <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. Here are some fragments of
<filename>all-packages.nix</filename>, with annotations of what they
mean:</para>
<title>Composing GNU Hello
(<filename>all-packages.nix</filename>)</title>
<programlisting> <programlisting>
... ...
rec { <co xml:id='ex-hello-composition-co-1' /> rec {
hello = import ../applications/misc/hello/ex-1 <co xml:id='ex-hello-composition-co-2' /> { <co xml:id='ex-hello-composition-co-3' /> hello = import ../applications/misc/hello/ex-1 ② { ③
inherit fetchurl stdenv perl; inherit fetchurl stdenv perl;
}; };
perl = import ../development/interpreters/perl { <co xml:id='ex-hello-composition-co-4' /> perl = import ../development/interpreters/perl {
inherit fetchurl stdenv; inherit fetchurl stdenv;
}; };
@ -31,31 +36,19 @@ rec { <co xml:id='ex-hello-composition-co-1' />
} }
</programlisting> </programlisting>
</example>
<para>The Nix expression in <xref linkend='ex-hello-nix' /> is a <orderedlist>
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'>
<listitem>
<para>This file defines a set of attributes, all of which are <para>This file defines a set of attributes, all of which are
concrete derivations (i.e., not functions). In fact, we define a concrete derivations (i.e., not functions). In fact, we define a
<emphasis>mutually recursive</emphasis> set of attributes. That <emphasis>mutually recursive</emphasis> set of attributes. That
is, the attributes can refer to each other. This is precisely is, the attributes can refer to each other. This is precisely
what we want since we want to <quote>plug</quote> the what we want since we want to <quote>plug</quote> the
various packages into each other.</para> various packages into each other.</para>
</listitem>
</callout> <listitem>
<callout arearefs='ex-hello-composition-co-2'>
<para>Here we <emphasis>import</emphasis> the Nix expression for <para>Here we <emphasis>import</emphasis> the Nix expression for
GNU Hello. The import operation just loads and returns the GNU Hello. The import operation just loads and returns the
@ -71,9 +64,9 @@ some fragments of
When you try to import a directory, Nix automatically appends When you try to import a directory, Nix automatically appends
<filename>/default.nix</filename> to the file name.</para> <filename>/default.nix</filename> to the file name.</para>
</callout> </listitem>
<callout arearefs='ex-hello-composition-co-3'> <listitem>
<para>This is where the actual composition takes place. Here we <para>This is where the actual composition takes place. Here we
<emphasis>call</emphasis> the function imported from <emphasis>call</emphasis> the function imported from
@ -107,15 +100,15 @@ hello = callPackage ../applications/misc/hello/ex-1 { stdenv = myStdenv; };
</para></note> </para></note>
</callout> </listitem>
<callout arearefs='ex-hello-composition-co-4'> <listitem>
<para>Likewise, we have to instantiate Perl, <para>Likewise, we have to instantiate Perl,
<varname>fetchurl</varname>, and the standard environment.</para> <varname>fetchurl</varname>, and the standard environment.</para>
</callout> </listitem>
</calloutlist> </orderedlist>
</section> </section>

View file

@ -6,32 +6,30 @@
<title>Build Script</title> <title>Build Script</title>
<example xml:id='ex-hello-builder'><title>Build script for GNU Hello <para>Here is the builder referenced
(<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 from Hello's Nix expression (stored in
<filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>). <filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>):</para>
The builder can actually be made a lot shorter by using the
<programlisting>
source $stdenv/setup ①
PATH=$perl/bin:$PATH ②
tar xvfz $src ③
cd hello-*
./configure --prefix=$out ④
make ⑤
make install</programlisting>
<para>The builder can actually be made a lot shorter by using the
<emphasis>generic builder</emphasis> functions provided by <emphasis>generic builder</emphasis> functions provided by
<varname>stdenv</varname>, but here we write out the build steps to <varname>stdenv</varname>, but here we write out the build steps to
elucidate what a builder does. It performs the following elucidate what a builder does. It performs the following
steps:</para> steps:</para>
<calloutlist> <orderedlist>
<callout arearefs='ex-hello-builder-co-1'> <listitem>
<para>When Nix runs a builder, it initially completely clears the <para>When Nix runs a builder, it initially completely clears the
environment (except for the attributes declared in the environment (except for the attributes declared in the
@ -52,9 +50,9 @@ steps:</para>
attribute in <xref linkend='ex-hello-nix' />, but attribute in <xref linkend='ex-hello-nix' />, but
<varname>mkDerivation</varname> adds it automatically.)</para> <varname>mkDerivation</varname> adds it automatically.)</para>
</callout> </listitem>
<callout arearefs='ex-hello-builder-co-2'> <listitem>
<para>Since Hello needs Perl, we have to make sure that Perl is in <para>Since Hello needs Perl, we have to make sure that Perl is in
the <literal>PATH</literal>. The <literal>perl</literal> environment the <literal>PATH</literal>. The <literal>perl</literal> environment
@ -63,9 +61,9 @@ steps:</para>
<filename><replaceable>$perl</replaceable>/bin</filename> is the <filename><replaceable>$perl</replaceable>/bin</filename> is the
directory containing the Perl interpreter.</para> directory containing the Perl interpreter.</para>
</callout> </listitem>
<callout arearefs='ex-hello-builder-co-3'> <listitem>
<para>Now we have to unpack the sources. The <para>Now we have to unpack the sources. The
<varname>src</varname> attribute was bound to the result of <varname>src</varname> attribute was bound to the result of
@ -82,9 +80,9 @@ steps:</para>
always newly created, so you don't have to worry about files from always newly created, so you don't have to worry about files from
previous builds interfering with the current build.</para> previous builds interfering with the current build.</para>
</callout> </listitem>
<callout arearefs='ex-hello-builder-co-4'> <listitem>
<para>GNU Hello is a typical Autoconf-based package, so we first <para>GNU Hello is a typical Autoconf-based package, so we first
have to run its <filename>configure</filename> script. In Nix have to run its <filename>configure</filename> script. In Nix
@ -98,17 +96,17 @@ steps:</para>
<literal>--prefix=$out</literal> to cause Hello to be installed in <literal>--prefix=$out</literal> to cause Hello to be installed in
the expected location.</para> the expected location.</para>
</callout> </listitem>
<callout arearefs='ex-hello-builder-co-5'> <listitem>
<para>Finally we build Hello (<literal>make</literal>) and install <para>Finally we build Hello (<literal>make</literal>) and install
it into the location specified by <literal>out</literal> it into the location specified by <literal>out</literal>
(<literal>make install</literal>).</para> (<literal>make install</literal>).</para>
</callout> </listitem>
</calloutlist> </orderedlist>
<para>If you are wondering about the absence of error checking on the <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 result of various commands called in the builder: this is because the

View file

@ -1511,39 +1511,9 @@ in foo</programlisting>
<!-- TODO: more formally describe the schema of the XML <!-- TODO: more formally describe the schema of the XML
representation --> representation -->
<para><xref linkend='ex-toxml' /> shows an example where this is <para>Here is an example where this is
the case. The builder is supposed to generate the configuration the case:
file for a <link xlink:href='http://jetty.mortbay.org/'>Jetty </para>
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 wouldnt 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[ <programlisting><![CDATA[
{ stdenv, fetchurl, libxslt, jira, uberwiki }: { stdenv, fetchurl, libxslt, jira, uberwiki }:
@ -1556,10 +1526,10 @@ stdenv.mkDerivation (rec {
builder = builtins.toFile "builder.sh" " builder = builtins.toFile "builder.sh" "
source $stdenv/setup source $stdenv/setup
mkdir $out mkdir $out
echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <co xml:id='ex-toxml-co-apply' /> <![CDATA[ echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml]]> <![CDATA[
"; ";
stylesheet = builtins.toFile "stylesheet.xsl"]]> <co xml:id='ex-toxml-co-stylesheet' /> <![CDATA[ stylesheet = builtins.toFile "stylesheet.xsl"]]> <![CDATA[
"<?xml version='1.0' encoding='UTF-8'?> "<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:template match='/'> <xsl:template match='/'>
@ -1575,16 +1545,32 @@ stdenv.mkDerivation (rec {
</xsl:stylesheet> </xsl:stylesheet>
"; ";
servlets = builtins.toXML []]> <co xml:id='ex-toxml-co-servlets' /> <![CDATA[ servlets = builtins.toXML []]> <![CDATA[
{ path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; } { path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; }
{ path = "/wiki"; war = uberwiki + "/uberwiki.war"; } { path = "/wiki"; war = uberwiki + "/uberwiki.war"; }
]; ];
})]]></programlisting> })]]></programlisting>
</example> <para>The builder is supposed to generate the configuration file
for a <link xlink:href='http://jetty.mortbay.org/'>Jetty servlet
<example xml:id='ex-toxml-result'><title>XML representation produced by container</link>. A servlet container contains a number of
<function>toXML</function></title> 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 wouldnt 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 (at point ②) is applied to it (at point
①) to generate the XML configuration file for the Jetty server.
The XML representation produced at point ③ by
<function>toXML</function> is as follows:</para>
<programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?> <programlisting><![CDATA[<?xml version='1.0' encoding='utf-8'?>
<expr> <expr>
@ -1608,7 +1594,11 @@ stdenv.mkDerivation (rec {
</list> </list>
</expr>]]></programlisting> </expr>]]></programlisting>
</example> <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 using the
syntax <literal>xsltproc ${stylesheet}</literal>.</para>
</listitem> </listitem>

View file

@ -6,33 +6,31 @@
<title>Expression Syntax</title> <title>Expression Syntax</title>
<example xml:id='ex-hello-nix'><title>Nix expression for GNU Hello <para>Here is a Nix expression for GNU Hello:</para>
(<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' /> <programlisting>
name = "hello-2.1.1"; <co xml:id='ex-hello-nix-co-3' /> { stdenv, fetchurl, perl }: ①
builder = ./builder.sh; <co xml:id='ex-hello-nix-co-4' />
src = fetchurl { <co xml:id='ex-hello-nix-co-5' /> stdenv.mkDerivation { ②
name = "hello-2.1.1"; ③
builder = ./builder.sh; ④
src = fetchurl { ⑤
url = "ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz"; url = "ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz";
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465"; sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
}; };
inherit perl; <co xml:id='ex-hello-nix-co-6' /> inherit perl;
}</programlisting> }</programlisting>
</example>
<para><xref linkend='ex-hello-nix' /> shows a Nix expression for GNU <para>This file is actually already in the Nix Packages collection in
Hello. It's actually already in the Nix Packages collection in
<filename>pkgs/applications/misc/hello/ex-1/default.nix</filename>. <filename>pkgs/applications/misc/hello/ex-1/default.nix</filename>.
It is customary to place each package in a separate directory and call It is customary to place each package in a separate directory and call
the single Nix expression in that directory the single Nix expression in that directory
<filename>default.nix</filename>. The file has the following elements <filename>default.nix</filename>. The file has the following elements
(referenced from the figure by number): (referenced from the figure by number):
<calloutlist> <orderedlist>
<callout arearefs='ex-hello-nix-co-1'> <listitem>
<para>This states that the expression is a <para>This states that the expression is a
<emphasis>function</emphasis> that expects to be called with three <emphasis>function</emphasis> that expects to be called with three
@ -57,9 +55,9 @@ the single Nix expression in that directory
function; when given the required arguments, the body should function; when given the required arguments, the body should
describe how to build an instance of the Hello package.</para> describe how to build an instance of the Hello package.</para>
</callout> </listitem>
<callout arearefs='ex-hello-nix-co-2'> <listitem>
<para>So we have to build a package. Building something from <para>So we have to build a package. Building something from
other stuff is called a <emphasis>derivation</emphasis> in Nix (as other stuff is called a <emphasis>derivation</emphasis> in Nix (as
@ -76,9 +74,9 @@ the single Nix expression in that directory
<replaceable>nameN</replaceable> = <replaceable>nameN</replaceable> =
<replaceable>exprN</replaceable>; }</literal>.</para> <replaceable>exprN</replaceable>; }</literal>.</para>
</callout> </listitem>
<callout arearefs='ex-hello-nix-co-3'> <listitem>
<para>The attribute <varname>name</varname> specifies the symbolic <para>The attribute <varname>name</varname> specifies the symbolic
name and version of the package. Nix doesn't really care about name and version of the package. Nix doesn't really care about
@ -87,9 +85,9 @@ the single Nix expression in that directory
packages. This attribute is required by packages. This attribute is required by
<varname>mkDerivation</varname>.</para> <varname>mkDerivation</varname>.</para>
</callout> </listitem>
<callout arearefs='ex-hello-nix-co-4'> <listitem>
<para>The attribute <varname>builder</varname> specifies the <para>The attribute <varname>builder</varname> specifies the
builder. This attribute can sometimes be omitted, in which case builder. This attribute can sometimes be omitted, in which case
@ -101,9 +99,9 @@ the single Nix expression in that directory
<command>./builder.sh</command> refers to the shell script shown <command>./builder.sh</command> refers to the shell script shown
in <xref linkend='ex-hello-builder' />, discussed below.</para> in <xref linkend='ex-hello-builder' />, discussed below.</para>
</callout> </listitem>
<callout arearefs='ex-hello-nix-co-5'> <listitem>
<para>The builder has to know what the sources of the package <para>The builder has to know what the sources of the package
are. Here, the attribute <varname>src</varname> is bound to the are. Here, the attribute <varname>src</varname> is bound to the
@ -120,9 +118,9 @@ the single Nix expression in that directory
customary, and it's also expected by the default builder (which we customary, and it's also expected by the default builder (which we
don't use in this example).</para> don't use in this example).</para>
</callout> </listitem>
<callout arearefs='ex-hello-nix-co-6'> <listitem>
<para>Since the derivation requires Perl, we have to pass the <para>Since the derivation requires Perl, we have to pass the
value of the <varname>perl</varname> function argument to the value of the <varname>perl</varname> function argument to the
@ -139,9 +137,9 @@ perl = perl;</programlisting>
causes the specified attributes to be bound to whatever variables causes the specified attributes to be bound to whatever variables
with the same name happen to be in scope.</para> with the same name happen to be in scope.</para>
</callout> </listitem>
</calloutlist> </orderedlist>
</para> </para>

View file

@ -20,23 +20,21 @@ make install</programlisting>
The builders for almost all Unix packages look like this — set up some The builders for almost all Unix packages look like this — set up some
environment variables, unpack the sources, configure, build, and environment variables, unpack the sources, configure, build, and
install. For this reason the standard environment provides some Bash install. For this reason the standard environment provides some Bash
functions that automate the build process. A builder using the functions that automate the build process. Here is what a builder
generic build facilities in shown in <xref linkend='ex-hello-builder2' using the generic build facilities looks like:</para>
/>.</para>
<example xml:id='ex-hello-builder2'><title>Build script using the generic
build functions</title>
<programlisting> <programlisting>
buildInputs="$perl" <co xml:id='ex-hello-builder2-co-1' /> buildInputs="$perl" ①
source $stdenv/setup <co xml:id='ex-hello-builder2-co-2' /> source $stdenv/setup
genericBuild <co xml:id='ex-hello-builder2-co-3' /></programlisting> genericBuild ③</programlisting>
</example>
<calloutlist> <para>Here is what each line means:
<callout arearefs='ex-hello-builder2-co-1'> <orderedlist>
<listitem>
<para>The <literal>buildInputs</literal> variable tells <para>The <literal>buildInputs</literal> variable tells
<filename>setup</filename> to use the indicated packages as <filename>setup</filename> to use the indicated packages as
@ -54,16 +52,16 @@ genericBuild <co xml:id='ex-hello-builder2-co-3' /></programlisting>
inputs.</para></footnote> inputs.</para></footnote>
</para> </para>
</callout> </listitem>
<callout arearefs='ex-hello-builder2-co-2'> <listitem arearefs='ex-hello-builder2-co-2'>
<para>The function <function>genericBuild</function> is defined in <para>The function <function>genericBuild</function> is defined in
the file <literal>$stdenv/setup</literal>.</para> the file <literal>$stdenv/setup</literal>.</para>
</callout> </listitem>
<callout arearefs='ex-hello-builder2-co-3'> <listitem arearefs='ex-hello-builder2-co-3'>
<para>The final step calls the shell function <para>The final step calls the shell function
<function>genericBuild</function>, which performs the steps that <function>genericBuild</function>, which performs the steps that
@ -73,9 +71,11 @@ genericBuild <co xml:id='ex-hello-builder2-co-3' /></programlisting>
<command>bzip2</command>, etc. It can be customised in many ways; <command>bzip2</command>, etc. It can be customised in many ways;
see the Nixpkgs manual for details.</para> see the Nixpkgs manual for details.</para>
</callout> </listitem>
</calloutlist> </orderedlist>
</para>
<para>Discerning readers will note that the <para>Discerning readers will note that the
<literal>buildInputs</literal> could just as well have been set in the Nix <literal>buildInputs</literal> could just as well have been set in the Nix

View file

@ -278,7 +278,9 @@ evaluate to a Boolean value. If it evaluates to
<literal>true</literal>, <replaceable>e2</replaceable> is returned; <literal>true</literal>, <replaceable>e2</replaceable> is returned;
otherwise expression evaluation is aborted and a backtrace is printed.</para> otherwise expression evaluation is aborted and a backtrace is printed.</para>
<example xml:id='ex-subversion-nix'><title>Nix expression for Subversion</title> <para>Here is a Nix expression for the Subversion package that shows
how assertions can be used:.</para>
<programlisting> <programlisting>
{ localServer ? false { localServer ? false
, httpServer ? false , httpServer ? false
@ -290,9 +292,9 @@ otherwise expression evaluation is aborted and a backtrace is printed.</para>
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null , openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
}: }:
assert localServer -> db4 != null; <co xml:id='ex-subversion-nix-co-1' /> assert localServer -> db4 != null;
assert httpServer -> httpd != null &amp;&amp; httpd.expat == expat; <co xml:id='ex-subversion-nix-co-2' /> assert httpServer -> httpd != null &amp;&amp; httpd.expat == expat;
assert sslSupport -> openssl != null &amp;&amp; (httpServer -> httpd.openssl == openssl); <co xml:id='ex-subversion-nix-co-3' /> assert sslSupport -> openssl != null &amp;&amp; (httpServer -> httpd.openssl == openssl);
assert pythonBindings -> swig != null &amp;&amp; swig.pythonSupport; assert pythonBindings -> swig != null &amp;&amp; swig.pythonSupport;
assert javaSwigBindings -> swig != null &amp;&amp; swig.javaSupport; assert javaSwigBindings -> swig != null &amp;&amp; swig.javaSupport;
assert javahlBindings -> j2sdk != null; assert javahlBindings -> j2sdk != null;
@ -300,26 +302,24 @@ assert javahlBindings -> j2sdk != null;
stdenv.mkDerivation { stdenv.mkDerivation {
name = "subversion-1.1.1"; name = "subversion-1.1.1";
... ...
openssl = if sslSupport then openssl else null; <co xml:id='ex-subversion-nix-co-4' /> openssl = if sslSupport then openssl else null;
... ...
}</programlisting> }</programlisting>
</example>
<para><xref linkend='ex-subversion-nix' /> show how assertions are <para>The points of interest are:</para>
used in the Nix expression for Subversion.</para>
<calloutlist> <orderedlist>
<callout arearefs='ex-subversion-nix-co-1'> <listitem>
<para>This assertion states that if Subversion is to have support <para>This assertion states that if Subversion is to have support
for local repositories, then Berkeley DB is needed. So if the for local repositories, then Berkeley DB is needed. So if the
Subversion function is called with the Subversion function is called with the
<varname>localServer</varname> argument set to <varname>localServer</varname> argument set to
<literal>true</literal> but the <varname>db4</varname> argument <literal>true</literal> but the <varname>db4</varname> argument
set to <literal>null</literal>, then the evaluation fails.</para> set to <literal>null</literal>, then the evaluation fails.</para>
</callout> </listitem>
<callout arearefs='ex-subversion-nix-co-2'> <listitem>
<para>This is a more subtle condition: if Subversion is built with <para>This is a more subtle condition: if Subversion is built with
Apache (<literal>httpServer</literal>) support, then the Expat Apache (<literal>httpServer</literal>) support, then the Expat
library (an XML library) used by Subversion should be same as the library (an XML library) used by Subversion should be same as the
@ -327,27 +327,27 @@ used in the Nix expression for Subversion.</para>
Subversion code ends up being linked with Apache code, and if the Subversion code ends up being linked with Apache code, and if the
Expat libraries do not match, a build- or runtime link error or Expat libraries do not match, a build- or runtime link error or
incompatibility might occur.</para> incompatibility might occur.</para>
</callout> </listitem>
<callout arearefs='ex-subversion-nix-co-3'> <listitem>
<para>This assertion says that in order for Subversion to have SSL <para>This assertion says that in order for Subversion to have SSL
support (so that it can access <literal>https</literal> URLs), an support (so that it can access <literal>https</literal> URLs), an
OpenSSL library must be passed. Additionally, it says that OpenSSL library must be passed. Additionally, it says that
<emphasis>if</emphasis> Apache support is enabled, then Apache's <emphasis>if</emphasis> Apache support is enabled, then Apache's
OpenSSL should match Subversion's. (Note that if Apache support OpenSSL should match Subversion's. (Note that if Apache support
is not enabled, we don't care about Apache's OpenSSL.)</para> is not enabled, we don't care about Apache's OpenSSL.)</para>
</callout> </listitem>
<callout arearefs='ex-subversion-nix-co-4'> <listitem>
<para>The conditional here is not really related to assertions, <para>The conditional here is not really related to assertions,
but is worth pointing out: it ensures that if SSL support is but is worth pointing out: it ensures that if SSL support is
disabled, then the Subversion derivation is not dependent on disabled, then the Subversion derivation is not dependent on
OpenSSL, even if a non-<literal>null</literal> value was passed. OpenSSL, even if a non-<literal>null</literal> value was passed.
This prevents an unnecessary rebuild of Subversion if OpenSSL This prevents an unnecessary rebuild of Subversion if OpenSSL
changes.</para> changes.</para>
</callout> </listitem>
</calloutlist> </orderedlist>
</simplesect> </simplesect>

View file

@ -1,14 +1,21 @@
# Arguments and Variables # Arguments and Variables
The Nix expression in [???](#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 `pkgs/top-level/all-packages.nix`,
where all Nix expressions for packages are imported and called with the
appropriate arguments. Here are some fragments of `all-packages.nix`,
with annotations of what they mean:
... ...
rec { rec {
hello = import ../applications/misc/hello/ex-1 { hello = import ../applications/misc/hello/ex-1 {
inherit fetchurl stdenv perl; inherit fetchurl stdenv perl;
}; };
perl = import ../development/interpreters/perl { perl = import ../development/interpreters/perl {
inherit fetchurl stdenv; inherit fetchurl stdenv;
}; };
@ -20,20 +27,13 @@
} }
The Nix expression in [???](#ex-hello-nix) is a function; it is missing 1. This file defines a set of attributes, all of which are concrete
some arguments that have to be filled in somewhere. In the Nix Packages
collection this is done in the file `pkgs/top-level/all-packages.nix`,
where all Nix expressions for packages are imported and called with the
appropriate arguments. [example\_title](#ex-hello-composition) shows
some fragments of `all-packages.nix`.
- This file defines a set of attributes, all of which are concrete
derivations (i.e., not functions). In fact, we define a *mutually derivations (i.e., not functions). In fact, we define a *mutually
recursive* set of attributes. That is, the attributes can refer to recursive* set of attributes. That is, the attributes can refer to
each other. This is precisely what we want since we want to “plug” each other. This is precisely what we want since we want to “plug”
the various packages into each other. the various packages into each other.
- Here we *import* the Nix expression for GNU Hello. The import 2. Here we *import* the Nix expression for GNU Hello. The import
operation just loads and returns the specified Nix expression. In operation just loads and returns the specified Nix expression. In
fact, we could just have put the contents of [???](#ex-hello-nix) in fact, we could just have put the contents of [???](#ex-hello-nix) in
`all-packages.nix` at this point. That would be completely `all-packages.nix` at this point. That would be completely
@ -44,7 +44,7 @@ some fragments of `all-packages.nix`.
import a directory, Nix automatically appends `/default.nix` to the import a directory, Nix automatically appends `/default.nix` to the
file name. file name.
- This is where the actual composition takes place. Here we *call* the 3. This is where the actual composition takes place. Here we *call* the
function imported from `../applications/misc/hello/ex-1` with a set function imported from `../applications/misc/hello/ex-1` with a set
containing the things that the function expects, namely `fetchurl`, containing the things that the function expects, namely `fetchurl`,
`stdenv`, and `perl`. We use inherit again to use the attributes `stdenv`, and `perl`. We use inherit again to use the attributes
@ -68,5 +68,5 @@ some fragments of `all-packages.nix`.
> >
> hello = callPackage ../applications/misc/hello/ex-1 { stdenv = myStdenv; }; > hello = callPackage ../applications/misc/hello/ex-1 { stdenv = myStdenv; };
- Likewise, we have to instantiate Perl, `fetchurl`, and the standard 4. Likewise, we have to instantiate Perl, `fetchurl`, and the standard
environment. environment.

View file

@ -1,23 +1,23 @@
# Build Script # Build Script
source $stdenv/setup Here is the builder referenced from Hello's Nix expression (stored in
`pkgs/applications/misc/hello/ex-1/builder.sh`):
PATH=$perl/bin:$PATH source $stdenv/setup ①
tar xvfz $src PATH=$perl/bin:$PATH ②
tar xvfz $src ③
cd hello-* cd hello-*
./configure --prefix=$out ./configure --prefix=$out
make make
make install make install
[example\_title](#ex-hello-builder) shows the builder referenced from The builder can actually be made a lot shorter by using the *generic
Hello's Nix expression (stored in builder* functions provided by `stdenv`, but here we write out the build
`pkgs/applications/misc/hello/ex-1/builder.sh`). The builder can steps to elucidate what a builder does. It performs the following steps:
actually be made a lot shorter by using the *generic builder* functions
provided by `stdenv`, but here we write out the build steps to elucidate
what a builder does. It performs the following steps:
- When Nix runs a builder, it initially completely clears the 1. When Nix runs a builder, it initially completely clears the
environment (except for the attributes declared in the derivation). environment (except for the attributes declared in the derivation).
For instance, the `PATH` variable is empty\[1\]. This is done to For instance, the `PATH` variable is empty\[1\]. This is done to
prevent undeclared inputs from being used in the build process. If prevent undeclared inputs from being used in the build process. If
@ -31,13 +31,13 @@ what a builder does. It performs the following steps:
attribute in [???](#ex-hello-nix), but `mkDerivation` adds it attribute in [???](#ex-hello-nix), but `mkDerivation` adds it
automatically.) automatically.)
- Since Hello needs Perl, we have to make sure that Perl is in the 2. Since Hello needs Perl, we have to make sure that Perl is in the
`PATH`. The `perl` environment variable points to the location of `PATH`. The `perl` environment variable points to the location of
the Perl package (since it was passed in as an attribute to the the Perl package (since it was passed in as an attribute to the
derivation), so `$perl/bin` is the directory containing the Perl derivation), so `$perl/bin` is the directory containing the Perl
interpreter. interpreter.
- Now we have to unpack the sources. The `src` attribute was bound to 3. Now we have to unpack the sources. The `src` attribute was bound to
the result of fetching the Hello source tarball from the network, so the result of fetching the Hello source tarball from the network, so
the `src` environment variable points to the location in the Nix the `src` environment variable points to the location in the Nix
store to which the tarball was downloaded. After unpacking, we `cd` store to which the tarball was downloaded. After unpacking, we `cd`
@ -50,7 +50,7 @@ what a builder does. It performs the following steps:
have to worry about files from previous builds interfering with the have to worry about files from previous builds interfering with the
current build. current build.
- GNU Hello is a typical Autoconf-based package, so we first have to 4. GNU Hello is a typical Autoconf-based package, so we first have to
run its `configure` script. In Nix every package is stored in a run its `configure` script. In Nix every package is stored in a
separate location in the Nix store, for instance separate location in the Nix store, for instance
`/nix/store/9a54ba97fb71b65fda531012d0443ce2-hello-2.1.1`. Nix `/nix/store/9a54ba97fb71b65fda531012d0443ce2-hello-2.1.1`. Nix
@ -60,7 +60,7 @@ what a builder does. It performs the following steps:
`--prefix=$out` to cause Hello to be installed in the expected `--prefix=$out` to cause Hello to be installed in the expected
location. location.
- Finally we build Hello (`make`) and install it into the location 5. Finally we build Hello (`make`) and install it into the location
specified by `out` (`make install`). specified by `out` (`make install`).
If you are wondering about the absence of error checking on the result If you are wondering about the absence of error checking on the result

View file

@ -735,31 +735,7 @@ For instance, `derivation` is also available as `builtins.derivation`.
builder in a more structured format than plain environment builder in a more structured format than plain environment
variables. variables.
[example\_title](#ex-toxml) shows an example where this is the case. Here is an example where this is the case:
The builder is supposed to generate the configuration file for a
[Jetty servlet container](http://jetty.mortbay.org/). A servlet
container contains a number of servlets (`*.war` files) each
exported under a specific URI prefix. So the servlet configuration
is a list of sets containing the `path` and `war` of the servlet
([co\_title](#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 wouldnt work if fields are optional or contain lists
themselves). Instead the Nix expression is converted to an XML
representation with `toXML`, which is unambiguous and can easily be
processed with the appropriate tools. For instance, in the example
an XSLT stylesheet ([co\_title](#ex-toxml-co-stylesheet)) is applied
to it ([co\_title](#ex-toxml-co-apply)) to generate the XML
configuration file for the Jetty server. The XML representation
produced from [co\_title](#ex-toxml-co-servlets) by `toXML` is shown
in [example\_title](#ex-toxml-result).
Note that [example\_title](#ex-toxml) uses the `toFile` 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 `xsltproc
${stylesheet}
...`.
{ stdenv, fetchurl, libxslt, jira, uberwiki }: { stdenv, fetchurl, libxslt, jira, uberwiki }:
@ -771,10 +747,10 @@ For instance, `derivation` is also available as `builtins.derivation`.
builder = builtins.toFile "builder.sh" " builder = builtins.toFile "builder.sh" "
source $stdenv/setup source $stdenv/setup
mkdir $out mkdir $out
echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml
"; ";
stylesheet = builtins.toFile "stylesheet.xsl" stylesheet = builtins.toFile "stylesheet.xsl"
"<?xml version='1.0' encoding='UTF-8'?> "<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:template match='/'> <xsl:template match='/'>
@ -790,12 +766,29 @@ For instance, `derivation` is also available as `builtins.derivation`.
</xsl:stylesheet> </xsl:stylesheet>
"; ";
servlets = builtins.toXML [ servlets = builtins.toXML [
{ path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; } { path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; }
{ path = "/wiki"; war = uberwiki + "/uberwiki.war"; } { path = "/wiki"; war = uberwiki + "/uberwiki.war"; }
]; ];
}) })
The builder is supposed to generate the configuration file for a
[Jetty servlet container](http://jetty.mortbay.org/). A servlet
container contains a number of servlets (`*.war` files) each
exported under a specific URI prefix. So the servlet configuration
is a list of sets containing the `path` and `war` of the servlet
([???](#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 wouldnt work if fields are optional or contain lists
themselves). Instead the Nix expression is converted to an XML
representation with `toXML`, which is unambiguous and can easily be
processed with the appropriate tools. For instance, in the example
an XSLT stylesheet (at point ②) is applied to it (at point ①) to
generate the XML configuration file for the Jetty server. The XML
representation produced at point ③ by `toXML` is as follows:
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<expr> <expr>
<list> <list>
@ -818,6 +811,11 @@ For instance, `derivation` is also available as `builtins.derivation`.
</list> </list>
</expr> </expr>
Note that [???](#ex-toxml) uses the `toFile` built-in to write the
builder and the stylesheet “inline” in the Nix expression. The path
of the stylesheet is spliced into the builder using the syntax
`xsltproc ${stylesheet}`.
- `builtins.trace` e1 e2 - `builtins.trace` e1 e2
Evaluate e1 and print its abstract syntax representation on standard Evaluate e1 and print its abstract syntax representation on standard
error. Then return e2. This function is useful for debugging. error. Then return e2. This function is useful for debugging.

View file

@ -1,25 +1,26 @@
# Expression Syntax # Expression Syntax
{ stdenv, fetchurl, perl }: Here is a Nix expression for GNU Hello:
stdenv.mkDerivation { { stdenv, fetchurl, perl }: ①
name = "hello-2.1.1";
builder = ./builder.sh; stdenv.mkDerivation { ②
src = fetchurl { name = "hello-2.1.1"; ③
builder = ./builder.sh; ④
src = fetchurl { ⑤
url = "ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz"; url = "ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz";
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465"; sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
}; };
inherit perl; inherit perl;
} }
[example\_title](#ex-hello-nix) shows a Nix expression for GNU Hello. This file is actually already in the Nix Packages collection in
It's actually already in the Nix Packages collection in
`pkgs/applications/misc/hello/ex-1/default.nix`. It is customary to `pkgs/applications/misc/hello/ex-1/default.nix`. It is customary to
place each package in a separate directory and call the single Nix place each package in a separate directory and call the single Nix
expression in that directory `default.nix`. The file has the following expression in that directory `default.nix`. The file has the following
elements (referenced from the figure by number): elements (referenced from the figure by number):
- This states that the expression is a *function* that expects to be 1. This states that the expression is a *function* that expects to be
called with three arguments: `stdenv`, `fetchurl`, and `perl`. They called with three arguments: `stdenv`, `fetchurl`, and `perl`. They
are needed to build Hello, but we don't know how to build them here; are needed to build Hello, but we don't know how to build them here;
that's why they are function arguments. `stdenv` is a package that that's why they are function arguments. `stdenv` is a package that
@ -37,7 +38,7 @@ elements (referenced from the figure by number):
the required arguments, the body should describe how to build an the required arguments, the body should describe how to build an
instance of the Hello package. instance of the Hello package.
- So we have to build a package. Building something from other stuff 2. So we have to build a package. Building something from other stuff
is called a *derivation* in Nix (as opposed to sources, which are is called a *derivation* in Nix (as opposed to sources, which are
built by humans instead of computers). We perform a derivation by built by humans instead of computers). We perform a derivation by
calling `stdenv.mkDerivation`. `mkDerivation` is a function provided calling `stdenv.mkDerivation`. `mkDerivation` is a function provided
@ -50,13 +51,13 @@ elements (referenced from the figure by number):
nameN = nameN =
exprN; }`. exprN; }`.
- The attribute `name` specifies the symbolic name and version of the 3. The attribute `name` specifies the symbolic name and version of the
package. Nix doesn't really care about these things, but they are package. Nix doesn't really care about these things, but they are
used by for instance `nix-env used by for instance `nix-env
-q` to show a “human-readable” name for packages. This attribute is -q` to show a “human-readable” name for packages. This attribute is
required by `mkDerivation`. required by `mkDerivation`.
- The attribute `builder` specifies the builder. This attribute can 4. The attribute `builder` specifies the builder. This attribute can
sometimes be omitted, in which case `mkDerivation` will fill in a sometimes be omitted, in which case `mkDerivation` will fill in a
default builder (which does a `configure; make; make install`, in default builder (which does a `configure; make; make install`, in
essence). Hello is sufficiently simple that the default builder essence). Hello is sufficiently simple that the default builder
@ -64,7 +65,7 @@ elements (referenced from the figure by number):
educational purposes. The value `./builder.sh` refers to the shell educational purposes. The value `./builder.sh` refers to the shell
script shown in [???](#ex-hello-builder), discussed below. script shown in [???](#ex-hello-builder), discussed below.
- The builder has to know what the sources of the package are. Here, 5. The builder has to know what the sources of the package are. Here,
the attribute `src` is bound to the result of a call to the the attribute `src` is bound to the result of a call to the
`fetchurl` function. Given a URL and a SHA-256 hash of the expected `fetchurl` function. Given a URL and a SHA-256 hash of the expected
contents of the file at that URL, this function builds a derivation contents of the file at that URL, this function builds a derivation
@ -77,7 +78,7 @@ elements (referenced from the figure by number):
However, `src` is customary, and it's also expected by the default However, `src` is customary, and it's also expected by the default
builder (which we don't use in this example). builder (which we don't use in this example).
- Since the derivation requires Perl, we have to pass the value of the 6. Since the derivation requires Perl, we have to pass the value of the
`perl` function argument to the builder. All attributes in the set `perl` function argument to the builder. All attributes in the set
are actually passed as environment variables to the builder, so are actually passed as environment variables to the builder, so
declaring an attribute declaring an attribute

View file

@ -13,24 +13,26 @@ like this:
The builders for almost all Unix packages look like this — set up some The builders for almost all Unix packages look like this — set up some
environment variables, unpack the sources, configure, build, and environment variables, unpack the sources, configure, build, and
install. For this reason the standard environment provides some Bash install. For this reason the standard environment provides some Bash
functions that automate the build process. A builder using the generic functions that automate the build process. Here is what a builder using
build facilities in shown in [example\_title](#ex-hello-builder2). the generic build facilities looks like:
buildInputs="$perl" buildInputs="$perl"
source $stdenv/setup source $stdenv/setup
genericBuild genericBuild
- The `buildInputs` variable tells `setup` to use the indicated Here is what each line means:
1. The `buildInputs` variable tells `setup` to use the indicated
packages as “inputs”. This means that if a package provides a `bin` packages as “inputs”. This means that if a package provides a `bin`
subdirectory, it's added to `PATH`; if it has a `include` subdirectory, it's added to `PATH`; if it has a `include`
subdirectory, it's added to GCC's header search path; and so subdirectory, it's added to GCC's header search path; and so
on.\[1\] on.\[1\]
- The function `genericBuild` is defined in the file `$stdenv/setup`. 2. The function `genericBuild` is defined in the file `$stdenv/setup`.
- The final step calls the shell function `genericBuild`, which 3. The final step calls the shell function `genericBuild`, which
performs the steps that were done explicitly in performs the steps that were done explicitly in
[???](#ex-hello-builder). The generic builder is smart enough to [???](#ex-hello-builder). The generic builder is smart enough to
figure out whether to unpack the sources using `gzip`, `bzip2`, etc. figure out whether to unpack the sources using `gzip`, `bzip2`, etc.

View file

@ -203,6 +203,9 @@ where e1 is an expression that should evaluate to a Boolean value. If it
evaluates to `true`, e2 is returned; otherwise expression evaluation is evaluates to `true`, e2 is returned; otherwise expression evaluation is
aborted and a backtrace is printed. aborted and a backtrace is printed.
Here is a Nix expression for the Subversion package that shows how
assertions can be used:.
{ localServer ? false { localServer ? false
, httpServer ? false , httpServer ? false
, sslSupport ? false , sslSupport ? false
@ -213,9 +216,9 @@ aborted and a backtrace is printed.
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null , openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
}: }:
assert localServer -> db4 != null; assert localServer -> db4 != null;
assert httpServer -> httpd != null && httpd.expat == expat; assert httpServer -> httpd != null && httpd.expat == expat;
assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl);
assert pythonBindings -> swig != null && swig.pythonSupport; assert pythonBindings -> swig != null && swig.pythonSupport;
assert javaSwigBindings -> swig != null && swig.javaSupport; assert javaSwigBindings -> swig != null && swig.javaSupport;
assert javahlBindings -> j2sdk != null; assert javahlBindings -> j2sdk != null;
@ -223,33 +226,32 @@ aborted and a backtrace is printed.
stdenv.mkDerivation { stdenv.mkDerivation {
name = "subversion-1.1.1"; name = "subversion-1.1.1";
... ...
openssl = if sslSupport then openssl else null; openssl = if sslSupport then openssl else null;
... ...
} }
[example\_title](#ex-subversion-nix) show how assertions are used in the The points of interest are:
Nix expression for Subversion.
- This assertion states that if Subversion is to have support for 1. This assertion states that if Subversion is to have support for
local repositories, then Berkeley DB is needed. So if the Subversion local repositories, then Berkeley DB is needed. So if the Subversion
function is called with the `localServer` argument set to `true` but function is called with the `localServer` argument set to `true` but
the `db4` argument set to `null`, then the evaluation fails. the `db4` argument set to `null`, then the evaluation fails.
- This is a more subtle condition: if Subversion is built with Apache 2. This is a more subtle condition: if Subversion is built with Apache
(`httpServer`) support, then the Expat library (an XML library) used (`httpServer`) support, then the Expat library (an XML library) used
by Subversion should be same as the one used by Apache. This is by Subversion should be same as the one used by Apache. This is
because in this configuration Subversion code ends up being linked because in this configuration Subversion code ends up being linked
with Apache code, and if the Expat libraries do not match, a build- with Apache code, and if the Expat libraries do not match, a build-
or runtime link error or incompatibility might occur. or runtime link error or incompatibility might occur.
- This assertion says that in order for Subversion to have SSL support 3. This assertion says that in order for Subversion to have SSL support
(so that it can access `https` URLs), an OpenSSL library must be (so that it can access `https` URLs), an OpenSSL library must be
passed. Additionally, it says that *if* Apache support is enabled, passed. Additionally, it says that *if* Apache support is enabled,
then Apache's OpenSSL should match Subversion's. (Note that if then Apache's OpenSSL should match Subversion's. (Note that if
Apache support is not enabled, we don't care about Apache's Apache support is not enabled, we don't care about Apache's
OpenSSL.) OpenSSL.)
- The conditional here is not really related to assertions, but is 4. The conditional here is not really related to assertions, but is
worth pointing out: it ensures that if SSL support is disabled, then worth pointing out: it ensures that if SSL support is disabled, then
the Subversion derivation is not dependent on OpenSSL, even if a the Subversion derivation is not dependent on OpenSSL, even if a
non-`null` value was passed. This prevents an unnecessary rebuild of non-`null` value was passed. This prevents an unnecessary rebuild of