diff --git a/doc/manual/build-farm.xml b/doc/manual/build-farm.xml
index 2dd0932fc..b0d3fb8b6 100644
--- a/doc/manual/build-farm.xml
+++ b/doc/manual/build-farm.xml
@@ -9,7 +9,7 @@ build farm, since:
Nix supports distributed builds: a local Nix
installation can forward Nix builds to other machines over the
network. This allows multiple builds to be performed in parallel
- (thus improving performce), but more in importantly, it allows Nix
+ (thus improving performance), but more in importantly, it allows Nix
to perform multi-platform builds in a semi-transparent way. For
instance, if you perform a build for a
powerpc-darwin on an
@@ -38,8 +38,8 @@ build farm, since:
once.The results of a Nix build farm can be made
- available through a channel, so that users can use succesfull builds
- immediately.
+ available through a channel, so successful builds can be deployed to
+ users immediately.
diff --git a/doc/manual/writing-nix-expressions.xml b/doc/manual/writing-nix-expressions.xml
index eb366c249..b16d00b92 100644
--- a/doc/manual/writing-nix-expressions.xml
+++ b/doc/manual/writing-nix-expressions.xml
@@ -1,146 +1,221 @@
Writing Nix Expressions
+This chapter shows you how to write Nix expressions, which are
+the things that tell Nix how to build components. It starts with a
+simple example (a Nix expression for GNU Hello), and then moves
+on to a more in-depth look at the Nix expression language.
+
+
A simple Nix expression
-This section shows how to write simple Nix expressions — the
-things that describe how to build a package.
+This section shows how to add and test the GNU Hello
+package to the Nix Packages collection. Hello is a program
+that prints out the text Hello, world!.
+
+To add a component to the Nix Packages collection, you generally
+need to do three things:
+
+
+
+ Write a Nix expression for the component. This is a
+ file that describes all the inputs involved in building the
+ component, such as dependencies (other components required by the
+ component), sources, and so on.
+
+ Write a builder. This is a
+ shell scriptIn fact, it can be written in any
+ language, but typically it's a bash shell
+ script. that actually builds the component from
+ the inputs.
+
+ Add the component to the file
+ pkgs/system/all-packages-generic.nix. The Nix
+ expression written in the first step is a
+ function; it requires other components in order
+ to build it. In this step you put it all together, i.e., you call
+ the function with the right arguments to build the actual
+ component.
+
+
+
+
+
+
+The Nix expressionNix expression for GNU Hello
{stdenv, fetchurl, perl}:
-derivation {
+stdenv.mkDerivation {
name = "hello-2.1.1";
- system = stdenv.system;
- builder = ./builder.sh;
- src = fetchurl {
+ builder = ./builder.sh;
+ src = fetchurl {
url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
md5 = "70c9ccf9fac07f762c24f2df2290784d";
};
- stdenv = stdenv;
- perl = perl;
+ inherit perl;
}
-A simple Nix expression is shown in . It describes how to the build the GNU Hello
-package. This package has several dependencies. First, it
-requires a number of other packages, such as a C compiler, standard
-Unix shell tools, and Perl. Rather than have this Nix expression
-refer to and use specific versions of these packages, it should be
-generic; that is, it should be a function that
-takes the required packages as inputs and yield a build of the GNU
-Hello package as a result. This Nix expression defines a function
-with three arguments , namely:
+ shows a Nix expression for GNU
+Hello. It's 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):
-
- stdenv, which should be a
- standard environment package. The standard
- environment is a set of tools and other components that would be
- expected in a fairly minimal Unix-like environment: a C compiler
- and linker, Unix shell tools, and so on.
+
+
+
+
+ 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 component that is used
+ by almost all Nix Packages components; it provides a
+ standard environment consisting of the things you
+ would expect in a basic Unix environment: a C/C++ compiler (GCC,
+ to be precise), the Bash shell, fundamental Unix tools such as
+ cp, grep,
+ tar, etc. (See
+ pkgs/stdenv/nix/path.nix to see what's in
+ stdenv.) fetchurl is a
+ function that downloads files. perl is the
+ Perl interpreter.
+
+ Nix functions generally have the form {x, y, ...,
+ z}: e where x, y,
+ etc. are the names of the expected arguments, and where
+ e is the body of the function. So
+ here, the entire remainder of the file is the body of the
+ function; when given the required arguments, the body should
+ describe how to build an instance of the Hello component.
- fetchurl, which should be a
- function that given parameters url and
- md5, will fetch a file from the specified
- location and check that this file has the given MD5 hash code.
- The hash is required because build operations must be
- pure: given the same inputs they should
- always yield the same output. Since network resources can change
- at any time, we must in some way guarantee what the result will
- be.
-
- perl, which should be a Perl
- interpreter.
-
-
+
+
+
+
+ So we have to build a component. 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 by
+ stdenv that builds a component from a set of
+ attributes. An attribute set is just a list
+ of key/value pairs where the value is an arbitrary Nix expression.
+ They take the general form
+ {name1 =
+ expr1; ...
+ name1 =
+ expr1;.
+
+
+
+
+
+ The attribute name specifies the symbolic
+ name and version of the component. 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
+ components. This attribute is required by
+ mkDerivation.
+
+
+
+
+
+ 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
+ would suffice, but in this case, we will show an actual builder
+ for educational purposes. The value
+ ./builder.sh refers to the shell script shown
+ in , discussed below.
+
+
+
+
+
+ The builder has to know what the sources of the component
+ are. Here, the attribute src is bound to the
+ result of a call to the fetchurl function.
+ Given a URL and a MD5 hash of the expected contents of the file at
+ that URL, this function actually builds a derivation that
+ downloads the file and checks its hash. So the sources are a
+ dependency that like all other dependencies is built before Hello
+ itself is built.
+
+ Instead of src any other name could have
+ been used, and in fact there can be any number of sources (bound
+ to different attributes). 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 perl function argument to the
+ builder. All attributes in the set are actually passed as
+ environment variables to the builder, so declaring an attribute
+
+
+perl = perl;
+
+ will do the trink: it binds an attribute perl
+ to the function argument which also happens to be called
+ perl. However, it looks a bit silly, so there
+ is a shorter syntax. The inherit keyword
+ causes the specified attributes to be bound to whatever variables
+ with the same name happen to be in scope.
+
+
+
+
+
-The remainder of the file is the body of the function, which
-happens to be a derivation, which is the built-in function
-derivation applied to a set of attributes that
-encode all the necessary information for building the GNU Hello
-package.
+
-Build script (builder.sh) for GNU
-Hello
+
+The builder
+
+Build script for GNU Hello
-#! /bin/sh
+. $stdenv/setup
-buildinputs="$perl"
-. $stdenv/setup || exit 1
+PATH=$perl/bin:$PATH
-tar xvfz $src || exit 1
-cd hello-* || exit 1
-./configure --prefix=$out || exit 1
-make || exit 1
-make install || exit 1
+tar xvfz $src
+cd hello-*
+./configure --prefix=$out
+make
+make install
-
+ shows the builder referenced
+from Hello's Nix expression (stored in
+pkgs/applications/misc/hello/ex-1/builder.sh).
+TODO
-A more complex Nix expression
+If you are wondering about the absence of error checking on the
+result of various commands called in the builder: this is because the
+shell script is evaluated with Bash's option,
+which causes the script to be aborted if any command fails without an
+error check.
-Nix expression for Subversion
-
-{ localServer ? false
-, httpServer ? false
-, sslSupport ? false
-, swigBindings ? false
-, stdenv, fetchurl
-, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null
-}:
+
-assert !isNull expat;
-assert localServer -> !isNull db4;
-assert httpServer -> !isNull httpd && httpd.expat == expat;
-assert sslSupport -> !isNull openssl && (httpServer -> httpd.openssl == openssl);
-assert swigBindings -> !isNull swig;
-
-derivation {
- name = "subversion-0.32.1";
- system = stdenv.system;
-
- builder = ./builder.sh;
- src = fetchurl {
- url = http://svn.collab.net/tarballs/subversion-0.32.1.tar.gz;
- md5 = "b06717a8ef50db4b5c4d380af00bd901";
- };
-
- localServer = localServer;
- httpServer = httpServer;
- sslSupport = sslSupport;
- swigBindings = swigBindings;
-
- stdenv = stdenv;
- openssl = if sslSupport then openssl else null;
- httpd = if httpServer then httpd else null;
- expat = expat;
- db4 = if localServer then db4 else null;
- swig = if swigBindings then swig else null;
-}
-
-
-This example shows several features. Default parameters can be used to simplify call sites: if an
-argument that has a default is omitted, its default value is
-used.
-
-You can use assertions to test whether
-arguments satisfy certain constraints. The simple assertion tests whether the expat
-argument is not a null value. The more complex assertion says that if Subversion is built with
-Apache support, then httpd (the Apache package)
-must not be null and it must have been built using the same instance
-of the expat library as was passed to the
-Subversion expression. This is since the Subversion code is
-dynamically linked against the Apache code and they both use Expat,
-they must be linked against the same instance — otherwise a conflict
-might occur.