git-subtree-dir: third_party/nix
git-subtree-mainline: cf8cd640c1
git-subtree-split: be66c7a6b24e3c3c6157fd37b86c7203d14acf10
		
	
			
		
			
				
	
	
		
			148 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
| <section xmlns="http://docbook.org/ns/docbook"
 | |
|       xmlns:xlink="http://www.w3.org/1999/xlink"
 | |
|       xmlns:xi="http://www.w3.org/2001/XInclude"
 | |
|       version="5.0"
 | |
|       xml:id='sec-expression-syntax'>
 | |
| 
 | |
| <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' />
 | |
| 
 | |
| 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' />
 | |
|     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' />
 | |
| }</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
 | |
| <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>
 | |
| 
 | |
|   <callout arearefs='ex-hello-nix-co-1'>
 | |
| 
 | |
|     <para>This states that the expression is a
 | |
|     <emphasis>function</emphasis> that expects to be called with three
 | |
|     arguments: <varname>stdenv</varname>, <varname>fetchurl</varname>,
 | |
|     and <varname>perl</varname>.  They are needed to build Hello, but
 | |
|     we don't know how to build them here; that's why they are function
 | |
|     arguments.  <varname>stdenv</varname> is a package that is used
 | |
|     by almost all Nix Packages packages; it provides a
 | |
|     <quote>standard</quote> 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
 | |
|     <command>cp</command>, <command>grep</command>,
 | |
|     <command>tar</command>, etc.  <varname>fetchurl</varname> is a
 | |
|     function that downloads files.  <varname>perl</varname> is the
 | |
|     Perl interpreter.</para>
 | |
| 
 | |
|     <para>Nix functions generally have the form <literal>{ x, y, ...,
 | |
|     z }: e</literal> where <varname>x</varname>, <varname>y</varname>,
 | |
|     etc. are the names of the expected arguments, and where
 | |
|     <replaceable>e</replaceable> 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 package.</para>
 | |
| 
 | |
|   </callout>
 | |
| 
 | |
|   <callout arearefs='ex-hello-nix-co-2'>
 | |
| 
 | |
|     <para>So we have to build a package.  Building something from
 | |
|     other stuff is called a <emphasis>derivation</emphasis> in Nix (as
 | |
|     opposed to sources, which are built by humans instead of
 | |
|     computers).  We perform a derivation by calling
 | |
|     <varname>stdenv.mkDerivation</varname>.
 | |
|     <varname>mkDerivation</varname> is a function provided by
 | |
|     <varname>stdenv</varname> that builds a package from a set of
 | |
|     <emphasis>attributes</emphasis>.  A set is just a list of
 | |
|     key/value pairs where each key is a string and each value is an
 | |
|     arbitrary Nix expression.  They take the general form <literal>{
 | |
|     <replaceable>name1</replaceable> =
 | |
|     <replaceable>expr1</replaceable>; <replaceable>...</replaceable>
 | |
|     <replaceable>nameN</replaceable> =
 | |
|     <replaceable>exprN</replaceable>; }</literal>.</para>
 | |
| 
 | |
|   </callout>
 | |
| 
 | |
|   <callout arearefs='ex-hello-nix-co-3'>
 | |
| 
 | |
|     <para>The attribute <varname>name</varname> specifies the symbolic
 | |
|     name and version of the package.  Nix doesn't really care about
 | |
|     these things, but they are used by for instance <command>nix-env
 | |
|     -q</command> to show a <quote>human-readable</quote> name for
 | |
|     packages.  This attribute is required by
 | |
|     <varname>mkDerivation</varname>.</para>
 | |
| 
 | |
|   </callout>
 | |
| 
 | |
|   <callout arearefs='ex-hello-nix-co-4'>
 | |
| 
 | |
|     <para>The attribute <varname>builder</varname> specifies the
 | |
|     builder.  This attribute can sometimes be omitted, in which case
 | |
|     <varname>mkDerivation</varname> will fill in a default builder
 | |
|     (which does a <literal>configure; make; make install</literal>, 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
 | |
|     <command>./builder.sh</command> refers to the shell script shown
 | |
|     in <xref linkend='ex-hello-builder' />, discussed below.</para>
 | |
| 
 | |
|   </callout>
 | |
| 
 | |
|   <callout arearefs='ex-hello-nix-co-5'>
 | |
| 
 | |
|     <para>The builder has to know what the sources of the package
 | |
|     are.  Here, the attribute <varname>src</varname> is bound to the
 | |
|     result of a call to the <command>fetchurl</command> function.
 | |
|     Given a URL and a SHA-256 hash of the expected contents of the file
 | |
|     at that URL, this function 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.</para>
 | |
| 
 | |
|     <para>Instead of <varname>src</varname> any other name could have
 | |
|     been used, and in fact there can be any number of sources (bound
 | |
|     to different attributes).  However, <varname>src</varname> is
 | |
|     customary, and it's also expected by the default builder (which we
 | |
|     don't use in this example).</para>
 | |
| 
 | |
|   </callout>
 | |
| 
 | |
|   <callout arearefs='ex-hello-nix-co-6'>
 | |
| 
 | |
|     <para>Since the derivation requires Perl, we have to pass the
 | |
|     value of the <varname>perl</varname> function argument to the
 | |
|     builder.  All attributes in the set are actually passed as
 | |
|     environment variables to the builder, so declaring an attribute
 | |
| 
 | |
|     <programlisting>
 | |
| perl = perl;</programlisting>
 | |
| 
 | |
|     will do the trick: it binds an attribute <varname>perl</varname>
 | |
|     to the function argument which also happens to be called
 | |
|     <varname>perl</varname>.  However, it looks a bit silly, so there
 | |
|     is a shorter syntax.  The <literal>inherit</literal> keyword
 | |
|     causes the specified attributes to be bound to whatever variables
 | |
|     with the same name happen to be in scope.</para>
 | |
| 
 | |
|   </callout>
 | |
| 
 | |
| </calloutlist>
 | |
| 
 | |
| </para>
 | |
| 
 | |
| </section>
 |