Skip to content

mkDerivation helper

pkgs/stdenv/generic/setup.sh genericBuild

The derivation function is the foundation for packaging in Nix. However, several helper functions are provided. The most general of which is mkDerivation. This provides a default builder, which first reads in the stdenv script, then calls genericBuild. The build script is organized into multiple phases, which can be overridden (define the attribute and provide a multi-line string) or skipped by setting one of the dont<phase> attributes (source).

This default builder handles autotools-, cmake- and meson-based projects, and extensive customization is possible by overridding the relevant phase(s).

Warning

mkDerivation is great for building many kinds of packages, especially autotools-, cmake- and meson-based projects. However, language- and/or framework-specific helpers exist, among others for Python and Rust.

Example - building a meson project

Example - overriding a phase

The default builder just sources the stdenv and calls genericBuild:

mkDerivation - default-builder.sh
source $stdenv/setup
genericBuild

Note

$stdenv points to the path of the stdenv derivation in the nix store. Hence source $stdenv/setup reads in the setup script of the stdenv derivation.

We can override parts of the genericBuild script by redefining one or more of the standard phases, e.g. to redefine the installPhase:

example, redefine install phase
mkDerivation {
  pname = "foo";
  version = "1.0.0";
  src = ... # provide some source code
  installPhase = ''
    cp my-script.sh $out/my-script.sh
  '';
};

This works well for shorter snippets. For longer scripts, consider writing your own builder script which still delegates to genericBuild.

Here is a minimal example:

my-builder.sh
source $stdenv/setup

cpfn() {
  # usage: cpfn <fn name> <new fn name>
  # redefine function under new name, a poor man's rename
  local old_def=$(declare -f $1)
  local new_def="$2${old_def#$1}"
  eval "$new_def"
}

cpfn buildPhase oldBuildPhase

buildPhase() {
  echo "before building"
  oldBuildPhase
  echo "after building"
}

genericBuild

Warning

Don't wrap buildPhase (or any other phase) in this way. Each phase already provides pre- and post-hooks which can be used. All hooks follow the same naming convention, for buildPhase the hooks are preBuild & postBuild, for fixupPhase they are preFixup & postFixup.

To use this builder, simply set the builder attribute of mkDerivation: builder=./my-builder.sh:

example derivation
mkDerivation = {
  pname = "foo";
  version = "1.0.0";
  src = ...; # provide path to local tarball, git repo URL or similar
  builder = ./my-builder.sh;
};