The Standard Environment The standard build environment in the Nix Packages collection provides a 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.
Using <literal>stdenv</literal> 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 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 overriden or modified individually: unpacking the sources, applying patches, configuring, building, and installing. (There are some others; see .) 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 = '' ensureDir $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 . 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() { ensureDir $out/bin cp foo $out/bin } genericBuild
Tools provided by <literal>stdenv</literal> The standard environment provides the following packages: The GNU C Compiler, configured with C and C++ support. GNU coreutils (contains a few dozen standard Unix commands). GNU findutils (contains find). GNU diffutils (contains diff, cmp). GNU sed. GNU grep. GNU awk. GNU tar. gzip and bzip2. GNU Make. It has been patched to provide nested output that can be fed into the nix-log2xml command and log2html stylesheet to create a structured, readable output of the build steps performed by Make. Bash. This is the shell used for all builders in the Nix Packages collection. Not using /bin/sh removes a large source of portability problems. The patch command. On Linux, stdenv also includes the patchelf utility.
Phases The generic builder has a number of phases. Each phase can be overriden in its entirety either by setting the environment variable namePhase to a string containing some shell commands to be executed, or by redefining the shell function namePhase. The former is convenient to override a phase from the derivation, while the latter is convenient from a build script.
Controlling phases There are a number of variables that control what phases are executed and in what order: Variables affecting phase control phases Specifies the phases. You can change the order in which phases are executed, or add new phases, by setting this variable. If it’s not set, the default value is used, which is $prePhases unpackPhase patchPhase $preConfigurePhases configurePhase $preBuildPhases buildPhase checkPhase $preInstallPhases installPhase fixupPhase $preDistPhases distPhase $postPhases. Usually, if you just want to add a few phases, it’s more convenient to set one of the variables below (such as preInstallPhases), as you then don’t specify all the normal phases. prePhases Additional phases executed before any of the default phases. preConfigurePhases Additional phases executed just before the configure phase. preBuildPhases Additional phases executed just before the build phase. preInstallPhases Additional phases executed just before the install phase. preDistPhases Additional phases executed just before the distribution phase. postPhases Additional phases executed after any of the default phases.
The unpack phase The unpack phase is responsible for unpacking the source code of the package. The default implementation of unpackPhase unpacks the source files listed in the src environment variable to the current directory. It supports the following files by default: Tar files These can optionally be compressed using gzip (.tar.gz, .tgz or .tar.Z) or bzip2 (.tar.bz2 or .tbz2). Zip files Zip files are unpacked using unzip. However, unzip is not in the standard environment, so you should add it to buildInputs yourself. Directories in the Nix store These are simply copied to the current directory. The hash part of the file name is stripped, e.g. /nix/store/1wydxgby13cz...-my-sources would be copied to my-sources. Additional file types can be supported by setting the unpackCmd variable (see below). Variables controlling the unpack phase srcs / src The list of source files or directories to be unpacked or copied. One of these must be set. sourceRoot After running unpackPhase, the generic builder changes the current directory to the directory created by unpacking the sources. If there are multiple source directories, you should set sourceRoot to the name of the intended directory. setSourceRoot Alternatively to setting sourceRoot, you can set setSourceRoot to a shell command to be evaluated by the unpack phase after the sources have been unpacked. This command must set sourceRoot. preUnpack Hook executed at the start of the unpack phase. postUnpack Hook executed at the end of the unpack phase. dontMakeSourcesWritable If set to 1, the unpacked sources are not made writable. By default, they are made writable to prevent problems with read-only sources. For example, copied store directories would be read-only without this. unpackCmd The unpack phase evaluates the string $unpackCmd for any unrecognised file. The path to the current source file is contained in the curSrc variable.
The patch phase The patch phase applies the list of patches defined in the patches variable. Variables controlling the patch phase patches The list of patches. They must be in the format accepted by the patch command, and may optionally be compressed using gzip (.gz) or bzip2 (.bz2). patchFlags Flags to be passed to patch. If not set, the argument is used, which causes the leading directory component to be stripped from the file names in each patch. prePatch Hook executed at the start of the patch phase. postPatch Hook executed at the end of the patch phase.
The configure phase The configure phase prepares the source tree for building. The default unpackPhase runs ./configure (typically an Autoconf-generated script) if it exists. Variables controlling the configure phase configureScript The name of the configure script. It defaults to ./configure if it exists; otherwise, the configure phase is skipped. This can actually be a command (like perl ./Configure.pl). configureFlags Additional arguments passed to the configure script. configureFlagsArray A shell array containing additional arguments passed to the configure script. You must use this instead of configureFlags if the arguments contain spaces. dontAddPrefix By default, the flag --prefix=$prefix is added to the configure flags. If this is undesirable, set this variable to a non-empty value. prefix The prefix under which the package must be installed, passed via the option to the configure script. It defaults to . dontAddDisableDepTrack By default, the flag --disable-dependency-tracking is added to the configure flags to speed up Automake-based builds. If this is undesirable, set this variable to a non-empty value. dontFixLibtool By default, the configure phase applies some special hackery to all files called ltmain.sh before running the configure script in order to improve the purity of Libtool-based packagesIt clears the sys_lib_*search_path variables in the Libtool script to prevent Libtool from using libraries in /usr/lib and such.. If this is undesirable, set this variable to a non-empty value. preConfigure Hook executed at the start of the configure phase. postConfigure Hook executed at the end of the configure phase.
The build phase buildPhase calls make. You can set flags for make through the makeFlags variable. Before and after running make, the hooks preBuild and postBuild are called, respectively.
The check phase checkPhase calls make check, but only if the doCheck variable is set to 1. Additional flags can be set through the checkFlags variable.
The install phase installPhase calls make install. Additional flags can be set through the installFlags variable. Before and after running make install, the hooks preInstall and postInstall are called, respectively.
The fixup phase fixupPhase cleans up the installed files in various ways: It moves the man/, doc/ and info/ subdirectories of $out to share/. It strips libraries and executables of debug information. On Linux, it applies the patchelf command to ELF executables and libraries to remove unused directories from the RPATH in order to prevent unnecessary dependencies. It rewrites the interpreter paths of shell scripts to paths found in PATH. E.g., /usr/bin/perl will be rewritten to /nix/store/some-perl/bin/perl found in PATH.
The distribution phase distPhase calls make dist, but only if the doDist variable is set to 1. Additional flags can be set through the distFlags variable. The resulting tarball is copied to the /tarballs subdirectory of the output path. Before and after running make dist, the hooks preDist and postDist are called, respectively.
Attributes
Package setup hooks
Purity in Nixpkgs [measures taken to prevent dependencies on packages outside the store, and what you can do to prevent them] GCC doesn't search in locations such as /usr/include. In fact, attempts to add such directories through the flag are filtered out. Likewise, the linker (from GNU binutils) doesn't search in standard locations such as /usr/lib. Programs built on Linux are linked against a GNU C Library that likewise doesn't search in the default system locations.