mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-18 07:46:09 +01:00
1719 lines
63 KiB
XML
1719 lines
63 KiB
XML
<chapter xmlns="http://docbook.org/ns/docbook"
|
||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||
xml:id="chap-stdenv">
|
||
|
||
<title>The Standard Environment</title>
|
||
|
||
|
||
<para>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 <literal>./configure; make; make install</literal> build
|
||
interface, you don’t need to write a build script at all; the standard
|
||
environment does everything automatically. If
|
||
<literal>stdenv</literal> doesn’t do what you need automatically, you
|
||
can easily customise or override the various build phases.</para>
|
||
|
||
|
||
<section xml:id="sec-using-stdenv"><title>Using
|
||
<literal>stdenv</literal></title>
|
||
|
||
<para>To build a package with the standard environment, you use the
|
||
function <varname>stdenv.mkDerivation</varname>, instead of the
|
||
primitive built-in function <varname>derivation</varname>, e.g.
|
||
|
||
<programlisting>
|
||
stdenv.mkDerivation {
|
||
name = "libfoo-1.2.3";
|
||
src = fetchurl {
|
||
url = http://example.org/libfoo-1.2.3.tar.bz2;
|
||
sha256 = "0x2g1jqygyr5wiwg4ma1nd7w4ydpy82z9gkcv8vh2v8dn3y58v5m";
|
||
};
|
||
}</programlisting>
|
||
|
||
(<varname>stdenv</varname> needs to be in scope, so if you write this
|
||
in a separate Nix expression from
|
||
<filename>pkgs/all-packages.nix</filename>, you need to pass it as a
|
||
function argument.) Specifying a <varname>name</varname> and a
|
||
<varname>src</varname> 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 <varname>buildInputs</varname> attribute:
|
||
|
||
<programlisting>
|
||
stdenv.mkDerivation {
|
||
name = "libfoo-1.2.3";
|
||
...
|
||
buildInputs = [libbar perl ncurses];
|
||
}</programlisting>
|
||
|
||
This attribute ensures that the <filename>bin</filename>
|
||
subdirectories of these packages appear in the <envar>PATH</envar>
|
||
environment variable during the build, that their
|
||
<filename>include</filename> subdirectories are searched by the C
|
||
compiler, and so on. (See <xref linkend="ssec-setup-hooks"/> for
|
||
details.)</para>
|
||
|
||
<para>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 <emphasis>phases</emphasis>, all of
|
||
which can be overridden or modified individually: unpacking the
|
||
sources, applying patches, configuring, building, and installing.
|
||
(There are some others; see <xref linkend="sec-stdenv-phases"/>.)
|
||
For instance, a package that doesn’t supply a makefile but instead has
|
||
to be compiled “manually” could be handled like this:
|
||
|
||
<programlisting>
|
||
stdenv.mkDerivation {
|
||
name = "fnord-4.5";
|
||
...
|
||
buildPhase = ''
|
||
gcc foo.c -o foo
|
||
'';
|
||
installPhase = ''
|
||
mkdir -p $out/bin
|
||
cp foo $out/bin
|
||
'';
|
||
}</programlisting>
|
||
|
||
(Note the use of <literal>''</literal>-style string literals, which
|
||
are very convenient for large multi-line script fragments because they
|
||
don’t need escaping of <literal>"</literal> and <literal>\</literal>,
|
||
and because indentation is intelligently removed.)</para>
|
||
|
||
<para>There are many other attributes to customise the build. These
|
||
are listed in <xref linkend="ssec-stdenv-attributes"/>.</para>
|
||
|
||
<para>While the standard environment provides a generic builder, you
|
||
can still supply your own build script:
|
||
|
||
<programlisting>
|
||
stdenv.mkDerivation {
|
||
name = "libfoo-1.2.3";
|
||
...
|
||
builder = ./builder.sh;
|
||
}</programlisting>
|
||
|
||
where the builder can do anything it wants, but typically starts with
|
||
|
||
<programlisting>
|
||
source $stdenv/setup
|
||
</programlisting>
|
||
|
||
to let <literal>stdenv</literal> set up the environment (e.g., process
|
||
the <varname>buildInputs</varname>). If you want, you can still use
|
||
<literal>stdenv</literal>’s generic builder:
|
||
|
||
<programlisting>
|
||
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
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="sec-tools-of-stdenv"><title>Tools provided by
|
||
<literal>stdenv</literal></title>
|
||
|
||
<para>The standard environment provides the following packages:
|
||
|
||
<itemizedlist>
|
||
|
||
<listitem><para>The GNU C Compiler, configured with C and C++
|
||
support.</para></listitem>
|
||
|
||
<listitem><para>GNU coreutils (contains a few dozen standard Unix
|
||
commands).</para></listitem>
|
||
|
||
<listitem><para>GNU findutils (contains
|
||
<command>find</command>).</para></listitem>
|
||
|
||
<listitem><para>GNU diffutils (contains <command>diff</command>,
|
||
<command>cmp</command>).</para></listitem>
|
||
|
||
<listitem><para>GNU <command>sed</command>.</para></listitem>
|
||
|
||
<listitem><para>GNU <command>grep</command>.</para></listitem>
|
||
|
||
<listitem><para>GNU <command>awk</command>.</para></listitem>
|
||
|
||
<listitem><para>GNU <command>tar</command>.</para></listitem>
|
||
|
||
<listitem><para><command>gzip</command>, <command>bzip2</command>
|
||
and <command>xz</command>.</para></listitem>
|
||
|
||
<listitem><para>GNU Make. It has been patched to provide
|
||
<quote>nested</quote> output that can be fed into the
|
||
<command>nix-log2xml</command> command and
|
||
<command>log2html</command> stylesheet to create a structured,
|
||
readable output of the build steps performed by
|
||
Make.</para></listitem>
|
||
|
||
<listitem><para>Bash. This is the shell used for all builders in
|
||
the Nix Packages collection. Not using <command>/bin/sh</command>
|
||
removes a large source of portability problems.</para></listitem>
|
||
|
||
<listitem><para>The <command>patch</command>
|
||
command.</para></listitem>
|
||
|
||
</itemizedlist>
|
||
|
||
</para>
|
||
|
||
<para>On Linux, <literal>stdenv</literal> also includes the
|
||
<command>patchelf</command> utility.</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-stdenv-attributes"><title>Attributes</title>
|
||
|
||
<variablelist>
|
||
<title>Variables affecting <literal>stdenv</literal>
|
||
initialisation</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>NIX_DEBUG</varname></term>
|
||
<listitem><para>
|
||
A natural number indicating how much information to log.
|
||
If set to 1 or higher, <literal>stdenv</literal> will print moderate debug information during the build.
|
||
In particular, the <command>gcc</command> and <command>ld</command> wrapper scripts will print out the complete command line passed to the wrapped tools.
|
||
If set to 6 or higher, the <literal>stdenv</literal> setup script will be run with <literal>set -x</literal> tracing.
|
||
If set to 7 or higher, the <command>gcc</command> and <command>ld</command> wrapper scripts will also be run with <literal>set -x</literal> tracing.
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
<variablelist>
|
||
<title>Variables specifying dependencies</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>nativeBuildInputs</varname></term>
|
||
<listitem><para>
|
||
A list of dependencies used by the new derivation at <emphasis>build</emphasis>-time.
|
||
I.e. these dependencies should not make it into the package's runtime-closure, though this is currently not checked.
|
||
For each dependency <replaceable>dir</replaceable>, the directory <filename><replaceable>dir</replaceable>/bin</filename>, if it exists, is added to the <envar>PATH</envar> environment variable.
|
||
Other environment variables are also set up via a pluggable mechanism.
|
||
For instance, if <varname>buildInputs</varname> contains Perl, then the <filename>lib/site_perl</filename> subdirectory of each input is added to the <envar>PERL5LIB</envar> environment variable.
|
||
See <xref linkend="ssec-setup-hooks"/> for details.
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>buildInputs</varname></term>
|
||
<listitem><para>
|
||
A list of dependencies used by the new derivation at <emphasis>run</emphasis>-time.
|
||
Currently, the build-time environment is modified in the exact same way as with <varname>nativeBuildInputs</varname>.
|
||
This is problematic in that when cross-compiling, foreign executables can clobber native ones on the <envar>PATH</envar>.
|
||
Even more confusing is static-linking.
|
||
A statically-linked library should be listed here because ultimately that generated machine code will be used at run-time, even though a derivation containing the object files or static archives will only be used at build-time.
|
||
A less confusing solution to this would be nice.
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry>
|
||
<term><varname>propagatedNativeBuildInputs</varname></term>
|
||
<listitem><para>
|
||
Like <varname>nativeBuildInputs</varname>, but these dependencies are <emphasis>propagated</emphasis>:
|
||
that is, the dependencies listed here are added to the <varname>nativeBuildInputs</varname> of any package that uses <emphasis>this</emphasis> package as a dependency.
|
||
So if package Y has <literal>propagatedNativeBuildInputs = [X]</literal>, and package Z has <literal>nativeBuildInputs = [Y]</literal>,
|
||
then package X will appear in Z’s build environment automatically.
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>propagatedBuildInputs</varname></term>
|
||
<listitem><para>
|
||
Like <varname>buildInputs</varname>, but propagated just like <varname>propagatedNativeBuildInputs</varname>.
|
||
This inherits <varname>buildInputs</varname>'s flaws of clobbering native executables when cross-compiling and being confusing for static linking.
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
<variablelist>
|
||
<title>Variables affecting build properties</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>enableParallelBuilding</varname></term>
|
||
<listitem><para>If set, <literal>stdenv</literal> will pass specific
|
||
flags to <literal>make</literal> and other build tools to enable
|
||
parallel building with up to <literal>build-cores</literal>
|
||
workers.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preferLocalBuild</varname></term>
|
||
<listitem><para>If set, specifies that the package is so lightweight
|
||
in terms of build operations (e.g. write a text file from a Nix string
|
||
to the store) that there's no need to look for it in binary caches --
|
||
it's faster to just build it locally. It also tells Hydra and other
|
||
facilities that this package doesn't need to be exported in binary
|
||
caches (noone would use it, after all).</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
<variablelist>
|
||
<title>Special variables</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>passthru</varname></term>
|
||
<listitem><para>This is an attribute set which can be filled with arbitrary
|
||
values. For example:
|
||
|
||
<programlisting>
|
||
passthru = {
|
||
foo = "bar";
|
||
baz = {
|
||
value1 = 4;
|
||
value2 = 5;
|
||
};
|
||
}
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
<para>Values inside it are not passed to the builder, so you can change
|
||
them without triggering a rebuild. However, they can be accessed outside of a
|
||
derivation directly, as if they were set inside a derivation itself, e.g.
|
||
<literal>hello.baz.value1</literal>. We don't specify any usage or
|
||
schema of <literal>passthru</literal> - it is meant for values that would be
|
||
useful outside the derivation in other parts of a Nix expression (e.g. in other
|
||
derivations). An example would be to convey some specific dependency of your
|
||
derivation which contains a program with plugins support. Later, others who
|
||
make derivations with plugins can use passed-through dependency to ensure that
|
||
their plugin would be binary-compatible with built program.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="sec-stdenv-phases"><title>Phases</title>
|
||
|
||
<para>The generic builder has a number of <emphasis>phases</emphasis>.
|
||
Package builds are split into phases to make it easier to override
|
||
specific parts of the build (e.g., unpacking the sources or installing
|
||
the binaries). Furthermore, it allows a nicer presentation of build
|
||
logs in the Nix build farm.</para>
|
||
|
||
<para>Each phase can be overridden in its entirety either by setting
|
||
the environment variable
|
||
<varname><replaceable>name</replaceable>Phase</varname> to a string
|
||
containing some shell commands to be executed, or by redefining the
|
||
shell function
|
||
<varname><replaceable>name</replaceable>Phase</varname>. The former
|
||
is convenient to override a phase from the derivation, while the
|
||
latter is convenient from a build script.
|
||
|
||
However, typically one only wants to <emphasis>add</emphasis> some
|
||
commands to a phase, e.g. by defining <literal>postInstall</literal>
|
||
or <literal>preFixup</literal>, as skipping some of the default actions
|
||
may have unexpected consequences.
|
||
</para>
|
||
|
||
|
||
<section xml:id="ssec-controlling-phases"><title>Controlling
|
||
phases</title>
|
||
|
||
<para>There are a number of variables that control what phases are
|
||
executed and in what order:
|
||
|
||
<variablelist>
|
||
<title>Variables affecting phase control</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>phases</varname></term>
|
||
<listitem>
|
||
<para>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
|
||
<literal>$prePhases unpackPhase patchPhase $preConfigurePhases
|
||
configurePhase $preBuildPhases buildPhase checkPhase
|
||
$preInstallPhases installPhase fixupPhase $preDistPhases
|
||
distPhase $postPhases</literal>.
|
||
</para>
|
||
|
||
<para>Usually, if you just want to add a few phases, it’s more
|
||
convenient to set one of the variables below (such as
|
||
<varname>preInstallPhases</varname>), as you then don’t specify
|
||
all the normal phases.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>prePhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed before any of the default phases.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preConfigurePhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed just before the configure phase.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preBuildPhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed just before the build phase.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preInstallPhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed just before the install phase.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preFixupPhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed just before the fixup phase.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preDistPhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed just before the distribution phase.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postPhases</varname></term>
|
||
<listitem>
|
||
<para>Additional phases executed after any of the default
|
||
phases.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-unpack-phase"><title>The unpack phase</title>
|
||
|
||
<para>The unpack phase is responsible for unpacking the source code of
|
||
the package. The default implementation of
|
||
<function>unpackPhase</function> unpacks the source files listed in
|
||
the <envar>src</envar> environment variable to the current directory.
|
||
It supports the following files by default:
|
||
|
||
<variablelist>
|
||
|
||
<varlistentry>
|
||
<term>Tar files</term>
|
||
<listitem><para>These can optionally be compressed using
|
||
<command>gzip</command> (<filename>.tar.gz</filename>,
|
||
<filename>.tgz</filename> or <filename>.tar.Z</filename>),
|
||
<command>bzip2</command> (<filename>.tar.bz2</filename> or
|
||
<filename>.tbz2</filename>) or <command>xz</command>
|
||
(<filename>.tar.xz</filename> or
|
||
<filename>.tar.lzma</filename>).</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Zip files</term>
|
||
<listitem><para>Zip files are unpacked using
|
||
<command>unzip</command>. However, <command>unzip</command> is
|
||
not in the standard environment, so you should add it to
|
||
<varname>buildInputs</varname> yourself.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Directories in the Nix store</term>
|
||
<listitem><para>These are simply copied to the current directory.
|
||
The hash part of the file name is stripped,
|
||
e.g. <filename>/nix/store/1wydxgby13cz...-my-sources</filename>
|
||
would be copied to
|
||
<filename>my-sources</filename>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
Additional file types can be supported by setting the
|
||
<varname>unpackCmd</varname> variable (see below).</para>
|
||
|
||
<para></para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the unpack phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>srcs</varname> / <varname>src</varname></term>
|
||
<listitem><para>The list of source files or directories to be
|
||
unpacked or copied. One of these must be set.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>sourceRoot</varname></term>
|
||
<listitem><para>After running <function>unpackPhase</function>,
|
||
the generic builder changes the current directory to the directory
|
||
created by unpacking the sources. If there are multiple source
|
||
directories, you should set <varname>sourceRoot</varname> to the
|
||
name of the intended directory.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>setSourceRoot</varname></term>
|
||
<listitem><para>Alternatively to setting
|
||
<varname>sourceRoot</varname>, you can set
|
||
<varname>setSourceRoot</varname> to a shell command to be
|
||
evaluated by the unpack phase after the sources have been
|
||
unpacked. This command must set
|
||
<varname>sourceRoot</varname>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preUnpack</varname></term>
|
||
<listitem><para>Hook executed at the start of the unpack
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postUnpack</varname></term>
|
||
<listitem><para>Hook executed at the end of the unpack
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontMakeSourcesWritable</varname></term>
|
||
<listitem><para>If set to <literal>1</literal>, the unpacked
|
||
sources are <emphasis>not</emphasis> 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.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>unpackCmd</varname></term>
|
||
<listitem><para>The unpack phase evaluates the string
|
||
<literal>$unpackCmd</literal> for any unrecognised file. The path
|
||
to the current source file is contained in the
|
||
<varname>curSrc</varname> variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-patch-phase"><title>The patch phase</title>
|
||
|
||
<para>The patch phase applies the list of patches defined in the
|
||
<varname>patches</varname> variable.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the patch phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>patches</varname></term>
|
||
<listitem><para>The list of patches. They must be in the format
|
||
accepted by the <command>patch</command> command, and may
|
||
optionally be compressed using <command>gzip</command>
|
||
(<filename>.gz</filename>), <command>bzip2</command>
|
||
(<filename>.bz2</filename>) or <command>xz</command>
|
||
(<filename>.xz</filename>).</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>patchFlags</varname></term>
|
||
<listitem><para>Flags to be passed to <command>patch</command>.
|
||
If not set, the argument <option>-p1</option> is used, which
|
||
causes the leading directory component to be stripped from the
|
||
file names in each patch.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>prePatch</varname></term>
|
||
<listitem><para>Hook executed at the start of the patch
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postPatch</varname></term>
|
||
<listitem><para>Hook executed at the end of the patch
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-configure-phase"><title>The configure phase</title>
|
||
|
||
<para>The configure phase prepares the source tree for building. The
|
||
default <function>configurePhase</function> runs
|
||
<filename>./configure</filename> (typically an Autoconf-generated
|
||
script) if it exists.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the configure phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>configureScript</varname></term>
|
||
<listitem><para>The name of the configure script. It defaults to
|
||
<filename>./configure</filename> if it exists; otherwise, the
|
||
configure phase is skipped. This can actually be a command (like
|
||
<literal>perl ./Configure.pl</literal>).</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>configureFlags</varname></term>
|
||
<listitem><para>A list of strings passed as additional arguments to the
|
||
configure script.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>configureFlagsArray</varname></term>
|
||
<listitem><para>A shell array containing additional arguments
|
||
passed to the configure script. You must use this instead of
|
||
<varname>configureFlags</varname> if the arguments contain
|
||
spaces.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontAddPrefix</varname></term>
|
||
<listitem><para>By default, the flag
|
||
<literal>--prefix=$prefix</literal> is added to the configure
|
||
flags. If this is undesirable, set this variable to
|
||
true.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>prefix</varname></term>
|
||
<listitem><para>The prefix under which the package must be
|
||
installed, passed via the <option>--prefix</option> option to the
|
||
configure script. It defaults to
|
||
<option>$out</option>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontAddDisableDepTrack</varname></term>
|
||
<listitem><para>By default, the flag
|
||
<literal>--disable-dependency-tracking</literal> is added to the
|
||
configure flags to speed up Automake-based builds. If this is
|
||
undesirable, set this variable to true.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontFixLibtool</varname></term>
|
||
<listitem><para>By default, the configure phase applies some
|
||
special hackery to all files called <filename>ltmain.sh</filename>
|
||
before running the configure script in order to improve the purity
|
||
of Libtool-based packages<footnote><para>It clears the
|
||
<varname>sys_lib_<replaceable>*</replaceable>search_path</varname>
|
||
variables in the Libtool script to prevent Libtool from using
|
||
libraries in <filename>/usr/lib</filename> and
|
||
such.</para></footnote>. If this is undesirable, set this
|
||
variable to true.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontDisableStatic</varname></term>
|
||
<listitem><para>By default, when the configure script has
|
||
<option>--enable-static</option>, the option
|
||
<option>--disable-static</option> is added to the configure flags.</para>
|
||
<para>If this is undesirable, set this variable to
|
||
true.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>configurePlatforms</varname></term>
|
||
<listitem><para>
|
||
By default, when cross compiling, the configure script has <option>--build=...</option> and <option>--host=...</option> passed.
|
||
Packages can instead pass <literal>[ "build" "host" "target" ]</literal> or a subset to control exactly which platform flags are passed.
|
||
Compilers and other tools should use this to also pass the target platform, for example.
|
||
Note eventually these will be passed when in native builds too, to improve determinism: build-time guessing, as is done today, is a risk of impurity.
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preConfigure</varname></term>
|
||
<listitem><para>Hook executed at the start of the configure
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postConfigure</varname></term>
|
||
<listitem><para>Hook executed at the end of the configure
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="build-phase"><title>The build phase</title>
|
||
|
||
<para>The build phase is responsible for actually building the package
|
||
(e.g. compiling it). The default <function>buildPhase</function>
|
||
simply calls <command>make</command> if a file named
|
||
<filename>Makefile</filename>, <filename>makefile</filename> or
|
||
<filename>GNUmakefile</filename> exists in the current directory (or
|
||
the <varname>makefile</varname> is explicitly set); otherwise it does
|
||
nothing.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the build phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontBuild</varname></term>
|
||
<listitem><para>Set to true to skip the build phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>makefile</varname></term>
|
||
<listitem><para>The file name of the Makefile.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>makeFlags</varname></term>
|
||
<listitem><para>A list of strings passed as additional flags to
|
||
<command>make</command>. These flags are also used by the default
|
||
install and check phase. For setting make flags specific to the
|
||
build phase, use <varname>buildFlags</varname> (see below).
|
||
|
||
<programlisting>
|
||
makeFlags = [ "PREFIX=$(out)" ];
|
||
</programlisting>
|
||
|
||
<note><para>The flags are quoted in bash, but environment variables can
|
||
be specified by using the make syntax.</para></note></para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>makeFlagsArray</varname></term>
|
||
<listitem><para>A shell array containing additional arguments
|
||
passed to <command>make</command>. You must use this instead of
|
||
<varname>makeFlags</varname> if the arguments contain
|
||
spaces, e.g.
|
||
|
||
<programlisting>
|
||
makeFlagsArray=(CFLAGS="-O0 -g" LDFLAGS="-lfoo -lbar")
|
||
</programlisting>
|
||
|
||
Note that shell arrays cannot be passed through environment
|
||
variables, so you cannot set <varname>makeFlagsArray</varname> in
|
||
a derivation attribute (because those are passed through
|
||
environment variables): you have to define them in shell
|
||
code.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>buildFlags</varname> / <varname>buildFlagsArray</varname></term>
|
||
<listitem><para>A list of strings passed as additional flags to
|
||
<command>make</command>. Like <varname>makeFlags</varname> and
|
||
<varname>makeFlagsArray</varname>, but only used by the build
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preBuild</varname></term>
|
||
<listitem><para>Hook executed at the start of the build
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postBuild</varname></term>
|
||
<listitem><para>Hook executed at the end of the build
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
|
||
<para>
|
||
You can set flags for <command>make</command> through the
|
||
<varname>makeFlags</varname> variable.</para>
|
||
|
||
<para>Before and after running <command>make</command>, the hooks
|
||
<varname>preBuild</varname> and <varname>postBuild</varname> are
|
||
called, respectively.</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-check-phase"><title>The check phase</title>
|
||
|
||
<para>The check phase checks whether the package was built correctly
|
||
by running its test suite. The default
|
||
<function>checkPhase</function> calls <command>make check</command>,
|
||
but only if the <varname>doCheck</varname> variable is enabled.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the check phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>doCheck</varname></term>
|
||
<listitem><para>If set to a non-empty string, the check phase is
|
||
executed, otherwise it is skipped (default). Thus you should set
|
||
|
||
<programlisting>
|
||
doCheck = true;</programlisting>
|
||
|
||
in the derivation to enable checks.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>makeFlags</varname> /
|
||
<varname>makeFlagsArray</varname> /
|
||
<varname>makefile</varname></term>
|
||
<listitem><para>See the build phase for details.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>checkTarget</varname></term>
|
||
<listitem><para>The make target that runs the tests. Defaults to
|
||
<literal>check</literal>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>checkFlags</varname> / <varname>checkFlagsArray</varname></term>
|
||
<listitem><para>A list of strings passed as additional flags to
|
||
<command>make</command>. Like <varname>makeFlags</varname> and
|
||
<varname>makeFlagsArray</varname>, but only used by the check
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preCheck</varname></term>
|
||
<listitem><para>Hook executed at the start of the check
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postCheck</varname></term>
|
||
<listitem><para>Hook executed at the end of the check
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-install-phase"><title>The install phase</title>
|
||
|
||
<para>The install phase is responsible for installing the package in
|
||
the Nix store under <envar>out</envar>. The default
|
||
<function>installPhase</function> creates the directory
|
||
<literal>$out</literal> and calls <command>make
|
||
install</command>.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the install phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>makeFlags</varname> /
|
||
<varname>makeFlagsArray</varname> /
|
||
<varname>makefile</varname></term>
|
||
<listitem><para>See the build phase for details.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>installTargets</varname></term>
|
||
<listitem><para>The make targets that perform the installation.
|
||
Defaults to <literal>install</literal>. Example:
|
||
|
||
<programlisting>
|
||
installTargets = "install-bin install-doc";</programlisting>
|
||
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>installFlags</varname> / <varname>installFlagsArray</varname></term>
|
||
<listitem><para>A list of strings passed as additional flags to
|
||
<command>make</command>. Like <varname>makeFlags</varname> and
|
||
<varname>makeFlagsArray</varname>, but only used by the install
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preInstall</varname></term>
|
||
<listitem><para>Hook executed at the start of the install
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postInstall</varname></term>
|
||
<listitem><para>Hook executed at the end of the install
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-fixup-phase"><title>The fixup phase</title>
|
||
|
||
<para>The fixup phase performs some (Nix-specific) post-processing
|
||
actions on the files installed under <filename>$out</filename> by the
|
||
install phase. The default <function>fixupPhase</function> does the
|
||
following:
|
||
|
||
<itemizedlist>
|
||
|
||
<listitem><para>It moves the <filename>man/</filename>,
|
||
<filename>doc/</filename> and <filename>info/</filename>
|
||
subdirectories of <envar>$out</envar> to
|
||
<filename>share/</filename>.</para></listitem>
|
||
|
||
<listitem><para>It strips libraries and executables of debug
|
||
information.</para></listitem>
|
||
|
||
<listitem><para>On Linux, it applies the <command>patchelf</command>
|
||
command to ELF executables and libraries to remove unused
|
||
directories from the <literal>RPATH</literal> in order to prevent
|
||
unnecessary runtime dependencies.</para></listitem>
|
||
|
||
<listitem><para>It rewrites the interpreter paths of shell scripts
|
||
to paths found in <envar>PATH</envar>. E.g.,
|
||
<filename>/usr/bin/perl</filename> will be rewritten to
|
||
<filename>/nix/store/<replaceable>some-perl</replaceable>/bin/perl</filename>
|
||
found in <envar>PATH</envar>.</para></listitem>
|
||
|
||
</itemizedlist>
|
||
|
||
</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the fixup phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontStrip</varname></term>
|
||
<listitem><para>If set, libraries and executables are not
|
||
stripped. By default, they are.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontMoveSbin</varname></term>
|
||
<listitem><para>If set, files in <filename>$out/sbin</filename> are not moved
|
||
to <filename>$out/bin</filename>. By default, they are.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>stripAllList</varname></term>
|
||
<listitem><para>List of directories to search for libraries and
|
||
executables from which <emphasis>all</emphasis> symbols should be
|
||
stripped. By default, it’s empty. Stripping all symbols is
|
||
risky, since it may remove not just debug symbols but also ELF
|
||
information necessary for normal execution.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>stripAllFlags</varname></term>
|
||
<listitem><para>Flags passed to the <command>strip</command>
|
||
command applied to the files in the directories listed in
|
||
<varname>stripAllList</varname>. Defaults to <option>-s</option>
|
||
(i.e. <option>--strip-all</option>).</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>stripDebugList</varname></term>
|
||
<listitem><para>List of directories to search for libraries and
|
||
executables from which only debugging-related symbols should be
|
||
stripped. It defaults to <literal>lib bin
|
||
sbin</literal>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>stripDebugFlags</varname></term>
|
||
<listitem><para>Flags passed to the <command>strip</command>
|
||
command applied to the files in the directories listed in
|
||
<varname>stripDebugList</varname>. Defaults to
|
||
<option>-S</option>
|
||
(i.e. <option>--strip-debug</option>).</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontPatchELF</varname></term>
|
||
<listitem><para>If set, the <command>patchelf</command> command is
|
||
not used to remove unnecessary <literal>RPATH</literal> entries.
|
||
Only applies to Linux.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontPatchShebangs</varname></term>
|
||
<listitem><para>If set, scripts starting with
|
||
<literal>#!</literal> do not have their interpreter paths
|
||
rewritten to paths in the Nix store.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>forceShare</varname></term>
|
||
<listitem><para>The list of directories that must be moved from
|
||
<filename>$out</filename> to <filename>$out/share</filename>.
|
||
Defaults to <literal>man doc info</literal>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>setupHook</varname></term>
|
||
<listitem><para>A package can export a <link
|
||
linkend="ssec-setup-hooks">setup hook</link> by setting this
|
||
variable. The setup hook, if defined, is copied to
|
||
<filename>$out/nix-support/setup-hook</filename>. Environment
|
||
variables are then substituted in it using <function
|
||
linkend="fun-substituteAll">substituteAll</function>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preFixup</varname></term>
|
||
<listitem><para>Hook executed at the start of the fixup
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postFixup</varname></term>
|
||
<listitem><para>Hook executed at the end of the fixup
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry xml:id="stdenv-separateDebugInfo">
|
||
<term><varname>separateDebugInfo</varname></term>
|
||
<listitem><para>If set to <literal>true</literal>, the standard
|
||
environment will enable debug information in C/C++ builds. After
|
||
installation, the debug information will be separated from the
|
||
executables and stored in the output named
|
||
<literal>debug</literal>. (This output is enabled automatically;
|
||
you don’t need to set the <varname>outputs</varname> attribute
|
||
explicitly.) To be precise, the debug information is stored in
|
||
<filename><replaceable>debug</replaceable>/lib/debug/.build-id/<replaceable>XX</replaceable>/<replaceable>YYYY…</replaceable></filename>,
|
||
where <replaceable>XXYYYY…</replaceable> is the <replaceable>build
|
||
ID</replaceable> of the binary — a SHA-1 hash of the contents of
|
||
the binary. Debuggers like GDB use the build ID to look up the
|
||
separated debug information.</para>
|
||
|
||
<para>For example, with GDB, you can add
|
||
|
||
<programlisting>
|
||
set debug-file-directory ~/.nix-profile/lib/debug
|
||
</programlisting>
|
||
|
||
to <filename>~/.gdbinit</filename>. GDB will then be able to find
|
||
debug information installed via <literal>nix-env
|
||
-i</literal>.</para>
|
||
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</section>
|
||
|
||
<section xml:id="ssec-installCheck-phase"><title>The installCheck phase</title>
|
||
|
||
<para>The installCheck phase checks whether the package was installed
|
||
correctly by running its test suite against the installed directories.
|
||
The default <function>installCheck</function> calls <command>make
|
||
installcheck</command>.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the installCheck phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>doInstallCheck</varname></term>
|
||
<listitem><para>If set to a non-empty string, the installCheck phase is
|
||
executed, otherwise it is skipped (default). Thus you should set
|
||
|
||
<programlisting>doInstallCheck = true;</programlisting>
|
||
|
||
in the derivation to enable install checks.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preInstallCheck</varname></term>
|
||
<listitem><para>Hook executed at the start of the installCheck
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postInstallCheck</varname></term>
|
||
<listitem><para>Hook executed at the end of the installCheck
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</section>
|
||
|
||
<section xml:id="ssec-distribution-phase"><title>The distribution
|
||
phase</title>
|
||
|
||
<para>The distribution phase is intended to produce a source
|
||
distribution of the package. The default
|
||
<function>distPhase</function> first calls <command>make
|
||
dist</command>, then it copies the resulting source tarballs to
|
||
<filename>$out/tarballs/</filename>. This phase is only executed if
|
||
the attribute <varname>doDist</varname> is set.</para>
|
||
|
||
<variablelist>
|
||
<title>Variables controlling the distribution phase</title>
|
||
|
||
<varlistentry>
|
||
<term><varname>distTarget</varname></term>
|
||
<listitem><para>The make target that produces the distribution.
|
||
Defaults to <literal>dist</literal>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>distFlags</varname> / <varname>distFlagsArray</varname></term>
|
||
<listitem><para>Additional flags passed to
|
||
<command>make</command>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>tarballs</varname></term>
|
||
<listitem><para>The names of the source distribution files to be
|
||
copied to <filename>$out/tarballs/</filename>. It can contain
|
||
shell wildcards. The default is
|
||
<filename>*.tar.gz</filename>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>dontCopyDist</varname></term>
|
||
<listitem><para>If set, no files are copied to
|
||
<filename>$out/tarballs/</filename>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>preDist</varname></term>
|
||
<listitem><para>Hook executed at the start of the distribution
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>postDist</varname></term>
|
||
<listitem><para>Hook executed at the end of the distribution
|
||
phase.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-stdenv-functions"><title>Shell functions</title>
|
||
|
||
<para>The standard environment provides a number of useful
|
||
functions.</para>
|
||
|
||
<variablelist>
|
||
|
||
|
||
<varlistentry xml:id='fun-makeWrapper'>
|
||
<term><function>makeWrapper</function>
|
||
<replaceable>executable</replaceable>
|
||
<replaceable>wrapperfile</replaceable>
|
||
<replaceable>args</replaceable></term>
|
||
<listitem><para>Constructs a wrapper for a program with various
|
||
possible arguments. For example:
|
||
|
||
<programlisting>
|
||
# adds `FOOBAR=baz` to `$out/bin/foo`’s environment
|
||
makeWrapper $out/bin/foo $wrapperfile --set FOOBAR baz
|
||
|
||
# prefixes the binary paths of `hello` and `git`
|
||
# Be advised that paths often should be patched in directly
|
||
# (via string replacements or in `configurePhase`).
|
||
makeWrapper $out/bin/foo $wrapperfile --prefix PATH : ${lib.makeBinPath [ hello git ]}
|
||
</programlisting>
|
||
|
||
There’s many more kinds of arguments, they are documented in
|
||
<literal>nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh</literal>.</para>
|
||
|
||
<para><literal>wrapProgram</literal> is a convenience function you probably
|
||
want to use most of the time.</para>
|
||
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry xml:id='fun-substitute'>
|
||
<term><function>substitute</function>
|
||
<replaceable>infile</replaceable>
|
||
<replaceable>outfile</replaceable>
|
||
<replaceable>subs</replaceable></term>
|
||
|
||
<listitem>
|
||
<para>Performs string substitution on the contents of
|
||
<replaceable>infile</replaceable>, writing the result to
|
||
<replaceable>outfile</replaceable>. The substitutions in
|
||
<replaceable>subs</replaceable> are of the following form:
|
||
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term><option>--replace</option>
|
||
<replaceable>s1</replaceable>
|
||
<replaceable>s2</replaceable></term>
|
||
<listitem><para>Replace every occurrence of the string
|
||
<replaceable>s1</replaceable> by
|
||
<replaceable>s2</replaceable>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><option>--subst-var</option>
|
||
<replaceable>varName</replaceable></term>
|
||
<listitem><para>Replace every occurrence of
|
||
<literal>@<replaceable>varName</replaceable>@</literal> by
|
||
the contents of the environment variable
|
||
<replaceable>varName</replaceable>. This is useful for
|
||
generating files from templates, using
|
||
<literal>@<replaceable>...</replaceable>@</literal> in the
|
||
template as placeholders.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><option>--subst-var-by</option>
|
||
<replaceable>varName</replaceable>
|
||
<replaceable>s</replaceable></term>
|
||
<listitem><para>Replace every occurrence of
|
||
<literal>@<replaceable>varName</replaceable>@</literal> by
|
||
the string <replaceable>s</replaceable>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</para>
|
||
|
||
<para>Example:
|
||
|
||
<programlisting>
|
||
substitute ./foo.in ./foo.out \
|
||
--replace /usr/bin/bar $bar/bin/bar \
|
||
--replace "a string containing spaces" "some other text" \
|
||
--subst-var someVar
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
<para><function>substitute</function> is implemented using the
|
||
<command
|
||
xlink:href="http://replace.richardlloyd.org.uk/">replace</command>
|
||
command. Unlike with the <command>sed</command> command, you
|
||
don’t have to worry about escaping special characters. It
|
||
supports performing substitutions on binary files (such as
|
||
executables), though there you’ll probably want to make sure
|
||
that the replacement string is as long as the replaced
|
||
string.</para>
|
||
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry xml:id='fun-substituteInPlace'>
|
||
<term><function>substituteInPlace</function>
|
||
<replaceable>file</replaceable>
|
||
<replaceable>subs</replaceable></term>
|
||
<listitem><para>Like <function>substitute</function>, but performs
|
||
the substitutions in place on the file
|
||
<replaceable>file</replaceable>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry xml:id='fun-substituteAll'>
|
||
<term><function>substituteAll</function>
|
||
<replaceable>infile</replaceable>
|
||
<replaceable>outfile</replaceable></term>
|
||
<listitem><para>Replaces every occurrence of
|
||
<literal>@<replaceable>varName</replaceable>@</literal>, where
|
||
<replaceable>varName</replaceable> is any environment variable, in
|
||
<replaceable>infile</replaceable>, writing the result to
|
||
<replaceable>outfile</replaceable>. For instance, if
|
||
<replaceable>infile</replaceable> has the contents
|
||
|
||
<programlisting>
|
||
#! @bash@/bin/sh
|
||
PATH=@coreutils@/bin
|
||
echo @foo@
|
||
</programlisting>
|
||
|
||
and the environment contains
|
||
<literal>bash=/nix/store/bmwp0q28cf21...-bash-3.2-p39</literal>
|
||
and
|
||
<literal>coreutils=/nix/store/68afga4khv0w...-coreutils-6.12</literal>,
|
||
but does not contain the variable <varname>foo</varname>, then the
|
||
output will be
|
||
|
||
<programlisting>
|
||
#! /nix/store/bmwp0q28cf21...-bash-3.2-p39/bin/sh
|
||
PATH=/nix/store/68afga4khv0w...-coreutils-6.12/bin
|
||
echo @foo@
|
||
</programlisting>
|
||
|
||
That is, no substitution is performed for undefined variables.</para>
|
||
|
||
<para>Environment variables that start with an uppercase letter or an
|
||
underscore are filtered out,
|
||
to prevent global variables (like <literal>HOME</literal>) or private
|
||
variables (like <literal>__ETC_PROFILE_DONE</literal>) from accidentally
|
||
getting substituted.
|
||
The variables also have to be valid bash “names”, as
|
||
defined in the bash manpage (alphanumeric or <literal>_</literal>,
|
||
must not start with a number).</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry xml:id='fun-substituteAllInPlace'>
|
||
<term><function>substituteAllInPlace</function>
|
||
<replaceable>file</replaceable></term>
|
||
<listitem><para>Like <function>substituteAll</function>, but performs
|
||
the substitutions in place on the file
|
||
<replaceable>file</replaceable>.</para></listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry xml:id='fun-stripHash'>
|
||
<term><function>stripHash</function>
|
||
<replaceable>path</replaceable></term>
|
||
<listitem><para>Strips the directory and hash part of a store
|
||
path, outputting the name part to <literal>stdout</literal>.
|
||
For example:
|
||
|
||
<programlisting>
|
||
# prints coreutils-8.24
|
||
stripHash "/nix/store/9s9r019176g7cvn2nvcw41gsp862y6b4-coreutils-8.24"
|
||
</programlisting>
|
||
|
||
If you wish to store the result in another variable, then the
|
||
following idiom may be useful:
|
||
|
||
<programlisting>
|
||
name="/nix/store/9s9r019176g7cvn2nvcw41gsp862y6b4-coreutils-8.24"
|
||
someVar=$(stripHash $name)
|
||
</programlisting>
|
||
|
||
</para></listitem>
|
||
</varlistentry>
|
||
|
||
|
||
<varlistentry xml:id='fun-wrapProgram'>
|
||
<term><function>wrapProgram</function>
|
||
<replaceable>executable</replaceable>
|
||
<replaceable>makeWrapperArgs</replaceable></term>
|
||
<listitem><para>Convenience function for <literal>makeWrapper</literal>
|
||
that automatically creates a sane wrapper file
|
||
|
||
It takes all the same arguments as <literal>makeWrapper</literal>,
|
||
except for <literal>--argv0</literal>.</para>
|
||
|
||
<para>It cannot be applied multiple times, since it will overwrite the wrapper
|
||
file.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
|
||
</variablelist>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="ssec-setup-hooks"><title>Package setup hooks</title>
|
||
|
||
<para>The following packages provide a setup hook:
|
||
|
||
<variablelist>
|
||
|
||
<varlistentry>
|
||
<term>CC Wrapper</term>
|
||
<listitem>
|
||
<para>
|
||
CC Wrapper wraps a C toolchain for a bunch of miscellaneous purposes.
|
||
Specifically, a C compiler (GCC or Clang), Binutils (or the CCTools + binutils mashup when targetting Darwin), and a C standard library (glibc or Darwin's libSystem) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by CC Wrapper.
|
||
Packages typically depend on only CC Wrapper, instead of those 3 inputs directly.
|
||
</para>
|
||
<para>
|
||
Dependency finding is undoubtedly the main task of CC wrapper.
|
||
It is currently accomplished by collecting directories of host-platform dependencies (i.e. <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>) in environment variables.
|
||
CC wrapper's setup hook causes any <filename>include</filename> subdirectory of such a dependency to be added to <envar>NIX_CFLAGS_COMPILE</envar>, and any <filename>lib</filename> and <filename>lib64</filename> subdirectories to <envar>NIX_LDFLAGS</envar>.
|
||
The setup hook itself contains some lengthy comments describing the exact convoluted mechanism by which this is accomplished.
|
||
</para>
|
||
<para>
|
||
A final task of the setup hook is defining a number of standard environment variables to tell build systems which executables full-fill which purpose.
|
||
They are defined to just be the base name of the tools, under the assumption that CC Wrapper's binaries will be on the path.
|
||
Firstly, this helps poorly-written packages, e.g. ones that look for just <command>gcc</command> when <envar>CC</envar> isn't defined yet <command>clang</command> is to be used.
|
||
Secondly, this helps packages not get confused when cross-compiling, in which case multiple CC wrappers may be simultaneous in use (targeting different platforms).
|
||
<envar>BUILD_</envar>- and <envar>TARGET_</envar>-prefixed versions of the normal environment variable are defined for the additional CC Wrappers, properly disambiguating them.
|
||
</para>
|
||
<para>
|
||
A problem with this final task is that CC Wrapper is honest and defines <envar>LD</envar> as <command>ld</command>.
|
||
Most packages, however, firstly use the C compiler for linking, secondly use <envar>LD</envar> anyways, defining it as the C compiler, and thirdly, only so define <envar>LD</envar> when it is undefined as a fallback.
|
||
This triple-threat means CC Wrapper will break those packages, as LD is already defined as the actually linker which the package won't override yet doesn't want to use.
|
||
The workaround is to define, just for the problematic package, <envar>LD</envar> as the C compiler.
|
||
A good way to do this would be <command>preConfigure = "LD=$CC"</command>.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Perl</term>
|
||
<listitem><para>Adds the <filename>lib/site_perl</filename> subdirectory
|
||
of each build input to the <envar>PERL5LIB</envar>
|
||
environment variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Python</term>
|
||
<listitem><para>Adds the
|
||
<filename>lib/${python.libPrefix}/site-packages</filename> subdirectory of
|
||
each build input to the <envar>PYTHONPATH</envar> environment
|
||
variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>pkg-config</term>
|
||
<listitem><para>Adds the <filename>lib/pkgconfig</filename> and
|
||
<filename>share/pkgconfig</filename> subdirectories of each
|
||
build input to the <envar>PKG_CONFIG_PATH</envar> environment
|
||
variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Automake</term>
|
||
<listitem><para>Adds the <filename>share/aclocal</filename>
|
||
subdirectory of each build input to the <envar>ACLOCAL_PATH</envar>
|
||
environment variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Autoconf</term>
|
||
<listitem><para>The <varname>autoreconfHook</varname> derivation adds
|
||
<varname>autoreconfPhase</varname>, which runs autoreconf, libtoolize and
|
||
automake, essentially preparing the configure script in autotools-based
|
||
builds.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>libxml2</term>
|
||
<listitem><para>Adds every file named
|
||
<filename>catalog.xml</filename> found under the
|
||
<filename>xml/dtd</filename> and <filename>xml/xsl</filename>
|
||
subdirectories of each build input to the
|
||
<envar>XML_CATALOG_FILES</envar> environment
|
||
variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>teTeX / TeX Live</term>
|
||
<listitem><para>Adds the <filename>share/texmf-nix</filename>
|
||
subdirectory of each build input to the <envar>TEXINPUTS</envar>
|
||
environment variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Qt 4</term>
|
||
<listitem><para>Sets the <envar>QTDIR</envar> environment variable
|
||
to Qt’s path.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>gdk-pixbuf</term>
|
||
<listitem><para>Exports <envar>GDK_PIXBUF_MODULE_FILE</envar>
|
||
environment variable the the builder. Add librsvg package
|
||
to <varname>buildInputs</varname> to get svg support.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>GHC</term>
|
||
<listitem><para>Creates a temporary package database and registers
|
||
every Haskell build input in it (TODO: how?).</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>GStreamer</term>
|
||
<listitem><para>Adds the
|
||
GStreamer plugins subdirectory of
|
||
each build input to the <envar>GST_PLUGIN_SYSTEM_PATH_1_0</envar> or
|
||
<envar>GST_PLUGIN_SYSTEM_PATH</envar> environment variable.</para></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>paxctl</term>
|
||
<listitem><para>Defines the <varname>paxmark</varname> helper for
|
||
setting per-executable PaX flags on Linux (where it is available by
|
||
default; on all other platforms, <varname>paxmark</varname> is a no-op).
|
||
For example, to disable secure memory protections on the executable
|
||
<replaceable>foo</replaceable>:
|
||
<programlisting>
|
||
postFixup = ''
|
||
paxmark m $out/bin/<replaceable>foo</replaceable>
|
||
'';
|
||
</programlisting>
|
||
The <literal>m</literal> flag is the most common flag and is typically
|
||
required for applications that employ JIT compilation or otherwise need to
|
||
execute code generated at run-time. Disabling PaX protections should be
|
||
considered a last resort: if possible, problematic features should be
|
||
disabled or patched to work with PaX.</para></listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="sec-purity-in-nixpkgs"><title>Purity in Nixpkgs</title>
|
||
|
||
<para>[measures taken to prevent dependencies on packages outside the
|
||
store, and what you can do to prevent them]</para>
|
||
|
||
<para>GCC doesn't search in locations such as
|
||
<filename>/usr/include</filename>. In fact, attempts to add such
|
||
directories through the <option>-I</option> flag are filtered out.
|
||
Likewise, the linker (from GNU binutils) doesn't search in standard
|
||
locations such as <filename>/usr/lib</filename>. Programs built on
|
||
Linux are linked against a GNU C Library that likewise doesn't search
|
||
in the default system locations.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="sec-hardening-in-nixpkgs"><title>Hardening in Nixpkgs</title>
|
||
|
||
<para>There are flags available to harden packages at compile or link-time.
|
||
These can be toggled using the <varname>stdenv.mkDerivation</varname> parameters
|
||
<varname>hardeningDisable</varname> and <varname>hardeningEnable</varname>.
|
||
</para>
|
||
|
||
<para>
|
||
Both parameters take a list of flags as strings. The special
|
||
<varname>"all"</varname> flag can be passed to <varname>hardeningDisable</varname>
|
||
to turn off all hardening. These flags can also be used as environment variables
|
||
for testing or development purposes.
|
||
</para>
|
||
|
||
<para>The following flags are enabled by default and might require disabling with
|
||
<varname>hardeningDisable</varname> if the program to package is incompatible.
|
||
</para>
|
||
|
||
<variablelist>
|
||
|
||
<varlistentry>
|
||
<term><varname>format</varname></term>
|
||
<listitem><para>Adds the <option>-Wformat -Wformat-security
|
||
-Werror=format-security</option> compiler options. At present,
|
||
this warns about calls to <varname>printf</varname> and
|
||
<varname>scanf</varname> functions where the format string is
|
||
not a string literal and there are no format arguments, as in
|
||
<literal>printf(foo);</literal>. This may be a security hole
|
||
if the format string came from untrusted input and contains
|
||
<literal>%n</literal>.</para>
|
||
|
||
<para>This needs to be turned off or fixed for errors similar to:</para>
|
||
|
||
<programlisting>
|
||
/tmp/nix-build-zynaddsubfx-2.5.2.drv-0/zynaddsubfx-2.5.2/src/UI/guimain.cpp:571:28: error: format not a string literal and no format arguments [-Werror=format-security]
|
||
printf(help_message);
|
||
^
|
||
cc1plus: some warnings being treated as errors
|
||
</programlisting></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>stackprotector</varname></term>
|
||
<listitem>
|
||
<para>Adds the <option>-fstack-protector-strong
|
||
--param ssp-buffer-size=4</option>
|
||
compiler options. This adds safety checks against stack overwrites
|
||
rendering many potential code injection attacks into aborting situations.
|
||
In the best case this turns code injection vulnerabilities into denial
|
||
of service or into non-issues (depending on the application).</para>
|
||
|
||
<para>This needs to be turned off or fixed for errors similar to:</para>
|
||
|
||
<programlisting>
|
||
bin/blib.a(bios_console.o): In function `bios_handle_cup':
|
||
/tmp/nix-build-ipxe-20141124-5cbdc41.drv-0/ipxe-5cbdc41/src/arch/i386/firmware/pcbios/bios_console.c:86: undefined reference to `__stack_chk_fail'
|
||
</programlisting></listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>fortify</varname></term>
|
||
<listitem>
|
||
<para>Adds the <option>-O2 -D_FORTIFY_SOURCE=2</option> compiler
|
||
options. During code generation the compiler knows a great deal of
|
||
information about buffer sizes (where possible), and attempts to replace
|
||
insecure unlimited length buffer function calls with length-limited ones.
|
||
This is especially useful for old, crufty code. Additionally, format
|
||
strings in writable memory that contain '%n' are blocked. If an application
|
||
depends on such a format string, it will need to be worked around.
|
||
</para>
|
||
|
||
<para>Additionally, some warnings are enabled which might trigger build
|
||
failures if compiler warnings are treated as errors in the package build.
|
||
In this case, set <option>NIX_CFLAGS_COMPILE</option> to
|
||
<option>-Wno-error=warning-type</option>.</para>
|
||
|
||
<para>This needs to be turned off or fixed for errors similar to:</para>
|
||
|
||
<programlisting>
|
||
malloc.c:404:15: error: return type is an incomplete type
|
||
malloc.c:410:19: error: storage size of 'ms' isn't known
|
||
</programlisting>
|
||
<programlisting>
|
||
strdup.h:22:1: error: expected identifier or '(' before '__extension__'
|
||
</programlisting>
|
||
<programlisting>
|
||
strsep.c:65:23: error: register name not specified for 'delim'
|
||
</programlisting>
|
||
<programlisting>
|
||
installwatch.c:3751:5: error: conflicting types for '__open_2'
|
||
</programlisting>
|
||
<programlisting>
|
||
fcntl2.h:50:4: error: call to '__open_missing_mode' declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments
|
||
</programlisting>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>pic</varname></term>
|
||
<listitem>
|
||
<para>Adds the <option>-fPIC</option> compiler options. This options adds
|
||
support for position independent code in shared libraries and thus making
|
||
ASLR possible.</para>
|
||
<para>Most notably, the Linux kernel, kernel modules and other code
|
||
not running in an operating system environment like boot loaders won't
|
||
build with PIC enabled. The compiler will is most cases complain that
|
||
PIC is not supported for a specific build.
|
||
</para>
|
||
|
||
<para>This needs to be turned off or fixed for assembler errors similar to:</para>
|
||
|
||
<programlisting>
|
||
ccbLfRgg.s: Assembler messages:
|
||
ccbLfRgg.s:33: Error: missing or invalid displacement expression `private_key_len@GOTOFF'
|
||
</programlisting>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>strictoverflow</varname></term>
|
||
<listitem>
|
||
<para>Signed integer overflow is undefined behaviour according to the C
|
||
standard. If it happens, it is an error in the program as it should check
|
||
for overflow before it can happen, not afterwards. GCC provides built-in
|
||
functions to perform arithmetic with overflow checking, which are correct
|
||
and faster than any custom implementation. As a workaround, the option
|
||
<option>-fno-strict-overflow</option> makes gcc behave as if signed
|
||
integer overflows were defined.
|
||
</para>
|
||
|
||
<para>This flag should not trigger any build or runtime errors.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>relro</varname></term>
|
||
<listitem>
|
||
<para>Adds the <option>-z relro</option> linker option. During program
|
||
load, several ELF memory sections need to be written to by the linker,
|
||
but can be turned read-only before turning over control to the program.
|
||
This prevents some GOT (and .dtors) overwrite attacks, but at least the
|
||
part of the GOT used by the dynamic linker (.got.plt) is still vulnerable.
|
||
</para>
|
||
|
||
<para>This flag can break dynamic shared object loading. For instance, the
|
||
module systems of Xorg and OpenCV are incompatible with this flag. In almost
|
||
all cases the <varname>bindnow</varname> flag must also be disabled and
|
||
incompatible programs typically fail with similar errors at runtime.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term><varname>bindnow</varname></term>
|
||
<listitem>
|
||
<para>Adds the <option>-z bindnow</option> linker option. During program
|
||
load, all dynamic symbols are resolved, allowing for the complete GOT to
|
||
be marked read-only (due to <varname>relro</varname>). This prevents GOT
|
||
overwrite attacks. For very large applications, this can incur some
|
||
performance loss during initial load while symbols are resolved, but this
|
||
shouldn't be an issue for daemons.
|
||
</para>
|
||
|
||
<para>This flag can break dynamic shared object loading. For instance, the
|
||
module systems of Xorg and PHP are incompatible with this flag. Programs
|
||
incompatible with this flag often fail at runtime due to missing symbols,
|
||
like:</para>
|
||
|
||
<programlisting>
|
||
intel_drv.so: undefined symbol: vgaHWFreeHWRec
|
||
</programlisting>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
<para>The following flags are disabled by default and should be enabled
|
||
with <varname>hardeningEnable</varname> for packages that take untrusted
|
||
input like network services.
|
||
</para>
|
||
|
||
<variablelist>
|
||
|
||
<varlistentry>
|
||
<term><varname>pie</varname></term>
|
||
<listitem>
|
||
<para>Adds the <option>-fPIE</option> compiler and <option>-pie</option>
|
||
linker options. Position Independent Executables are needed to take
|
||
advantage of Address Space Layout Randomization, supported by modern
|
||
kernel versions. While ASLR can already be enforced for data areas in
|
||
the stack and heap (brk and mmap), the code areas must be compiled as
|
||
position-independent. Shared libraries already do this with the
|
||
<varname>pic</varname> flag, so they gain ASLR automatically, but binary
|
||
.text regions need to be build with <varname>pie</varname> to gain ASLR.
|
||
When this happens, ROP attacks are much harder since there are no static
|
||
locations to bounce off of during a memory corruption attack.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
<para>For more in-depth information on these hardening flags and hardening in
|
||
general, refer to the
|
||
<link xlink:href="https://wiki.debian.org/Hardening">Debian Wiki</link>,
|
||
<link xlink:href="https://wiki.ubuntu.com/Security/Features">Ubuntu Wiki</link>,
|
||
<link xlink:href="https://wiki.gentoo.org/wiki/Project:Hardened">Gentoo Wiki</link>,
|
||
and the <link xlink:href="https://wiki.archlinux.org/index.php/DeveloperWiki:Security">
|
||
Arch Wiki</link>.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
</chapter>
|