148 lines
		
	
	
		
			No EOL
		
	
	
		
			6.1 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			No EOL
		
	
	
		
			6.1 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;
 | 
						|
    md5 = "70c9ccf9fac07f762c24f2df2290784d";
 | 
						|
  };
 | 
						|
  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 an MD5 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> |