2014-08-27 19:41:09 +03:00
|
|
|
<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;
|
2017-07-15 22:06:30 +03:00
|
|
|
sha256 = "1md7jsfd8pa45z73bz1kszpp01yw6x5ljkjk2hx7wl800any6465";
|
2014-08-27 19:41:09 +03:00
|
|
|
};
|
|
|
|
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>
|