Home Explore Blog CI



nixpkgs

1st chunk of `doc/stdenv/multiple-output.chapter.md`
6e94e983d65223f6e5d983c2af31671a3445e2bd6981e23500000001000010b7
# Multiple-output packages {#chap-multiple-output}

The Nix language allows a derivation to produce multiple outputs, which is similar to what is utilized by other Linux distribution packaging systems. The outputs reside in separate Nix store paths, so they can be mostly handled independently of each other, including passing to build inputs, garbage collection or binary substitution. The exception is that building from source always produces all the outputs.

The main motivation is to save disk space by reducing runtime closure sizes; consequently also sizes of substituted binaries get reduced. Splitting can be used to have more granular runtime dependencies, for example the typical reduction is to split away development-only files, as those are typically not needed during runtime. As a result, closure sizes of many packages can get reduced to a half or even much less.

::: {.note}
The reduction effects could be instead achieved by building the parts in completely separate derivations. That would often additionally reduce build-time closures, but it tends to be much harder to write such derivations, as build systems typically assume all parts are being built at once. This compromise approach of single source package producing multiple binary packages is also utilized often by rpm and deb.
:::

A number of attributes can be used to work with a derivation with multiple outputs.
The attribute `outputs` is a list of strings, which are the names of the outputs.
For each of these names, an identically named attribute is created, corresponding to that output.

The attribute `meta.outputsToInstall` is used to determine the [default set of outputs to install](https://github.com/NixOS/nixpkgs/blob/08c3198f1c6fd89a09f8f0ea09b425028a34de3e/pkgs/stdenv/generic/check-meta.nix#L411-L426) when using the derivation name unqualified:
`bin`, or `out`, or the first specified output; as well as `man` if that is specified.

## Using a split package {#sec-multiple-outputs-using-split-packages}

In the Nix language the individual outputs can be reached explicitly as attributes, e.g. `coreutils.info`, but the typical case is just using packages as build inputs.

When a multiple-output derivation gets into a build input of another derivation, the `dev` output is added if it exists, otherwise the first output is added. In addition to that, `propagatedBuildOutputs` of that package which by default contain `$outputBin` and `$outputLib` are also added. (See [](#multiple-output-file-type-groups).)

In some cases it may be desirable to combine different outputs under a single store path. The `symlinkJoin` builder can be used to do this. (See [](#trivial-builder-symlinkJoin)). Note that this may negate some closure size benefits of using a multiple-output package.

## Writing a split derivation {#sec-multiple-outputs-}

Here you find how to write a derivation that produces multiple outputs.

In nixpkgs there is a framework supporting multiple-output derivations. It tries to cover most cases by default behavior. You can find the source separated in `<nixpkgs/pkgs/build-support/setup-hooks/multiple-outputs.sh>`; it’s relatively well-readable. The whole machinery is triggered by defining the `outputs` attribute to contain the list of desired output names (strings).

```nix
{
  outputs = [
    "bin"
    "dev"
    "out"
    "doc"
  ];
}
```

Often such a single line is enough. For each output an equally named environment variable is passed to the builder and contains the path in nix store for that output. Typically you also want to have the main `out` output, as it catches any files that didn’t get elsewhere.

::: {.note}
There is a special handling of the `debug` output, described at [](#stdenv-separateDebugInfo).
:::

### “Binaries first” {#multiple-output-file-binaries-first-convention}

A commonly adopted convention in `nixpkgs` is that executables provided by the package are contained within its first output. This convention allows the dependent packages to reference the executables provided by packages in a uniform manner. For instance, provided with the knowledge that the `perl` package contains a `perl` executable it can be referenced as `${pkgs.perl}/bin/perl` within a Nix derivation that needs to execute a Perl script.

Title: Multiple-Output Packages in Nix
Summary
This section explains how Nix allows derivations to produce multiple outputs, similar to other Linux packaging systems. This is motivated by saving disk space and reducing runtime closure sizes. The `outputs` attribute lists the output names, and the `meta.outputsToInstall` attribute determines the default outputs to install. When a multiple-output derivation is used as a build input, the `dev` output is added if it exists, otherwise the first output is added. The `symlinkJoin` builder can be used to combine different outputs under a single store path. Nixpkgs provides a framework for supporting multiple-output derivations, triggered by defining the `outputs` attribute. A common convention is to place executables in the first output for easy referencing.