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 (<filename>builder.sh</filename>) 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.