Skip to content

Commit

Permalink
Merge branch 'staging', containing closure-size #7701
Browse files Browse the repository at this point in the history
  • Loading branch information
vcunat committed Apr 13, 2016
2 parents 81cedab + 87b4939 commit 39ebb01
Show file tree
Hide file tree
Showing 882 changed files with 8,951 additions and 2,475 deletions.
1 change: 1 addition & 0 deletions doc/manual.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<xi:include href="introduction.xml" />
<xi:include href="quick-start.xml" />
<xi:include href="stdenv.xml" />
<xi:include href="multiple-output.xml" />
<xi:include href="configuration.xml" />
<xi:include href="functions.xml" />
<xi:include href="meta.xml" />
Expand Down
91 changes: 91 additions & 0 deletions doc/multiple-output.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter [
<!ENTITY ndash "&#x2013;"> <!-- @vcunat likes to use this one ;-) -->
]>
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-multiple-output">

<title>Multiple-output packages</title>

<section><title>Introduction</title>
<para>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.</para>
<para>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.</para>
<note><para>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>
</section>

<section><title>Installing a split package</title>
<para>When installing a package via <varname>systemPackages</varname> or <command>nix-env</command> you have several options:</para>
<warning><para>Currently <command>nix-env</command> almost always installs all outputs until https://github.com/NixOS/nix/pull/815 gets merged.</para></warning>
<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><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.</para></note>
</listitem>
</itemizedlist>
</section>

<section><title>Using a split package</title>
<para>In the Nix language the individual outputs can be reached explicitly as attributes, e.g. <varname>coreutils.info</varname>, but the typical case is just using packages as build inputs.</para>
<para>When a multiple-output derivation gets into a build input of another derivation, the first output is added (<varname>.dev</varname> by convention) and also <varname>propagatedBuildOutputs</varname> of that package which by default contain <varname>$outputBin</varname> and <varname>$outputLib</varname>. (See <xref linkend="multiple-output-file-type-groups" />.)</para>
</section>


<section><title>Writing a split derivation</title>
<para>Here you find how to write a derivation that produces multiple outputs.</para>
<para>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 &lt;<filename>nixpkgs/pkgs/build-support/setup-hooks/multiple-outputs.sh</filename>&gt;; it's relatively well-readable. The whole machinery is triggered by defining the <varname>outputs</varname> attribute to contain the list of desired output names (strings).</para>
<programlisting>outputs = [ "dev" "out" "bin" "doc" ];</programlisting>
<para>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. By convention, the first output should usually be <varname>dev</varname>; typically you also want to have the main <varname>out</varname> output, as it catches any files that didn't get elsewhere.</para>

<note><para>There is a special handling of the <varname>debug</varname> output, described at <xref linkend="stdenv-separateDebugInfo" />.</para></note>

<section xml:id="multiple-output-file-type-groups">
<title>File type groups</title>
<para>The support code currently recognizes some particular kinds of outputs and either instructs the build system of the package to put files into their desired outputs or it moves the files during the fixup phase. Each group of file types has an <varname>outputFoo</varname> variable specifying the output name where they should go. If that variable isn't defined by the derivation writer, it is guessed &ndash; a default output name is defined, falling back to other possibilities if the output isn't defined.</para>
<variablelist>
<varlistentry><term><varname>
$outputDev</varname></term><listitem><para>
is for development-only files. These include C(++) headers, pkg-config, cmake and aclocal files. They go to <varname>dev</varname> or <varname>out</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputBin</varname></term><listitem><para>
is meant for user-facing binaries, typically residing in bin/. They go to <varname>bin</varname> or <varname>out</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputLib</varname></term><listitem><para>
is meant for libraries, typically residing in <filename>lib/</filename> and <filename>libexec/</filename>. They go to <varname>lib</varname> or <varname>out</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputDoc</varname></term><listitem><para>
is for user documentation, typically residing in <filename>share/doc/</filename>. It goes to <varname>doc</varname> or <varname>out</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputDocdev</varname></term><listitem><para>
is for <emphasis>developer</emphasis> documentation. Currently we count gtk-doc and man3 pages in there. It goes to <varname>docdev</varname> or is removed (!) by default. This is because e.g. gtk-doc tends to be rather large and completely unused by nixpkgs users.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputMan</varname></term><listitem><para>
is for man pages (except for section 3). They go to <varname>man</varname> or <varname>doc</varname> or <varname>$outputBin</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputInfo</varname></term><listitem><para>
is for info pages. They go to <varname>info</varname> or <varname>doc</varname> or <varname>$outputMan</varname> by default.
</para></listitem></varlistentry>
</variablelist>
</section>

<section><title>Common caveats</title>
<itemizedlist>
<listitem><para>Some configure scripts don't like some of the parameters passed by default by the framework, e.g. <literal>--docdir=/foo/bar</literal>. You can disable this by setting <literal>setOutputFlags = false;</literal>.</para></listitem>
<listitem><para>The outputs of a single derivation can retain references to each other, but note that circular references are not allowed. (And each strongly-connected component would act as a single output anyway.)</para></listitem>
<listitem><para>Most of split packages contain their core functionality in libraries. These libraries tend to refer to various kind of data that typically gets into <varname>out</varname>, e.g. locale strings, so there is often no advantage in separating the libraries into <varname>lib</varname>, as keeping them in <varname>out</varname> is easier.</para></listitem>
<listitem><para>Some packages have hidden assumptions on install paths, which complicates splitting.</para></listitem>
</itemizedlist>
</section>

</section><!--Writing a split derivation-->

</chapter>

2 changes: 1 addition & 1 deletion doc/stdenv.xml
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ following:
phase.</para></listitem>
</varlistentry>

<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
Expand Down
2 changes: 1 addition & 1 deletion lib/customisation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ rec {
};

outputsList = map outputToAttrListElement outputs;
in commonAttrs.${drv.outputName};
in commonAttrs // { outputUnspecified = true; };


/* Strip a derivation of all non-essential attributes, returning
Expand Down
4 changes: 3 additions & 1 deletion lib/strings.nix
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ rec {
makeLibraryPath [ pkgs.openssl pkgs.zlib ]
=> "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r/lib:/nix/store/wwh7mhwh269sfjkm6k5665b5kgp7jrk2-zlib-1.2.8/lib"
*/
makeLibraryPath = makeSearchPath "lib";
makeLibraryPath = pkgs: makeSearchPath "lib"
# try to guess the right output of each pkg
(map (pkg: pkg.lib or (pkg.out or pkg)) pkgs);

/* Construct a binary search path (such as $PATH) containing the
binaries for a set of packages.
Expand Down
2 changes: 1 addition & 1 deletion nixos/doc/manual/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ let
echo "for hints about the offending path)."
exit 1
fi
${libxslt}/bin/xsltproc \
${libxslt.bin}/bin/xsltproc \
--stringparam revision '${revision}' \
-o $out ${./options-to-docbook.xsl} $optionsXML
'';
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/config/debug-info.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ with lib;
# environment.pathsToLink, and we can't have both.
#environment.pathsToLink = [ "/lib/debug/.build-id" ];

environment.outputsToLink =
environment.extraOutputsToInstall =
optional config.environment.enableDebugInfo "debug";

};
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/config/fonts/fontconfig.nix
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ with lib;
# Versioned fontconfig > 2.10. Take shared fonts.conf from fontconfig.
# Otherwise specify only font directories.
environment.etc."fonts/${pkgs.fontconfig.configVersion}/fonts.conf".source =
"${pkgs.fontconfig}/etc/fonts/fonts.conf";
"${pkgs.fontconfig.out}/etc/fonts/fonts.conf";

environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/00-nixos.conf".text =
let
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/config/networking.nix
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ in
"protocols".source = pkgs.iana_etc + "/etc/protocols";

# /etc/rpc: RPC program numbers.
"rpc".source = pkgs.glibc + "/etc/rpc";
"rpc".source = pkgs.glibc.out + "/etc/rpc";

# /etc/hosts: Hostname-to-IP mappings.
"hosts".text =
Expand Down
8 changes: 4 additions & 4 deletions nixos/modules/config/pulseaudio.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ let
# are built with PulseAudio support (like KDE).
clientConf = writeText "client.conf" ''
autospawn=${if nonSystemWide then "yes" else "no"}
${optionalString nonSystemWide "daemon-binary=${cfg.package}/bin/pulseaudio"}
${optionalString nonSystemWide "daemon-binary=${cfg.package.out}/bin/pulseaudio"}
'';

# Write an /etc/asound.conf that causes all ALSA applications to
Expand Down Expand Up @@ -130,11 +130,11 @@ in {
source = clientConf;
};

hardware.pulseaudio.configFile = mkDefault "${cfg.package}/etc/pulse/default.pa";
hardware.pulseaudio.configFile = mkDefault "${cfg.package.out}/etc/pulse/default.pa";
}

(mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
environment.systemPackages = [ cfg.package.out ];

environment.etc = singleton {
target = "asound.conf";
Expand Down Expand Up @@ -195,7 +195,7 @@ in {
environment.PULSE_RUNTIME_PATH = stateDir;
serviceConfig = {
Type = "notify";
ExecStart = "${cfg.package}/bin/pulseaudio --daemonize=no --log-level=${cfg.daemon.logLevel} --system -n --file=${cfg.configFile}";
ExecStart = "${cfg.package.out}/bin/pulseaudio --daemonize=no --log-level=${cfg.daemon.logLevel} --system -n --file=${cfg.configFile}";
Restart = "on-failure";
};
};
Expand Down
11 changes: 6 additions & 5 deletions nixos/modules/config/system-path.nix
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ in
description = "List of directories to be symlinked in <filename>/run/current-system/sw</filename>.";
};

outputsToLink = mkOption {
extraOutputsToInstall = mkOption {
type = types.listOf types.str;
default = [];
example = [ "doc" ];
description = "List of package outputs to be symlinked into <filename>/run/current-system/sw</filename>.";
default = [ ];
example = [ "doc" "info" "docdev" ];
description = "List of additional package outputs to be symlinked into <filename>/run/current-system/sw</filename>.";
};

};
Expand Down Expand Up @@ -123,9 +123,10 @@ in
system.path = pkgs.buildEnv {
name = "system-path";
paths = config.environment.systemPackages;
inherit (config.environment) pathsToLink outputsToLink;
inherit (config.environment) pathsToLink extraOutputsToInstall;
ignoreCollisions = true;
# !!! Hacky, should modularise.
# outputs TODO: note that the tools will often not be linked by default
postBuild =
''
if [ -x $out/bin/update-mime-database -a -w $out/share/mime ]; then
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/installer/tools/auto-upgrade.nix
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ let cfg = config.system.autoUpgrade; in
HOME = "/root";
};

path = [ pkgs.gnutar pkgs.xz config.nix.package ];
path = [ pkgs.gnutar pkgs.xz.bin config.nix.package ];

script = ''
${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch ${toString cfg.flags}
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/profiles/base.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
# Tools to create / manipulate filesystems.
pkgs.ntfsprogs # for resizing NTFS partitions
pkgs.dosfstools
pkgs.xfsprogs
pkgs.xfsprogs.bin
pkgs.jfsutils
pkgs.f2fs-tools

Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/programs/man.nix
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ with lib;

environment.pathsToLink = [ "/share/man" ];

environment.outputsToLink = [ "man" ];
environment.extraOutputsToInstall = [ "man" ];

};

Expand Down
4 changes: 2 additions & 2 deletions nixos/modules/programs/xfs_quota.nix
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ in
nameValuePair "xfs_quota-${name}" {
description = "Setup xfs_quota for project ${name}";
script = ''
${pkgs.xfsprogs}/bin/xfs_quota -x -c 'project -s ${name}' ${opts.fileSystem}
${pkgs.xfsprogs}/bin/xfs_quota -x -c 'limit -p ${limitOptions opts} ${name}' ${opts.fileSystem}
${pkgs.xfsprogs.bin}/bin/xfs_quota -x -c 'project -s ${name}' ${opts.fileSystem}
${pkgs.xfsprogs.bin}/bin/xfs_quota -x -c 'limit -p ${limitOptions opts} ${name}' ${opts.fileSystem}
'';

wantedBy = [ "multi-user.target" ];
Expand Down
6 changes: 3 additions & 3 deletions nixos/modules/security/apparmor-suid.nix
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ with lib;
capability setuid,
network inet raw,
${pkgs.glibc}/lib/*.so mr,
${pkgs.libcap}/lib/libcap.so* mr,
${pkgs.attr}/lib/libattr.so* mr,
${pkgs.glibc.out}/lib/*.so mr,
${pkgs.libcap.out}/lib/libcap.so* mr,
${pkgs.attr.out}/lib/libattr.so* mr,
${pkgs.iputils}/bin/ping mixr,
/var/setuid-wrappers/ping.real r,
Expand Down
8 changes: 4 additions & 4 deletions nixos/modules/security/polkit.nix
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ in

config = mkIf cfg.enable {

environment.systemPackages = [ pkgs.polkit ];
environment.systemPackages = [ pkgs.polkit.bin pkgs.polkit.out ];

systemd.packages = [ pkgs.polkit ];
systemd.packages = [ pkgs.polkit.out ];

systemd.services.polkit.restartTriggers = [ config.system.path ];
systemd.services.polkit.unitConfig.X-StopIfChanged = false;
Expand All @@ -79,7 +79,7 @@ in
${cfg.extraConfig}
''; #TODO: validation on compilation (at least against typos)

services.dbus.packages = [ pkgs.polkit ];
services.dbus.packages = [ pkgs.polkit.out ];

security.pam.services.polkit-1 = {};

Expand All @@ -90,7 +90,7 @@ in
owner = "root";
group = "root";
setuid = true;
source = "${pkgs.polkit}/lib/polkit-1/polkit-agent-helper-1";
source = "${pkgs.polkit.out}/lib/polkit-1/polkit-agent-helper-1";
}
];

Expand Down
4 changes: 2 additions & 2 deletions nixos/modules/security/setuid-wrappers.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ let

setuidWrapper = pkgs.stdenv.mkDerivation {
name = "setuid-wrapper";
buildCommand = ''
unpackPhase = "true";
installPhase = ''
mkdir -p $out/bin
cp ${./setuid-wrapper.c} setuid-wrapper.c
gcc -Wall -O2 -DWRAPPER_DIR=\"${wrapperDir}\" \
setuid-wrapper.c -o $out/bin/setuid-wrapper
strip -S $out/bin/setuid-wrapper
'';
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,11 @@ in {
'';

postStart = ''
until ${pkgs.curl}/bin/curl -s -L ${cfg.listenAddress}:${toString cfg.port}${cfg.prefix} ; do
until ${pkgs.curl.bin}/bin/curl -s -L ${cfg.listenAddress}:${toString cfg.port}${cfg.prefix} ; do
sleep 10
done
while true ; do
index=`${pkgs.curl}/bin/curl -s -L ${cfg.listenAddress}:${toString cfg.port}${cfg.prefix}`
index=`${pkgs.curl.bin}/bin/curl -s -L ${cfg.listenAddress}:${toString cfg.port}${cfg.prefix}`
if [[ !("$index" =~ 'Please wait while Jenkins is restarting' ||
"$index" =~ 'Please wait while Jenkins is getting ready to work') ]]; then
exit 0
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/services/databases/openldap.nix
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ in
mkdir -p ${cfg.dataDir}
chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}
'';
serviceConfig.ExecStart = "${openldap}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -f ${configFile}";
serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -f ${configFile}";
};

users.extraUsers.openldap =
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/services/desktops/gnome3/gvfs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ in

services.dbus.packages = [ gnome3.gvfs ];

services.udev.packages = [ pkgs.libmtp ];
services.udev.packages = [ pkgs.libmtp.bin ];

};

Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/services/hardware/udev.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ let
run_progs=$(grep -v '^[[:space:]]*#' $out/* | grep 'RUN+="[^/$]' |
sed -e 's/.*RUN+="\([^ "]*\)[ "].*/\1/' | uniq)
for i in $import_progs $run_progs; do
if [[ ! -x ${pkgs.udev}/lib/udev/$i && ! $i =~ socket:.* ]]; then
if [[ ! -x ${udev}/lib/udev/$i && ! $i =~ socket:.* ]]; then
echo "FAIL"
echo "$i is called in udev rules but not installed by udev"
exit 1
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/services/hardware/upower.nix
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ in

systemd.services.upower =
{ description = "Power Management Daemon";
path = [ pkgs.glib ]; # needed for gdbus
path = [ pkgs.glib.out ]; # needed for gdbus
serviceConfig =
{ Type = "dbus";
BusName = "org.freedesktop.UPower";
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/services/misc/docker-registry.nix
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ in {
};

postStart = ''
until ${pkgs.curl}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/'; do
until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/'; do
sleep 1;
done
'';
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/services/misc/nix-daemon.nix
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ in
systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ];

systemd.services.nix-daemon =
{ path = [ nix pkgs.openssl pkgs.utillinux config.programs.ssh.package ]
{ path = [ nix pkgs.openssl.bin pkgs.utillinux config.programs.ssh.package ]
++ optionals cfg.distributedBuilds [ pkgs.gzip ];

environment = cfg.envVars
Expand Down
Loading

0 comments on commit 39ebb01

Please sign in to comment.