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>
<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>
...
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;
};
perl = import ../development/interpreters/perl { <co xml:id='ex-hello-composition-co-4' />
perl = import ../development/interpreters/perl {
inherit fetchurl stdenv;
};
@ -31,31 +36,19 @@ rec { <co xml:id='ex-hello-composition-co-1' />
}
</programlisting>
</example>
<para>The Nix expression in <xref linkend='ex-hello-nix' /> is a
function; it is missing some arguments that have to be filled in
somewhere. In the Nix Packages collection this is done in the file
<filename>pkgs/top-level/all-packages.nix</filename>, where all
Nix expressions for packages are imported and called with the
appropriate arguments. <xref linkend='ex-hello-composition' /> shows
some fragments of
<filename>all-packages.nix</filename>.</para>
<calloutlist>
<callout arearefs='ex-hello-composition-co-1'>
<orderedlist>
<listitem>
<para>This file defines a set of attributes, all of which are
concrete derivations (i.e., not functions). In fact, we define a
<emphasis>mutually recursive</emphasis> set of attributes. That
is, the attributes can refer to each other. This is precisely
what we want since we want to <quote>plug</quote> the
various packages into each other.</para>
</listitem>
</callout>
<callout arearefs='ex-hello-composition-co-2'>
<listitem>
<para>Here we <emphasis>import</emphasis> the Nix expression for
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
<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
<emphasis>call</emphasis> the function imported from
@ -107,15 +100,15 @@ hello = callPackage ../applications/misc/hello/ex-1 { stdenv = myStdenv; };
</para></note>
</callout>
</listitem>
<callout arearefs='ex-hello-composition-co-4'>
<listitem>
<para>Likewise, we have to instantiate Perl,
<varname>fetchurl</varname>, and the standard environment.</para>
</callout>
</listitem>
</calloutlist>
</orderedlist>
</section>

View file

@ -6,32 +6,30 @@
<title>Build Script</title>
<example xml:id='ex-hello-builder'><title>Build script for GNU Hello
(<filename>builder.sh</filename>)</title>
<programlisting>
source $stdenv/setup <co xml:id='ex-hello-builder-co-1' />
PATH=$perl/bin:$PATH <co xml:id='ex-hello-builder-co-2' />
tar xvfz $src <co xml:id='ex-hello-builder-co-3' />
cd hello-*
./configure --prefix=$out <co xml:id='ex-hello-builder-co-4' />
make <co xml:id='ex-hello-builder-co-5' />
make install</programlisting>
</example>
<para><xref linkend='ex-hello-builder' /> shows the builder referenced
<para>Here is the builder referenced
from Hello's Nix expression (stored in
<filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>).
The builder can actually be made a lot shorter by using the
<filename>pkgs/applications/misc/hello/ex-1/builder.sh</filename>):</para>
<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
<varname>stdenv</varname>, but here we write out the build steps to
elucidate what a builder does. It performs the following
steps:</para>
<calloutlist>
<orderedlist>
<callout arearefs='ex-hello-builder-co-1'>
<listitem>
<para>When Nix runs a builder, it initially completely clears the
environment (except for the attributes declared in the
@ -52,9 +50,9 @@ steps:</para>
attribute in <xref linkend='ex-hello-nix' />, but
<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
the <literal>PATH</literal>. The <literal>perl</literal> environment
@ -63,9 +61,9 @@ steps:</para>
<filename><replaceable>$perl</replaceable>/bin</filename> is the
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
<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
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
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
the expected location.</para>
</callout>
</listitem>
<callout arearefs='ex-hello-builder-co-5'>
<listitem>
<para>Finally we build Hello (<literal>make</literal>) and install
it into the location specified by <literal>out</literal>
(<literal>make install</literal>).</para>
</callout>
</listitem>
</calloutlist>
</orderedlist>
<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

View file

@ -1511,39 +1511,9 @@ in foo</programlisting>
<!-- TODO: more formally describe the schema of the XML
representation -->
<para><xref linkend='ex-toxml' /> shows an example where this is
the case. The builder is supposed to generate the configuration
file for a <link xlink:href='http://jetty.mortbay.org/'>Jetty
servlet container</link>. A servlet container contains a number
of servlets (<filename>*.war</filename> files) each exported under
a specific URI prefix. So the servlet configuration is a list of
sets containing the <varname>path</varname> and
<varname>war</varname> of the servlet (<xref
linkend='ex-toxml-co-servlets' />). This kind of information is
difficult to communicate with the normal method of passing
information through an environment variable, which just
concatenates everything together into a string (which might just
work in this case, but 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>
<para>Here is an example where this is
the case:
</para>
<programlisting><![CDATA[
{ stdenv, fetchurl, libxslt, jira, uberwiki }:
@ -1556,10 +1526,10 @@ stdenv.mkDerivation (rec {
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[
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'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:template match='/'>
@ -1575,16 +1545,32 @@ stdenv.mkDerivation (rec {
</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 = "/wiki"; war = uberwiki + "/uberwiki.war"; }
];
})]]></programlisting>
</example>
<example xml:id='ex-toxml-result'><title>XML representation produced by
<function>toXML</function></title>
<para>The builder is supposed to generate the configuration file
for a <link xlink:href='http://jetty.mortbay.org/'>Jetty servlet
container</link>. A servlet container contains a number of
servlets (<filename>*.war</filename> files) each exported under a
specific URI prefix. So the servlet configuration is a list of
sets containing the <varname>path</varname> and
<varname>war</varname> of the servlet (<xref
linkend='ex-toxml-co-servlets' />). This kind of information is
difficult to communicate with the normal method of passing
information through an environment variable, which just
concatenates everything together into a string (which might just
work in this case, but 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'?>
<expr>
@ -1608,7 +1594,11 @@ stdenv.mkDerivation (rec {
</list>
</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>

View file

@ -6,33 +6,31 @@
<title>Expression Syntax</title>
<example xml:id='ex-hello-nix'><title>Nix expression for GNU Hello
(<filename>default.nix</filename>)</title>
<programlisting>
{ stdenv, fetchurl, perl }: <co xml:id='ex-hello-nix-co-1' />
<para>Here is a Nix expression for GNU Hello:</para>
stdenv.mkDerivation { <co xml:id='ex-hello-nix-co-2' />
name = "hello-2.1.1"; <co xml:id='ex-hello-nix-co-3' />
builder = ./builder.sh; <co xml:id='ex-hello-nix-co-4' />
src = fetchurl { <co xml:id='ex-hello-nix-co-5' />
<programlisting>
{ stdenv, fetchurl, perl }: ①
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";
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
};
inherit perl; <co xml:id='ex-hello-nix-co-6' />
inherit perl;
}</programlisting>
</example>
<para><xref linkend='ex-hello-nix' /> shows a Nix expression for GNU
Hello. It's actually already in the Nix Packages collection in
<para>This file is actually already in the Nix Packages collection in
<filename>pkgs/applications/misc/hello/ex-1/default.nix</filename>.
It is customary to place each package in a separate directory and call
the single Nix expression in that directory
<filename>default.nix</filename>. The file has the following elements
(referenced from the figure by number):
<calloutlist>
<orderedlist>
<callout arearefs='ex-hello-nix-co-1'>
<listitem>
<para>This states that the expression is a
<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
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
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>exprN</replaceable>; }</literal>.</para>
</callout>
</listitem>
<callout arearefs='ex-hello-nix-co-3'>
<listitem>
<para>The attribute <varname>name</varname> specifies the symbolic
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
<varname>mkDerivation</varname>.</para>
</callout>
</listitem>
<callout arearefs='ex-hello-nix-co-4'>
<listitem>
<para>The attribute <varname>builder</varname> specifies the
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
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
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
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
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
with the same name happen to be in scope.</para>
</callout>
</listitem>
</calloutlist>
</orderedlist>
</para>

View file

@ -20,23 +20,21 @@ make install</programlisting>
The builders for almost all Unix packages look like this — set up some
environment variables, unpack the sources, configure, build, and
install. For this reason the standard environment provides some Bash
functions that automate the build process. A builder using the
generic build facilities in shown in <xref linkend='ex-hello-builder2'
/>.</para>
functions that automate the build process. Here is what a builder
using the generic build facilities looks like:</para>
<example xml:id='ex-hello-builder2'><title>Build script using the generic
build functions</title>
<programlisting>
buildInputs="$perl" <co xml:id='ex-hello-builder2-co-1' />
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>
</example>
genericBuild ③</programlisting>
<calloutlist>
<para>Here is what each line means:
<callout arearefs='ex-hello-builder2-co-1'>
<orderedlist>
<listitem>
<para>The <literal>buildInputs</literal> variable tells
<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>
</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
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
<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;
see the Nixpkgs manual for details.</para>
</callout>
</listitem>
</calloutlist>
</orderedlist>
</para>
<para>Discerning readers will note that the
<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;
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>
{ localServer ? 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
}:
assert localServer -> db4 != null; <co xml:id='ex-subversion-nix-co-1' />
assert httpServer -> httpd != null &amp;&amp; httpd.expat == expat; <co xml:id='ex-subversion-nix-co-2' />
assert sslSupport -> openssl != null &amp;&amp; (httpServer -> httpd.openssl == openssl); <co xml:id='ex-subversion-nix-co-3' />
assert localServer -> db4 != null;
assert httpServer -> httpd != null &amp;&amp; httpd.expat == expat;
assert sslSupport -> openssl != null &amp;&amp; (httpServer -> httpd.openssl == openssl);
assert pythonBindings -> swig != null &amp;&amp; swig.pythonSupport;
assert javaSwigBindings -> swig != null &amp;&amp; swig.javaSupport;
assert javahlBindings -> j2sdk != null;
@ -300,26 +302,24 @@ assert javahlBindings -> j2sdk != null;
stdenv.mkDerivation {
name = "subversion-1.1.1";
...
openssl = if sslSupport then openssl else null; <co xml:id='ex-subversion-nix-co-4' />
openssl = if sslSupport then openssl else null;
...
}</programlisting>
</example>
<para><xref linkend='ex-subversion-nix' /> show how assertions are
used in the Nix expression for Subversion.</para>
<para>The points of interest are:</para>
<calloutlist>
<orderedlist>
<callout arearefs='ex-subversion-nix-co-1'>
<listitem>
<para>This assertion states that if Subversion is to have support
for local repositories, then Berkeley DB is needed. So if the
Subversion function is called with the
<varname>localServer</varname> argument set to
<literal>true</literal> but the <varname>db4</varname> argument
set to <literal>null</literal>, then the evaluation fails.</para>
</callout>
</listitem>
<callout arearefs='ex-subversion-nix-co-2'>
<listitem>
<para>This is a more subtle condition: if Subversion is built with
Apache (<literal>httpServer</literal>) support, then the Expat
library (an XML library) used by Subversion should be same as the
@ -327,27 +327,27 @@ used in the Nix expression for Subversion.</para>
Subversion code ends up being linked with Apache code, and if the
Expat libraries do not match, a build- or runtime link error or
incompatibility might occur.</para>
</callout>
</listitem>
<callout arearefs='ex-subversion-nix-co-3'>
<listitem>
<para>This assertion says that in order for Subversion to have SSL
support (so that it can access <literal>https</literal> URLs), an
OpenSSL library must be passed. Additionally, it says that
<emphasis>if</emphasis> Apache support is enabled, then Apache's
OpenSSL should match Subversion's. (Note that if Apache support
is not enabled, we don't care about Apache's OpenSSL.)</para>
</callout>
</listitem>
<callout arearefs='ex-subversion-nix-co-4'>
<listitem>
<para>The conditional here is not really related to assertions,
but is worth pointing out: it ensures that if SSL support is
disabled, then the Subversion derivation is not dependent on
OpenSSL, even if a non-<literal>null</literal> value was passed.
This prevents an unnecessary rebuild of Subversion if OpenSSL
changes.</para>
</callout>
</listitem>
</calloutlist>
</orderedlist>
</simplesect>

View file

@ -1,14 +1,21 @@
# 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;
};
perl = import ../development/interpreters/perl {
perl = import ../development/interpreters/perl {
inherit fetchurl stdenv;
};
@ -20,20 +27,13 @@
}
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. [example\_title](#ex-hello-composition) shows
some fragments of `all-packages.nix`.
- This file defines a set of attributes, all of which are concrete
1. This file defines a set of attributes, all of which are concrete
derivations (i.e., not functions). In fact, we define a *mutually
recursive* set of attributes. That is, the attributes can refer to
each other. This is precisely what we want since we want to “plug”
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
fact, we could just have put the contents of [???](#ex-hello-nix) in
`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
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
containing the things that the function expects, namely `fetchurl`,
`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; };
- Likewise, we have to instantiate Perl, `fetchurl`, and the standard
4. Likewise, we have to instantiate Perl, `fetchurl`, and the standard
environment.

View file

@ -1,23 +1,23 @@
# 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-*
./configure --prefix=$out
make
./configure --prefix=$out
make
make install
[example\_title](#ex-hello-builder) shows the builder referenced from
Hello's Nix expression (stored in
`pkgs/applications/misc/hello/ex-1/builder.sh`). The builder can
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:
The builder can 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).
For instance, the `PATH` variable is empty\[1\]. This is done to
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
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
the Perl package (since it was passed in as an attribute to the
derivation), so `$perl/bin` is the directory containing the Perl
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 `src` environment variable points to the location in the Nix
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
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
separate location in the Nix store, for instance
`/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
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`).
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
variables.
[example\_title](#ex-toxml) shows 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}
...`.
Here is an example where this is the case:
{ stdenv, fetchurl, libxslt, jira, uberwiki }:
@ -771,10 +747,10 @@ For instance, `derivation` is also available as `builtins.derivation`.
builder = builtins.toFile "builder.sh" "
source $stdenv/setup
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'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:template match='/'>
@ -790,12 +766,29 @@ For instance, `derivation` is also available as `builtins.derivation`.
</xsl:stylesheet>
";
servlets = builtins.toXML [
servlets = builtins.toXML [
{ path = "/bugtracker"; war = jira + "/lib/atlassian-jira.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'?>
<expr>
<list>
@ -818,6 +811,11 @@ For instance, `derivation` is also available as `builtins.derivation`.
</list>
</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
Evaluate e1 and print its abstract syntax representation on standard
error. Then return e2. This function is useful for debugging.

View file

@ -1,25 +1,26 @@
# Expression Syntax
{ stdenv, fetchurl, perl }:
Here is a Nix expression for GNU Hello:
stdenv.mkDerivation {
name = "hello-2.1.1";
builder = ./builder.sh;
src = fetchurl {
{ stdenv, fetchurl, perl }: ①
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";
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
};
inherit perl;
inherit perl;
}
[example\_title](#ex-hello-nix) shows a Nix expression for GNU Hello.
It's actually already in the Nix Packages collection in
This file is actually already in the Nix Packages collection in
`pkgs/applications/misc/hello/ex-1/default.nix`. It is customary to
place each package in a separate directory and call the single Nix
expression in that directory `default.nix`. The file has the following
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
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
@ -37,7 +38,7 @@ elements (referenced from the figure by number):
the required arguments, the body should describe how to build an
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
built by humans instead of computers). We perform a derivation by
calling `stdenv.mkDerivation`. `mkDerivation` is a function provided
@ -50,13 +51,13 @@ elements (referenced from the figure by number):
nameN =
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
used by for instance `nix-env
-q` to show a “human-readable” name for packages. This attribute is
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
default builder (which does a `configure; make; make install`, in
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
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
`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
@ -77,7 +78,7 @@ elements (referenced from the figure by number):
However, `src` is customary, and it's also expected by the default
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
are actually passed as environment variables to the builder, so
declaring an attribute

View file

@ -13,24 +13,26 @@ like this:
The builders for almost all Unix packages look like this — set up some
environment variables, unpack the sources, configure, build, and
install. For this reason the standard environment provides some Bash
functions that automate the build process. A builder using the generic
build facilities in shown in [example\_title](#ex-hello-builder2).
functions that automate the build process. Here is what a builder using
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`
subdirectory, it's added to `PATH`; if it has a `include`
subdirectory, it's added to GCC's header search path; and so
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
[???](#ex-hello-builder). The generic builder is smart enough to
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
aborted and a backtrace is printed.
Here is a Nix expression for the Subversion package that shows how
assertions can be used:.
{ localServer ? false
, httpServer ? false
, sslSupport ? false
@ -213,9 +216,9 @@ aborted and a backtrace is printed.
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
}:
assert localServer -> db4 != null;
assert httpServer -> httpd != null && httpd.expat == expat;
assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl);
assert localServer -> db4 != null;
assert httpServer -> httpd != null && httpd.expat == expat;
assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl);
assert pythonBindings -> swig != null && swig.pythonSupport;
assert javaSwigBindings -> swig != null && swig.javaSupport;
assert javahlBindings -> j2sdk != null;
@ -223,33 +226,32 @@ aborted and a backtrace is printed.
stdenv.mkDerivation {
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
Nix expression for Subversion.
The points of interest are:
- 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
function is called with the `localServer` argument set to `true` but
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
by Subversion should be same as the one used by Apache. This is
because in this configuration Subversion code ends up being linked
with Apache code, and if the Expat libraries do not match, a build-
or runtime link error or incompatibility might occur.
- 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
passed. Additionally, it says that *if* Apache support is enabled,
then Apache's OpenSSL should match Subversion's. (Note that if
Apache support is not enabled, we don't care about Apache's
OpenSSL.)
- 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
the Subversion derivation is not dependent on OpenSSL, even if a
non-`null` value was passed. This prevents an unnecessary rebuild of