Merge pull request #76794 from dudebout/document-nix-env-multiple-output-install-bug

document nix-env bug relating to multiple output installation
This commit is contained in:
Silvan Mosberger 2020-09-05 15:40:26 +02:00 committed by GitHub
commit 560bb92473
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 26 deletions

View file

@ -22,39 +22,69 @@
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.
</para>
</note>
<para>
A number of attributes can be used to work with a derivation with multiple outputs. The attribute <varname>outputs</varname> 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 <varname>meta.outputsToInstall</varname> is used to determine the default set of outputs to install when using the derivation name unqualified.
</para>
</section>
<section xml:id="sec-multiple-outputs-installing">
<title>Installing a split package</title>
<para>
When installing a package via <varname>systemPackages</varname> or <command>nix-env</command> you have several options:
When installing a package with multiple outputs, the package's <varname>meta.outputsToInstall</varname> attribute determines which outputs are actually installed. <varname>meta.outputsToInstall</varname> is a list whose <link xlink:href="https://github.com/NixOS/nixpkgs/blob/f1680774340d5443a1409c3421ced84ac1163ba9/pkgs/stdenv/generic/make-derivation.nix#L310-L320">default installs binaries and the associated man pages</link>. The following sections describe ways to install different outputs.
</para>
<itemizedlist>
<listitem>
<para>
You can install particular outputs explicitly, as each is available in the Nix language as an attribute of the package. The <varname>outputs</varname> attribute contains a list of output names.
</para>
</listitem>
<listitem>
<para>
You can let it use the default outputs. These are handled by <varname>meta.outputsToInstall</varname> attribute that contains a list of output names.
</para>
<para>
TODO: more about tweaking the attribute, etc.
</para>
</listitem>
<listitem>
<para>
NixOS provides configuration option <varname>environment.extraOutputsToInstall</varname> that allows adding extra outputs of <varname>environment.systemPackages</varname> atop the default ones. It's mainly meant for documentation and debug symbols, and it's also modified by specific options.
</para>
<note>
<section xml:id="sec-multiple-outputs-installing-nixos">
<title>Selecting outputs to install via NixOS</title>
<para>
NixOS provides two ways to select the outputs to install for packages listed in <varname>environment.systemPackages</varname>:
</para>
<itemizedlist>
<listitem>
<para>
At this moment there is no similar configurability for packages installed by <command>nix-env</command>. You can still use approach from <xref linkend="sec-modify-via-packageOverrides" /> to override <varname>meta.outputsToInstall</varname> attributes, but that's a rather inconvenient way.
The configuration option <varname>environment.extraOutputsToInstall</varname> is appended to each package's <varname>meta.outputsToInstall</varname> attribute to determine the outputs to install. It can for example be used to install <literal>info</literal> documentation or debug symbols for all packages.
</para>
</note>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>
The outputs can be listed as packages in <varname>environment.systemPackages</varname>. For example, the <literal>"out"</literal> and <literal>"info"</literal> outputs for the <varname>coreutils</varname> package can be installed by including <varname>coreutils</varname> and <varname>coreutils.info</varname> in <varname>environment.systemPackages</varname>.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-multiple-outputs-installing-nix-env">
<title>Selecting outputs to install via <command>nix-env</command></title>
<para>
<command>nix-env</command> lacks an easy way to select the outputs to install. When installing a package, <command>nix-env</command> always installs the outputs listed in <varname>meta.outputsToInstall</varname>, even when the user explicitly selects an output.
</para>
<warning>
<para>
<command>nix-env</command> silenty disregards the outputs selected by the user, and instead installs the outputs from <varname>meta.outputsToInstall</varname>. For example,
</para>
<programlisting>$ nix-env -iA nixpkgs.coreutils.info</programlisting>
<para>
installs the <literal>"out"</literal> output (<varname>coreutils.meta.outputsToInstall</varname> is <literal>[ "out" ]</literal>) instead of the requested <literal>"info"</literal>.
</para>
</warning>
<para>
The only recourse to select an output with <command>nix-env</command> is to override the package's <varname>meta.outputsToInstall</varname>, using the functions described in <xref linkend="chap-overrides" />. For example, the following overlay adds the <literal>"info"</literal> output for the <varname>coreutils</varname> package:
</para>
<programlisting>self: super:
{
coreutils = super.coreutils.overrideAttrs (oldAttrs: {
meta = oldAttrs.meta // { outputsToInstall = oldAttrs.meta.outputsToInstall or [ "out" ] ++ [ "info" ]; };
});
}
</programlisting>
</section>
</section>
<section xml:id="sec-multiple-outputs-using-split-packages">
<title>Using a split package</title>

View file

@ -309,8 +309,12 @@ in rec {
name = attrs.name or "${attrs.pname}-${attrs.version}";
# If the packager hasn't specified `outputsToInstall`, choose a default,
# which is the name of `p.bin or p.out or p`;
# if he has specified it, it will be overridden below in `// meta`.
# which is the name of `p.bin or p.out or p` along with `p.man` when
# present.
#
# If the packager has specified it, it will be overridden below in
# `// meta`.
#
# Note: This default probably shouldn't be globally configurable.
# Services and users should specify outputs explicitly,
# unless they are comfortable with this default.