Writing Nix Expressions
A simple Nix expression
This section shows how to write simple Nix expressions — the
things that describe how to build a package.
Nix expression for GNU Hello
{stdenv, fetchurl, perl}:
derivation {
name = "hello-2.1.1";
system = stdenv.system;
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;
}
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:
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.
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.
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
#! /bin/sh
buildinputs="$perl"
. $stdenv/setup || exit 1
tar xvfz $src || exit 1
cd hello-* || exit 1
./configure --prefix=$out || exit 1
make || exit 1
make install || exit 1
A more complex Nix expression
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.