The standard build environment in the Nix Packages collection
provides an environment for building Unix packages that does a lot of
common build tasks automatically. In fact, for Unix packages that use
the standard ./configure; make; make install
build
interface, you don’t need to write a build script at all; the standard
environment does everything automatically. If
stdenv
doesn’t do what you need automatically, you
can easily customise or override the various build phases.
To build a package with the standard environment, you use the
function stdenv.mkDerivation
, instead of the
primitive built-in function derivation
, e.g.
stdenv.mkDerivation { name = "libfoo-1.2.3"; src = fetchurl { url = http://example.org/libfoo-1.2.3.tar.bz2; md5 = "e1ec107956b6ddcb0b8b0679367e9ac9"; }; }
(stdenv
needs to be in scope, so if you write this
in a separate Nix expression from
pkgs/all-packages.nix
, you need to pass it as a
function argument.) Specifying a name
and a
src
is the absolute minimum you need to do. Many
packages have dependencies that are not provided in the standard
environment. It’s usually sufficient to specify those dependencies in
the buildInputs
attribute:
stdenv.mkDerivation { name = "libfoo-1.2.3"; ... buildInputs = [libbar perl ncurses]; }
This attribute ensures that the bin
subdirectories of these packages appear in the PATH
environment variable during the build, that their
include
subdirectories are searched by the C
compiler, and so on. (See Section 3.6, “Package setup hooks” for
details.)
Often it is necessary to override or modify some aspect of the build. To make this easier, the standard environment breaks the package build into a number of phases, all of which can be overridden or modified individually: unpacking the sources, applying patches, configuring, building, and installing. (There are some others; see Section 3.4, “Phases”.) For instance, a package that doesn’t supply a makefile but instead has to be compiled “manually” could be handled like this:
stdenv.mkDerivation { name = "fnord-4.5"; ... buildPhase = '' gcc foo.c -o foo ''; installPhase = '' mkdir -p $out/bin cp foo $out/bin ''; }
(Note the use of ''
-style string literals, which
are very convenient for large multi-line script fragments because they
don’t need escaping of "
and \
,
and because indentation is intelligently removed.)
There are many other attributes to customise the build. These are listed in Section 3.3, “Attributes”.
While the standard environment provides a generic builder, you can still supply your own build script:
stdenv.mkDerivation { name = "libfoo-1.2.3"; ... builder = ./builder.sh; }
where the builder can do anything it wants, but typically starts with
source $stdenv/setup
to let stdenv
set up the environment (e.g., process
the buildInputs
). If you want, you can still use
stdenv
’s generic builder:
source $stdenv/setup buildPhase() { echo "... this is my custom build phase ..." gcc foo.c -o foo } installPhase() { mkdir -p $out/bin cp foo $out/bin } genericBuild