148 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
| <chapter id='chap-writing-nix-expressions'><title>Writing Nix Expressions</title>
 | |
| 
 | |
| <sect1><title>A simple Nix expression</title>
 | |
| 
 | |
| <para>This section shows how to write simple Nix expressions—the
 | |
| things that describe how to build a package.</para>
 | |
| 
 | |
| <example id='ex-hello-nix'><title>Nix expression for GNU Hello</title>
 | |
| <programlisting>
 | |
| {stdenv, fetchurl, perl}: <co id='ex-hello-nix-co-1' />
 | |
| 
 | |
| derivation { <co id='ex-hello-nix-co-2' />
 | |
|   name = "hello-2.1.1"; <co id='ex-hello-nix-co-3' />
 | |
|   system = stdenv.system; <co id='ex-hello-nix-co-4' />
 | |
|   builder = ./builder.sh; <co id='ex-hello-nix-co-5' />
 | |
|   src = fetchurl { <co id='ex-hello-nix-co-6' />
 | |
|     url = ftp://ftp.nluug.nl/pub/gnu/hello/hello-2.1.1.tar.gz;
 | |
|     md5 = "70c9ccf9fac07f762c24f2df2290784d";
 | |
|   };
 | |
|   stdenv = stdenv; <co id='ex-hello-nix-co-7' />
 | |
|   perl = perl;
 | |
| }</programlisting>
 | |
| </example>
 | |
| 
 | |
| <para>A simple Nix expression is shown in <xref linkend='ex-hello-nix'
 | |
| />. It describes how to the build the <ulink
 | |
| url='http://www.gnu.org/directory/GNU/hello.html'>GNU Hello
 | |
| package</ulink>.  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 <emphasis>function</emphasis> 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 <xref linkend='ex-hello-nix-co-1' />, namely:
 | |
| 
 | |
|   <orderedlist>
 | |
|     <listitem><para><varname>stdenv</varname>, which should be a
 | |
|     <emphasis>standard environment package</emphasis>.  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.</para></listitem>
 | |
|     
 | |
|     <listitem><para><varname>fetchurl</varname>, which should be a
 | |
|     function that given parameters <varname>url</varname> and
 | |
|     <varname>md5</varname>, 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
 | |
|     <emphasis>pure</emphasis>: 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.</para></listitem>
 | |
|     
 | |
|     <listitem><para><varname>perl</varname>, which should be a Perl
 | |
|     interpreter.</para></listitem>
 | |
|     
 | |
|   </orderedlist>
 | |
| </para>
 | |
| 
 | |
| <para>The remainder of the file is the body of the function, which
 | |
| happens to be a <emphasis>derivation</emphasis> <xref
 | |
| linkend='ex-hello-nix-co-2' />, which is the built-in function
 | |
| <varname>derivation</varname> applied to a set of attributes that
 | |
| encode all the necessary information for building the GNU Hello
 | |
| package.</para>
 | |
| 
 | |
| <example><title>Build script (<filename>builder.sh</filename>) for GNU
 | |
| Hello</title>
 | |
| <programlisting>
 | |
| #! /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</programlisting>
 | |
| </example>
 | |
| 
 | |
| </sect1>
 | |
| 
 | |
| 
 | |
| <sect1><title>A more complex Nix expression</title>
 | |
| 
 | |
| <example id='ex-svn-nix'><title>Nix expression for Subversion</title>
 | |
| <programlisting>
 | |
| { localServer ? false <co id='ex-svn-nix-co-1' />
 | |
| , httpServer ? false
 | |
| , sslSupport ? false
 | |
| , swigBindings ? false
 | |
| , stdenv, fetchurl
 | |
| , openssl ? null, httpd ? null, db4 ? null, expat, swig ? null
 | |
| }:
 | |
| 
 | |
| assert !isNull expat; <co id='ex-svn-nix-co-2' />
 | |
| assert localServer -> !isNull db4;
 | |
| assert httpServer -> !isNull httpd && httpd.expat == expat; <co id='ex-svn-nix-co-3' />
 | |
| 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; <co id='ex-svn-nix-co-4' />
 | |
|   httpd = if httpServer then httpd else null;
 | |
|   expat = expat;
 | |
|   db4 = if localServer then db4 else null;
 | |
|   swig = if swigBindings then swig else null;
 | |
| }</programlisting>
 | |
| </example>
 | |
| 
 | |
| <para>This example shows several features.  Default parameters <xref
 | |
| linkend='ex-svn-nix-co-1'/> can be used to simplify call sites: if an
 | |
| argument that has a default is omitted, its default value is
 | |
| used.</para>
 | |
| 
 | |
| <para>You can use <emphasis>assertions</emphasis> to test whether
 | |
| arguments satisfy certain constraints.  The simple assertion <xref
 | |
| linkend='ex-svn-nix-co-2'/> tests whether the <varname>expat</varname>
 | |
| argument is not a null value.  The more complex assertion <xref
 | |
| linkend='ex-svn-nix-co-3'/> says that if Subversion is built with
 | |
| Apache support, then <varname>httpd</varname> (the Apache package)
 | |
| must not be null and it must have been built using the same instance
 | |
| of the <varname>expat</varname> 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.</para>
 | |
| 
 | |
| </sect1>
 | |
| 
 | |
| 
 | |
| </chapter>
 |