diff options
56 files changed, 527 insertions, 511 deletions
diff --git a/doc/manual/advanced-topics/advanced-topics.xml b/doc/manual/advanced-topics/advanced-topics.xml new file mode 100644 index 000000000000..338aa6f3a238 --- /dev/null +++ b/doc/manual/advanced-topics/advanced-topics.xml @@ -0,0 +1,10 @@ +<part xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0"> + +<title>Advanced Topics</title> + +<xi:include href="distributed-builds.xml" /> + +</part> diff --git a/doc/manual/builds/enabling-builds.xml b/doc/manual/advanced-topics/distributed-builds.xml index 4b45812ee918..70f396f81cdb 100644 --- a/doc/manual/builds/enabling-builds.xml +++ b/doc/manual/advanced-topics/distributed-builds.xml @@ -2,9 +2,18 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0" - xml:id="ch-enabling-builds"> + xml:id='chap-distributed-builds'> -<title>Enabling Distributed Builds</title> +<title>Distributed Builds</title> + +<para>Nix supports distributed builds, where a local Nix installation can +forward Nix builds to other machines over the network. This allows +multiple builds to be performed in parallel (thus improving +performance) and allows Nix to perform multi-platform builds in a +semi-transparent way. For instance, if you perform a build for a +<literal>powerpc-darwin</literal> on an <literal>i686-linux</literal> +machine, Nix can automatically forward the build to a +<literal>powerpc-darwin</literal> machine, if available.</para> <para>You can enable distributed builds by setting the environment variable <envar>NIX_BUILD_HOOK</envar> to point to a program that Nix @@ -41,7 +50,7 @@ example configuration is shown in <xref linkend='ex-remote-systems' bits of information: <orderedlist> - + <listitem><para>The name of the remote machine, with optionally the user under which the remote build should be performed. This is actually passed as an argument to <command>ssh</command>, so it can @@ -73,9 +82,9 @@ bits of information: <filename>build-remote.pl</filename> will only perform the derivation on a machine that has the specified features. For instance, the attribute - + <programlisting> -requiredSystemFeatures = [ "kvm" ]; +requiredSystemFeatures = [ "kvm" ]; </programlisting> will cause the build to be performed on a machine that has the @@ -103,4 +112,4 @@ running, they should use the same <envar>NIX_CURRENT_LOAD</envar> file. Maybe in the future <filename>build-remote.pl</filename> will look at the actual remote load.</para> -</chapter> \ No newline at end of file +</chapter> diff --git a/doc/manual/builds/build-farm.xml b/doc/manual/builds/build-farm.xml deleted file mode 100644 index e0e9f10f1173..000000000000 --- a/doc/manual/builds/build-farm.xml +++ /dev/null @@ -1,22 +0,0 @@ -<part xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id='chap-distributed-builds'> - -<title>Distributed Builds</title> - -<partintro> -<para>Nix supports distributed builds, where a local Nix installation can -forward Nix builds to other machines over the network. This allows -multiple builds to be performed in parallel (thus improving -performance) and allows Nix to perform multi-platform builds in a -semi-transparent way. For instance, if you perform a build for a -<literal>powerpc-darwin</literal> on an <literal>i686-linux</literal> -machine, Nix can automatically forward the build to a -<literal>powerpc-darwin</literal> machine, if available.</para> -</partintro> - -<xi:include href="enabling-builds.xml" /> - -</part> diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml index a7539c4c7e40..053f4d43cb0c 100644 --- a/doc/manual/command-ref/conf-file.xml +++ b/doc/manual/command-ref/conf-file.xml @@ -348,7 +348,7 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> <listitem><para>A list of URLs of binary caches, separated by whitespace. The default is - <literal>http://cache.nixos.org</literal>.</para></listitem> + <literal>https://cache.nixos.org</literal>.</para></listitem> </varlistentry> @@ -402,6 +402,15 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> </varlistentry> + <varlistentry><term><literal>verify-https-binary-caches</literal></term> + + <listitem><para>Whether HTTPS binary caches are required to have a + certificate that can be verified. Defaults to + <literal>true</literal>.</para></listitem> + + </varlistentry> + + <varlistentry><term><literal>force-manifest</literal></term> <listitem><para>If this option is set to <literal>false</literal> diff --git a/doc/manual/command-ref/nix-channel.xml b/doc/manual/command-ref/nix-channel.xml index c4cc04ce24d8..b777c6b6b73c 100644 --- a/doc/manual/command-ref/nix-channel.xml +++ b/doc/manual/command-ref/nix-channel.xml @@ -33,8 +33,8 @@ <para>A Nix channel is mechanism that allows you to automatically stay up-to-date with a set of pre-built Nix expressions. A Nix channel is -just a URL that points to a place containing a set of Nix expressions -and a <command>nix-push</command> manifest. <phrase +just a URL that points to a place containing both a set of Nix +expressions and a pointer to a binary cache. <phrase condition="manual">See also <xref linkend="sec-channels" />.</phrase></para> @@ -99,13 +99,6 @@ an update.</para> <para>The list of subscribed channels is stored in <filename>~/.nix-channels</filename>.</para> -<para>A channel consists of two elements: a bzipped Tar archive -containing the Nix expressions, and a manifest created by -<command>nix-push</command>. These must be stored under -<literal><replaceable>url</replaceable>/nixexprs.tar.bz2</literal> and -<literal><replaceable>url</replaceable>/MANIFEST</literal>, -respectively.</para> - </refsection> <refsection><title>Examples</title> @@ -163,4 +156,49 @@ $ nix-instantiate --eval -E '(import <nixpkgs> {}).lib.nixpkgsVersion' </refsection> +<refsection><title>Channel format</title> + +<para>A channel URL should point to a directory containing the +following files:</para> + +<variablelist> + + <varlistentry><term><filename>nixexprs.tar.xz</filename></term> + + <listitem><para>A tarball containing Nix expressions and files + referenced by them (such as build scripts and patches). At + top-level, the tarball should contain a single directory. That + directory must contain a file <filename>default.nix</filename> + that serves as the channel’s “entry point”.</para></listitem> + + </varlistentry> + + <varlistentry><term><filename>binary-cache-url</filename></term> + + <listitem><para>A file containing the URL to a binary cache (such + as <uri>https://cache.nixos.org</uri>. Nix will automatically + check this cache for pre-built binaries, if the user has + sufficient rights to add binary caches. For instance, in a + multi-user Nix setup, the binary caches provided by the channels + of the root user are used automatically, but caches corresponding + to the channels of non-root users are ignored. Binary caches can + be created and maintained using + <command>nix-push</command>.</para></listitem> + + </varlistentry> + + <varlistentry><term><filename>MANIFEST.bz2</filename></term> + + <listitem><para>(Deprecated in favour of binary caches.) A + manifest as created by <command>nix-push</command>. Only used if + <filename>binary-cache-url</filename> is not present or if the + <filename>nix.conf</filename> option + <option>force-manifest</option> is set.</para></listitem> + + </varlistentry> + +</variablelist> + +</refsection> + </refentry> diff --git a/doc/manual/command-ref/nix-install-package.xml b/doc/manual/command-ref/nix-install-package.xml index 7d5cd996e44a..f7802a95d55e 100644 --- a/doc/manual/command-ref/nix-install-package.xml +++ b/doc/manual/command-ref/nix-install-package.xml @@ -3,7 +3,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0" xml:id="sec-nix-install-package"> - + <refmeta> <refentrytitle>nix-install-package</refentrytitle> <manvolnum>1</manvolnum> @@ -47,8 +47,7 @@ <para>The command <command>nix-install-package</command> interactively installs a Nix Package file (<filename>*.nixpkg</filename>), which is a small file that contains a store path to be installed along with the -URL of a <link linkend="sec-nix-push"><command>nix-push</command> -manifest</link>. The Nix Package file is either +URL of a binary cache. The Nix Package file is either <replaceable>file</replaceable>, or automatically downloaded from <replaceable>url</replaceable> if the <option>--url</option> switch is used.</para> @@ -76,7 +75,7 @@ to restart itself with <command>xterm</command>, <refsection><title>Options</title> <variablelist> - + <varlistentry><term><option>--non-interactive</option></term> <listitem><para>Do not open a new terminal window and do not ask @@ -139,14 +138,14 @@ The elements are as follows: <variablelist> <varlistentry><term><literal>NIXPKG1</literal></term> - + <listitem><para>The version of the Nix Package file.</para></listitem> </varlistentry> <varlistentry><term><replaceable>manifestURL</replaceable></term> - + <listitem><para>The manifest to be pulled by <command>nix-pull</command>. The manifest must contain <replaceable>outPath</replaceable>.</para></listitem> @@ -154,21 +153,21 @@ The elements are as follows: </varlistentry> <varlistentry><term><replaceable>name</replaceable></term> - + <listitem><para>The symbolic name and version of the package.</para></listitem> </varlistentry> <varlistentry><term><replaceable>system</replaceable></term> - + <listitem><para>The platform identifier of the platform for which this binary package is intended.</para></listitem> </varlistentry> <varlistentry><term><replaceable>drvPath</replaceable></term> - + <listitem><para>The path in the Nix store of the derivation from which <replaceable>outPath</replaceable> was built. Not currently used.</para></listitem> @@ -176,17 +175,21 @@ The elements are as follows: </varlistentry> <varlistentry><term><replaceable>outPath</replaceable></term> - - <listitem><para>The path in the Nix store of the package. After - <command>nix-install-package</command> has obtained the manifest - from <replaceable>manifestURL</replaceable>, it performs a - <literal>nix-env -i</literal> <replaceable>outPath</replaceable> - to install the binary package.</para></listitem> + + <listitem><para>The path in the Nix store of the + package.</para></listitem> + + </varlistentry> + + <varlistentry><term><replaceable>binaryCacheURL</replaceable></term> + + <listitem><para>The URL of a binary cache containing the closure + of <replaceable>outPath</replaceable>.</para></listitem> </varlistentry> </variablelist> - + </para> <para>An example follows: diff --git a/doc/manual/command-ref/nix-pull.xml b/doc/manual/command-ref/nix-pull.xml index 598c651b5091..eb471677b63f 100644 --- a/doc/manual/command-ref/nix-pull.xml +++ b/doc/manual/command-ref/nix-pull.xml @@ -13,7 +13,7 @@ <refnamediv> <refname>nix-pull</refname> - <refpurpose>pull substitutes from a network cache</refpurpose> + <refpurpose>register availability of pre-built binaries (deprecated)</refpurpose> </refnamediv> <refsynopsisdiv> @@ -26,6 +26,9 @@ <refsection><title>Description</title> +<note><para>This command and the use of manifests is deprecated. It is +better to use binary caches.</para></note> + <para>The command <command>nix-pull</command> obtains a list of pre-built store paths from the URL <replaceable>url</replaceable>, and for each of these store paths, registers a substitute derivation that @@ -43,7 +46,7 @@ with the files created by <replaceable>nix-push</replaceable>.</para> <refsection><title>Examples</title> <screen> -$ nix-pull http://nix.cs.uu.nl/dist/nix/nixpkgs-0.5pre753/MANIFEST</screen> +$ nix-pull https://nixos.org/releases/nixpkgs/nixpkgs-15.05pre54468.69858d7/MANIFEST</screen> </refsection> diff --git a/doc/manual/command-ref/nix-push.xml b/doc/manual/command-ref/nix-push.xml index c19f44a615a8..a3a3c9623e3c 100644 --- a/doc/manual/command-ref/nix-push.xml +++ b/doc/manual/command-ref/nix-push.xml @@ -260,7 +260,7 @@ The properties that are currently supported are: <listitem><para>Each binary cache has a priority (defaulting to 50). Binary caches are checked for binaries in order of ascending priority; thus a higher number denotes a lower priority. The - binary cache <uri>http://cache.nixos.org</uri> has priority + binary cache <uri>https://cache.nixos.org</uri> has priority 40.</para></listitem> </varlistentry> @@ -278,14 +278,14 @@ URL <replaceable>url</replaceable> has a binary for <replaceable>p</replaceable>, Nix fetches <replaceable>url/h</replaceable>, where <replaceable>h</replaceable> is the hash part of <replaceable>p</replaceable>. Thus, if we have a -cache <uri>http://cache.nixos.org</uri> and we want to obtain -the store path +cache <uri>https://cache.nixos.org</uri> and we want to obtain the +store path <screen> /nix/store/a8922c0h87iilxzzvwn2hmv8x210aqb9-glibc-2.7 </screen> then Nix will attempt to fetch <screen> -http://cache.nixos.org/a8922c0h87iilxzzvwn2hmv8x210aqb9.narinfo +https://cache.nixos.org/a8922c0h87iilxzzvwn2hmv8x210aqb9.narinfo </screen> (Commands such as <command>nix-env -qas</command> will issue an HTTP HEAD request, since it only needs to know if the @@ -389,7 +389,7 @@ The fields are as follows: references exist (e.g., <filename>/nix/store/2ma2k0ys8knh4an48n28vigcmc2z8773-linux-headers-2.6.23.16</filename>), Nix will fetch <screen> -http://cache.nixos.org/nar/0zzjpdz46mdn74v09m053yczlz4am038g8r74iy8w43gx8801h70.nar.bz2 +https://cache.nixos.org/nar/0zzjpdz46mdn74v09m053yczlz4am038g8r74iy8w43gx8801h70.nar.bz2 </screen> and decompress and unpack it to <filename>/nix/store/a8922c0h87iilxzzvwn2hmv8x210aqb9-glibc-2.7</filename>.</para> diff --git a/doc/manual/command-ref/utilities.xml b/doc/manual/command-ref/utilities.xml index d5650fd38f43..be2fe6e2d235 100644 --- a/doc/manual/command-ref/utilities.xml +++ b/doc/manual/command-ref/utilities.xml @@ -13,7 +13,9 @@ work with Nix.</para> <xi:include href="nix-collect-garbage.xml" /> <xi:include href="nix-copy-closure.xml" /> <xi:include href="nix-daemon.xml" /> +<!-- <xi:include href="nix-generate-patches.xml" /> +--> <xi:include href="nix-hash.xml" /> <xi:include href="nix-install-package.xml" /> <xi:include href="nix-instantiate.xml" /> @@ -21,4 +23,4 @@ work with Nix.</para> <xi:include href="nix-pull.xml" /> <xi:include href="nix-push.xml" /> -</chapter> \ No newline at end of file +</chapter> diff --git a/doc/manual/expressions/custom-builder.xml b/doc/manual/expressions/custom-builder.xml deleted file mode 100644 index c26deac40f4a..000000000000 --- a/doc/manual/expressions/custom-builder.xml +++ /dev/null @@ -1,26 +0,0 @@ -<section xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id="sec-custom-builder"> - -<title>Customizing the Generic Builder</title> - -<para>The operation of the generic builder can be modified in many -places by setting certain variables. These <emphasis>hook -variables</emphasis> are typically set to the name of some shell -function defined by you. For instance, to perform some additional -steps after <command>make install</command> you would set the -<varname>postInstall</varname> variable: - -<programlisting> -postInstall=myPostInstall - -myPostInstall() { - mkdir $out/share/extra - cp extrafiles/* $out/share/extra -}</programlisting> - -</para> - -</section> \ No newline at end of file diff --git a/doc/manual/expressions/debug-build.xml b/doc/manual/expressions/debug-build.xml index 508cb2c1930e..0c1f4e6719b2 100644 --- a/doc/manual/expressions/debug-build.xml +++ b/doc/manual/expressions/debug-build.xml @@ -6,13 +6,14 @@ <title>Debugging Build Failures</title> -<para>At the beginning of each phase, the set of all shell variables -is written to the file <filename>env-vars</filename> at the top-level -build directory. This is useful for debugging: it allows you to -recreate the environment in which a build was performed. For -instance, if a build fails, then assuming you used the -<option>-K</option> flag, you can go to the output directory and -<quote>switch</quote> to the environment of the builder: +<para>At the beginning of each phase of the build (such as unpacking, +building or installing), the set of all shell variables is written to +the file <filename>env-vars</filename> at the top-level build +directory. This is useful for debugging: it allows you to recreate +the environment in which a build was performed. For instance, if a +build fails, then assuming you used the <option>-K</option> flag, you +can go to the output directory and <quote>switch</quote> to the +environment of the builder: <screen> $ nix-build -K ./foo.nix @@ -30,4 +31,4 @@ $ make </para> -</section> \ No newline at end of file +</section> diff --git a/doc/manual/expressions/derivations.xml b/doc/manual/expressions/derivations.xml index b57c33f4e3a9..90e2786faaab 100644 --- a/doc/manual/expressions/derivations.xml +++ b/doc/manual/expressions/derivations.xml @@ -110,12 +110,12 @@ buildInputs = [ pkg pkg.headers ]; </itemizedlist> -<para>The function <function>mkDerivation</function> in the standard -environment is a wrapper around <function>derivation</function> that -adds a default value for <varname>system</varname> and always uses -Bash as the builder, to which the supplied builder is passed as a -command-line argument. See <xref linkend='sec-standard-environment' -/>.</para> +<para>The function <function>mkDerivation</function> in the Nixpkgs +standard environment is a wrapper around +<function>derivation</function> that adds a default value for +<varname>system</varname> and always uses Bash as the builder, to +which the supplied builder is passed as a command-line argument. See +the Nixpkgs manual for details.</para> <para>The builder is executed as follows: @@ -208,4 +208,4 @@ command-line argument. See <xref linkend='sec-standard-environment' <xi:include href="advanced-attributes.xml" /> -</section> \ No newline at end of file +</section> diff --git a/doc/manual/expressions/generic-builder.xml b/doc/manual/expressions/generic-builder.xml index f8567a042d47..db7ff405d8b1 100644 --- a/doc/manual/expressions/generic-builder.xml +++ b/doc/manual/expressions/generic-builder.xml @@ -71,7 +71,7 @@ genericBuild <co xml:id='ex-hello-builder2-co-3' /></programlisting> generic builder is smart enough to figure out whether to unpack the sources using <command>gzip</command>, <command>bzip2</command>, etc. It can be customised in many ways; - see <xref linkend='sec-standard-environment' />.</para> + see the Nixpkgs manual for details.</para> </callout> @@ -95,4 +95,4 @@ In fact, <varname>mkDerivation</varname> provides a default builder that looks exactly like that, so it is actually possible to omit the builder for Hello entirely.</para> -</section> \ No newline at end of file +</section> diff --git a/doc/manual/expressions/simple-building-testing.xml b/doc/manual/expressions/simple-building-testing.xml index cc90409b5e93..e0dd98b7e67e 100644 --- a/doc/manual/expressions/simple-building-testing.xml +++ b/doc/manual/expressions/simple-building-testing.xml @@ -83,4 +83,6 @@ Just pass the option <link linkend='opt-max-jobs'><option>-j in parallel, or set. Typically this should be the number of CPUs.</para> -</section> \ No newline at end of file +<xi:include href="debug-build.xml" /> + +</section> diff --git a/doc/manual/expressions/standard-env.xml b/doc/manual/expressions/standard-env.xml deleted file mode 100644 index 2571f43fccba..000000000000 --- a/doc/manual/expressions/standard-env.xml +++ /dev/null @@ -1,60 +0,0 @@ -<chapter xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id='sec-standard-environment'> - -<title>The Standard Environment</title> - - -<para>The standard environment is used by passing it as an input -called <envar>stdenv</envar> to the derivation, and then doing - -<programlisting> -source $stdenv/setup</programlisting> - -at the top of the builder.</para> - -<para>Apart from adding the aforementioned commands to the -<envar>PATH</envar>, <filename>setup</filename> also does the -following: - -<itemizedlist> - - <listitem><para>All input packages specified in the - <envar>buildInputs</envar> environment variable have their - <filename>/bin</filename> subdirectory added to <envar>PATH</envar>, - their <filename>/include</filename> subdirectory added to the C/C++ - header file search path, and their <filename>/lib</filename> - subdirectory added to the linker search path. This can be extended. - For instance, when the <command>pkgconfig</command> package is - used, the subdirectory <filename>/lib/pkgconfig</filename> of each - input is added to the <envar>PKG_CONFIG_PATH</envar> environment - variable.</para></listitem> - - <listitem><para>The environment variable - <envar>NIX_CFLAGS_STRIP</envar> is set so that the compiler strips - debug information from object files. This can be disabled by - setting <envar>NIX_STRIP_DEBUG</envar> to - <literal>0</literal>.</para></listitem> - -</itemizedlist> - -</para> - -<para>The <filename>setup</filename> script also exports a function -called <function>genericBuild</function> that knows how to build -typical Autoconf-style packages. It can be customised to perform -builds for any type of package. It is advisable to use -<function>genericBuild</function> since it provides facilities that -are almost always useful such as unpacking of sources, patching of -sources, nested logging, etc.</para> - -<para>The definitive, up-to-date documentation of the generic builder -is the source itself, which resides in -<filename>pkgs/stdenv/generic/setup.sh</filename>.</para> - -<xi:include href="custom-builder.xml" /> -<xi:include href="debug-build.xml" /> - -</chapter> \ No newline at end of file diff --git a/doc/manual/expressions/writing-nix-expressions.xml b/doc/manual/expressions/writing-nix-expressions.xml index 6b797c200992..6646dddf0842 100644 --- a/doc/manual/expressions/writing-nix-expressions.xml +++ b/doc/manual/expressions/writing-nix-expressions.xml @@ -22,6 +22,5 @@ manual</link>.</para></note> <xi:include href="simple-expression.xml" /> <xi:include href="expression-language.xml" /> -<xi:include href="standard-env.xml" /> </part> diff --git a/doc/manual/installation/multi-user.xml b/doc/manual/installation/multi-user.xml index 312f5966452d..69ae1ef27041 100644 --- a/doc/manual/installation/multi-user.xml +++ b/doc/manual/installation/multi-user.xml @@ -23,11 +23,11 @@ daemon</emphasis> running under the owner of the Nix store/database that performs the operation.</para> <note><para>Multi-user mode has one important limitation: only -<systemitem class="username">root</systemitem> can run <command -linkend="sec-nix-pull">nix-pull</command> to register the availability -of pre-built binaries. However, those registrations are shared by all -users, so they still get the benefit from <command>nix-pull</command>s -done by <systemitem class="username">root</systemitem>.</para></note> +<systemitem class="username">root</systemitem> and a set of trusted +users specified in <filename>nix.conf</filename> can specify arbitrary +binary caches. So while unprivileged users may install packages from +arbitrary Nix expressions, they may not get pre-built +binaries.</para></note> <simplesect> diff --git a/doc/manual/introduction/about-nix.xml b/doc/manual/introduction/about-nix.xml index 56ec39916b6c..efd6cf2bb347 100644 --- a/doc/manual/introduction/about-nix.xml +++ b/doc/manual/introduction/about-nix.xml @@ -166,8 +166,8 @@ cache</emphasis>, a web server that provides pre-built binaries. For instance, when asked to build <literal>/nix/store/b6gvzjyb2pg0…-firefox-33.1</literal> from source, Nix would first check if the file -<uri>http://cache.nixos.org/b6gvzjyb2pg0….narinfo</uri> exists, and if -so, fetch the pre-built binary referenced from there; otherwise, it +<uri>https://cache.nixos.org/b6gvzjyb2pg0….narinfo</uri> exists, and +if so, fetch the pre-built binary referenced from there; otherwise, it would fall back to building from source.</para> </simplesect> diff --git a/doc/manual/local.mk b/doc/manual/local.mk index 4caef57783c0..3d7e7fed9631 100644 --- a/doc/manual/local.mk +++ b/doc/manual/local.mk @@ -7,9 +7,11 @@ XSLTPROC = $(xsltproc) --nonet $(xmlflags) \ --param admon.style \'\' \ --param callout.graphics.extension \'.gif\' \ --param contrib.inline.enabled 0 \ - --stringparam generate.toc "book toc" + --stringparam generate.toc "book toc" \ + --param keep.relative.image.uris 0 -docbookxsl = http://docbook.sourceforge.net/release/xsl-ns/1.78.1/ +docbookxsl = http://docbook.sourceforge.net/release/xsl-ns/1.78.1 +docbookrng = http://docbook.org/xml/5.0/rng/docbook.rng MANUAL_SRCS := $(call rwildcard, $(d), *.xml) @@ -26,7 +28,7 @@ $(d)/version.txt: $(d)/manual.is-valid: $(d)/manual.xmli $(trace-gen) $(XSLTPROC) --novalid --stringparam profile.condition manual \ $(docbookxsl)/profiling/profile.xsl $< 2> /dev/null | \ - $(xmllint) --nonet --noout --relaxng http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng - + $(xmllint) --nonet --noout --relaxng $(docbookrng) - @touch $@ clean-files += $(d)/manual.xmli $(d)/version.txt $(d)/manual.is-valid @@ -38,7 +40,7 @@ dist-files += $(d)/manual.xmli $(d)/version.txt $(d)/manual.is-valid man-pages := $(foreach n, \ nix-env.1 nix-build.1 nix-shell.1 nix-store.1 nix-instantiate.1 \ nix-collect-garbage.1 nix-push.1 nix-pull.1 \ - nix-prefetch-url.1 nix-channel.1 nix-generate-patches.1 \ + nix-prefetch-url.1 nix-channel.1 \ nix-install-package.1 nix-hash.1 nix-copy-closure.1 \ nix.conf.5 nix-daemon.8, \ $(d)/$(n)) diff --git a/doc/manual/manual.xml b/doc/manual/manual.xml index 5c46f303a11c..b784bb5f3c22 100644 --- a/doc/manual/manual.xml +++ b/doc/manual/manual.xml @@ -41,7 +41,7 @@ <xi:include href="installation/installation.xml" /> <xi:include href="packages/package-management.xml" /> <xi:include href="expressions/writing-nix-expressions.xml" /> - <xi:include href="builds/build-farm.xml" /> + <xi:include href="advanced-topics/advanced-topics.xml" /> <xi:include href="command-ref/command-ref.xml" /> <xi:include href="troubleshooting/troubleshooting.xml" /> <xi:include href="glossary/glossary.xml" /> diff --git a/doc/manual/packages/basic-package-mgmt.xml b/doc/manual/packages/basic-package-mgmt.xml index 69c955c1dd11..540d3ec223cc 100644 --- a/doc/manual/packages/basic-package-mgmt.xml +++ b/doc/manual/packages/basic-package-mgmt.xml @@ -28,40 +28,71 @@ Nix expressions called the Nix Package collection that contains packages ranging from basic development stuff such as GCC and Glibc, to end-user applications like Mozilla Firefox. (Nix is however not tied to the Nix Package collection; you could write your own Nix -expressions based on it, or completely new ones.) You can download -the latest version from <link -xlink:href='http://nixos.org/nixpkgs/download.html' />.</para> +expressions based on it, or completely new ones.)</para> + +<para>You can manually download the latest version of Nixpkgs from +<link xlink:href='http://nixos.org/nixpkgs/download.html'/>. However, +it’s much more convenient to use the Nixpkgs +<emphasis>channel</emphasis>, since it makes it easy to stay up to +date with new versions of Nixpkgs. (Channels are described in more +detail in <xref linkend="sec-channels"/>.) Nixpkgs is automatically +added to your list of “subscribed” channels when when you install +Nix. If this is not the case for some reason, you can add it as +follows: -<para>Assuming that you have downloaded and unpacked a release of Nix -Packages, you can view the set of available packages in the release: +<screen> +$ nix-channel --add https://nixos.org/channels/nixpkgs-unstable +$ nix-channel --update +</screen> + +</para> + +<note><para>On NixOS, you’re automatically subscribed to a NixOS +channel corresponding to your NixOS major release +(e.g. <uri>http://nixos.org/channels/nixos-14.12</uri>). A NixOS +channel is identical to the Nixpkgs channel, except that it contains +only Linux binaries and is updated only if a set of regression tests +succeed.</para></note> + +<para>You can view the set of available packages in Nixpkgs: <screen> -$ nix-env -qaf nixpkgs-<replaceable>version</replaceable> '*' -ant-blackdown-1.4.2 +$ nix-env -qa aterm-2.2 bash-3.0 binutils-2.15 bison-1.875d blackdown-1.4.2 bzip2-1.0.2 -...</screen> - -where <literal>nixpkgs-<replaceable>version</replaceable></literal> is -where you’ve unpacked the release. The flag <option>-q</option> -specifies a query operation; <option>-a</option> means that you want -to show the “available” (i.e., installable) packages, as opposed to -the installed packages; and <option>-f</option> -<filename>nixpkgs-<replaceable>version</replaceable></filename> -specifies the source of the packages. The argument -<literal>'*'</literal> shows all installable packages. (The quotes are -necessary to prevent shell expansion.) You can also select specific -packages by name: +…</screen> + +The flag <option>-q</option> specifies a query operation, and +<option>-a</option> means that you want to show the “available” (i.e., +installable) packages, as opposed to the installed packages. If you +downloaded Nixpkgs yourself, or if you checked it out from GitHub, +then you need to pass the path to your Nixpkgs tree using the +<option>-f</option> flag: + +<screen> +$ nix-env -qaf <replaceable>/path/to/nixpkgs</replaceable> +</screen> + +where <replaceable>/path/to/nixpkgs</replaceable> is where you’ve +unpacked or checked out Nixpkgs.</para> + +<para>You can select specific packages by name: + +<screen> +$ nix-env -qa firefox +firefox-34.0.5 +firefox-with-plugins-34.0.5 +</screen> + +and using regular expressions: <screen> -$ nix-env -qaf nixpkgs-<replaceable>version</replaceable> gcc -gcc-3.4.6 -gcc-4.0.3 -gcc-4.1.1</screen> +$ nix-env -qa 'firefox.*' +</screen> </para> @@ -70,12 +101,12 @@ available packages, i.e., whether they are installed into the user environment and/or present in the system: <screen> -$ nix-env -qasf nixpkgs-<replaceable>version</replaceable> '*' -... +$ nix-env -qas +… -PS bash-3.0 --S binutils-2.15 IPS bison-1.875d -...</screen> +…</screen> The first character (<literal>I</literal>) indicates whether the package is installed in your current user environment. The second @@ -88,40 +119,33 @@ just means that Nix knows that it can fetch a pre-built package from somewhere (typically a network server) instead of building it locally.</para> -<para>So now that we have a set of Nix expressions we can build the -packages contained in them. This is done using <literal>nix-env --i</literal>. For instance, +<para>You can install a package using <literal>nix-env -i</literal>. +For instance, <screen> -$ nix-env -f nixpkgs-<replaceable>version</replaceable> -i subversion</screen> +$ nix-env -i subversion</screen> will install the package called <literal>subversion</literal> (which is, of course, the <link xlink:href='http://subversion.tigris.org/'>Subversion version management system</link>).</para> -<para>When you do this for the first time, Nix will start building -Subversion and all its dependencies. This will take quite a while — -typically an hour or two on modern machines. Fortunately, there is a -faster way (so do a Ctrl-C on that install operation!): you just need -to tell Nix that pre-built binaries of all those packages are -available somewhere. This is done using the -<command>nix-pull</command> command, which must be supplied with a URL -containing a <emphasis>manifest</emphasis> describing what binaries -are available. This URL should correspond to the Nix Packages release -that you’re using. For instance, if you obtained a release from <link -xlink:href='http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x' -/>, then you should do: - -<screen> -$ nix-pull http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x/MANIFEST</screen> - -If you then issue the installation command, it should start -downloading binaries from <systemitem -class='fqdomainname'>nixos.org</systemitem>, instead of building -them from source. This might still take a while since all -dependencies must be downloaded, but on a reasonably fast connection -such as a DSL line it’s on the order of a few minutes.</para> +<note><para>When you ask Nix to install a package, it will first try +to get it in pre-compiled form from a <emphasis>binary +cache</emphasis>. By default, Nix will use the binary cache +<uri>https://cache.nixos.org</uri>; it contains binaries for most +packages in Nixpkgs. Only if no binary is available in the binary +cache, Nix will build the package from source. So if <literal>nix-env +-i subversion</literal> results in Nix building stuff from source, +then either the package is not built for your platform by the Nixpkgs +build servers, or your version of Nixpkgs is too old or too new. For +instance, if you have a very recent checkout of Nixpkgs, then the +Nixpkgs build servers may not have had a chance to build everything +and upload the resulting binaries to +<uri>https://cache.nixos.org</uri>. The Nixpkgs channel is only +updated after all binaries have been uploaded to the cache, so if you +stick to the Nixpkgs channel (rather than using a Git checkout of the +Nixpkgs tree), you will get binaries for most packages.</para></note> <para>Naturally, packages can also be uninstalled: @@ -134,7 +158,7 @@ $ nix-env -e subversion</screen> release of Nix Packages, you can do: <screen> -$ nix-env -f nixpkgs-<replaceable>version</replaceable> -u subversion</screen> +$ nix-env -u subversion</screen> This will <emphasis>only</emphasis> upgrade Subversion if there is a “newer” version in the new set of Nix expressions, as @@ -149,17 +173,17 @@ whatever version is already installed.</para> versions: <screen> -$ nix-env -f nixpkgs-<replaceable>version</replaceable> -u '*'</screen> +$ nix-env -u</screen> </para> <para>Sometimes it’s useful to be able to ask what <command>nix-env</command> would do, without actually doing it. For instance, to find out what packages would be upgraded by -<literal>nix-env -u '*'</literal>, you can do +<literal>nix-env -u</literal>, you can do <screen> -$ nix-env ... -u '*' --dry-run +$ nix-env -u --dry-run (dry run; not doing anything) upgrading `libxslt-1.1.0' to `libxslt-1.1.10' upgrading `graphviz-1.10' to `graphviz-1.12' @@ -167,4 +191,4 @@ upgrading `coreutils-5.0' to `coreutils-5.2.1'</screen> </para> -</chapter> \ No newline at end of file +</chapter> diff --git a/doc/manual/packages/channels.xml b/doc/manual/packages/channels.xml index 094e11fe3b15..15c119fcb1f9 100644 --- a/doc/manual/packages/channels.xml +++ b/doc/manual/packages/channels.xml @@ -8,10 +8,9 @@ <para>If you want to stay up to date with a set of packages, it’s not very convenient to manually download the latest set of Nix expressions -for those packages, use <command>nix-pull</command> to register -pre-built binaries (if available), and upgrade using -<command>nix-env</command>. Fortunately, there’s a better way: -<emphasis>Nix channels</emphasis>.</para> +for those packages and upgrade using <command>nix-env</command>. +Fortunately, there’s a better way: <emphasis>Nix +channels</emphasis>.</para> <para>A Nix channel is just a URL that points to a place that contains a set of Nix expressions and a manifest. Using the command <link @@ -23,35 +22,36 @@ URL.</para> <command>nix-channel --add</command>, e.g., <screen> -$ nix-channel --add http://nixos.org/channels/nixpkgs-unstable</screen> +$ nix-channel --add https://nixos.org/channels/nixpkgs-unstable</screen> subscribes you to a channel that always contains that latest version -of the Nix Packages collection. (Instead of -<literal>nixpkgs-unstable</literal> you could also subscribe to -<literal>nixpkgs-stable</literal>, which should have a higher level of -stability, but right now is just outdated.) Subscribing really just -means that the URL is added to the file -<filename>~/.nix-channels</filename>. Right now there is no command -to “unsubscribe”; you should just edit that file manually -and delete the offending URL.</para> +of the Nix Packages collection. (Subscribing really just means that +the URL is added to the file <filename>~/.nix-channels</filename>, +where it is read by subsequent calls to <command>nix-channel +--update</command>.) You can “unsubscribe” using <command>nix-channel +--remove</command>: + +<screen> +$ nix-channel --remove nixpkgs +</screen> +</para> <para>To obtain the latest Nix expressions available in a channel, do <screen> $ nix-channel --update</screen> -This downloads the Nix expressions in every channel (downloaded from -<literal><replaceable>url</replaceable>/nixexprs.tar.bz2</literal>) -and registers any available pre-built binaries in every channel -(by <command>nix-pull</command>ing -<literal><replaceable>url</replaceable>/MANIFEST</literal>). It also -makes the union of each channel’s Nix expressions the default for -<command>nix-env</command> operations. Consequently, you can then say +This downloads and unpacks the Nix expressions in every channel +(downloaded from <literal><replaceable>url</replaceable>/nixexprs.tar.bz2</literal>). +It also makes the union of each channel’s Nix expressions available by +default to <command>nix-env</command> operations (via the symlink +<filename>~/.nix-defexpr/channels</filename>). Consequently, you can +then say <screen> -$ nix-env -u '*'</screen> +$ nix-env -u</screen> to upgrade all packages in your profile to the latest versions available in the subscribed channels.</para> -</chapter> \ No newline at end of file +</chapter> diff --git a/doc/manual/packages/garbage-collection.xml b/doc/manual/packages/garbage-collection.xml index ae28c485f076..03b8e4c976c1 100644 --- a/doc/manual/packages/garbage-collection.xml +++ b/doc/manual/packages/garbage-collection.xml @@ -37,7 +37,14 @@ generations, e.g., <screen> $ nix-env --delete-generations 10 11 14</screen> -</para> +To delete all generations older than a specified number of days +(except the current generation), use the <literal>d</literal> +suffix. For example, + +<screen> +$ nix-env --delete-generations 14d</screen> + +deletes all generations older than two weeks.</para> <para>After removing appropriate old generations you can run the garbage collector as follows: @@ -67,4 +74,4 @@ is a quick and easy way to clean up your system.</para> <xi:include href="garbage-collector-roots.xml" /> -</chapter> \ No newline at end of file +</chapter> diff --git a/doc/manual/packages/profiles.xml b/doc/manual/packages/profiles.xml index ad5e92aeb64b..60660056fb8e 100644 --- a/doc/manual/packages/profiles.xml +++ b/doc/manual/packages/profiles.xml @@ -30,7 +30,7 @@ store.</para> <figure xml:id='fig-user-environments'><title>User environments</title> <mediaobject> <imageobject> - <imagedata fileref='figures/user-environments.png' format='PNG' /> + <imagedata fileref='../figures/user-environments.png' format='PNG' /> </imageobject> </mediaobject> </figure> @@ -73,9 +73,9 @@ generated based on the current one. For instance, generation 43 was created from generation 42 when we did <screen> -$ nix-env -i subversion mozilla</screen> +$ nix-env -i subversion firefox</screen> -on a set of Nix expressions that contained Mozilla and a new version +on a set of Nix expressions that contained Firefox and a new version of Subversion.</para> <para>Generations are grouped together into @@ -156,4 +156,4 @@ $ nix-env -p /nix/var/nix/profiles/other-profile -i subversion</screen> This will <emphasis>not</emphasis> change the <command>~/.nix-profile</command> symlink.</para> -</chapter> \ No newline at end of file +</chapter> diff --git a/doc/manual/release-notes/rl-1.8.xml b/doc/manual/release-notes/rl-1.8.xml index 310aa54796d6..b812915a95cd 100644 --- a/doc/manual/release-notes/rl-1.8.xml +++ b/doc/manual/release-notes/rl-1.8.xml @@ -4,7 +4,7 @@ version="5.0" xml:id="ssec-relnotes-1.8"> -<title>Release 1.8 (TBA)</title> +<title>Release 1.8 (December 9, 2014)</title> <itemizedlist> @@ -13,6 +13,10 @@ --serve</command> on the remote machine. This requires build slaves to be updated to Nix 1.8.</para></listitem> + <listitem><para>Nix now uses HTTPS instead of HTTP to access the + default binary cache, + <literal>cache.nixos.org</literal>.</para></listitem> + <listitem><para><command>nix-env</command> selectors are now regular expressions. For instance, you can do diff --git a/doc/manual/style.css b/doc/manual/style.css index f805aeab076c..53fd9d5709c3 100644 --- a/doc/manual/style.css +++ b/doc/manual/style.css @@ -23,6 +23,11 @@ h1 /* title */ font-size: 200%; } +div.part h1 +{ + font-size: 240%; +} + h2 /* chapters, appendices, subtitle */ { font-size: 180%; @@ -30,7 +35,7 @@ h2 /* chapters, appendices, subtitle */ div.part { - margin-top: 2em; + margin-top: 4em; } /* Extra space between chapters, appendices. */ @@ -61,6 +66,12 @@ div.appendix h3 margin-top: 1.5em; } +div.refentry\.separator +{ + margin-top: 2.5em; + margin-bottom: 2em; +} + div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */ { margin-top: 1.4em; diff --git a/doc/manual/troubleshooting/links-nix-store.xml b/doc/manual/troubleshooting/links-nix-store.xml index c81477bd4f27..c768889567d0 100644 --- a/doc/manual/troubleshooting/links-nix-store.xml +++ b/doc/manual/troubleshooting/links-nix-store.xml @@ -20,7 +20,7 @@ in <filename>/nix/store</filename>, as can be seen using <command>ls -l</command>: <screen> -$ ls -l /nix/store +$ ls -ld /nix/store drwxrwxrwt 32000 nix nix 4620288 Sep 8 15:08 store</screen> The <literal>ext2</literal> file system is limited to an inode link @@ -35,9 +35,9 @@ machines).</para> the <option>--max-links</option> option.</para> <para>Real solution: put the Nix store on a file system that supports -more than 32,000 subdirectories per directory, such as ReiserFS. -(This doesn’t solve the <literal>st_nlink</literal> limit, but -ReiserFS lies to the kernel by reporting a link count of 1 if it -exceeds the limit.)</para> +more than 32,000 subdirectories per directory, such as ext4. (This +doesn’t solve the <literal>st_nlink</literal> limit, but ext4 lies to +the kernel by reporting a link count of 1 if it exceeds the +limit.)</para> </section> diff --git a/doc/signing.txt b/doc/signing.txt index 1d042e95e220..7403cac470b2 100644 --- a/doc/signing.txt +++ b/doc/signing.txt @@ -1,6 +1,6 @@ Generate a private key: -$ (umask 277 && openssl genrsa -out /nix/etc/nix/signing-key.sec 2048) +$ (umask 277 && openssl genrsa -out /etc/nix/signing-key.sec 2048) The private key should be kept secret (only readable to the Nix daemon user). @@ -8,7 +8,7 @@ user). Generate the corresponding public key: -$ openssl rsa -in /nix/etc/nix/signing-key.sec -pubout > /nix/etc/nix/signing-key.pub +$ openssl rsa -in /etc/nix/signing-key.sec -pubout > /etc/nix/signing-key.pub The public key should be copied to all machines to which you want to export store paths. diff --git a/mk/functions.mk b/mk/functions.mk index 45d917399391..c48775db8c3b 100644 --- a/mk/functions.mk +++ b/mk/functions.mk @@ -10,5 +10,5 @@ filename-to-dep = $(dir $1).$(notdir $1).dep # empty string if not found. find-program = $(shell for i in $$(IFS=: ; echo $$PATH); do p=$$i/$(strip $1); if [ -e $$p ]; then echo $$p; break; fi; done) -# Remove trailing slash. +# Ensure that the given string ends in a single slash. add-trailing-slash = $(patsubst %/,%,$(1))/ diff --git a/mk/jars.mk b/mk/jars.mk index 99470f37435b..c8513e664ed5 100644 --- a/mk/jars.mk +++ b/mk/jars.mk @@ -1,4 +1,5 @@ define build-jar + $(1)_NAME ?= $(1) _d := $$(strip $$($(1)_DIR)) @@ -7,14 +8,20 @@ define build-jar $(1)_TMPDIR := $$(_d)/.$$($(1)_NAME).jar.tmp - $$($(1)_PATH): $$($(1)_SOURCES) + _jars := $$(foreach jar, $$($(1)_JARS), $$($$(jar)_PATH)) + + $$($(1)_PATH): $$($(1)_SOURCES) $$(_jars) $$($(1)_EXTRA_DEPS)| $$($(1)_ORDER_AFTER) @rm -rf $$($(1)_TMPDIR) @mkdir -p $$($(1)_TMPDIR) - $$(trace-javac) javac $(GLOBAL_JAVACFLAGS) $$($(1)_JAVACFLAGS) -d $$($(1)_TMPDIR) $$($(1)_SOURCES) - $$(trace-jar) jar cf $$($(1)_PATH) -C $$($(1)_TMPDIR) . + $$(trace-javac) javac $(GLOBAL_JAVACFLAGS) $$($(1)_JAVACFLAGS) -d $$($(1)_TMPDIR) \ + $$(foreach fn, $$($(1)_SOURCES), '$$(fn)') \ + -cp "$$(subst $$(space),,$$(foreach jar,$$($(1)_JARS),$$($$(jar)_PATH):))$$$$CLASSPATH" + @echo -e '$$(subst $$(newline),\n,$$($(1)_MANIFEST))' > $$($(1)_PATH).manifest + $$(trace-jar) jar cfm $$($(1)_PATH) $$($(1)_PATH).manifest -C $$($(1)_TMPDIR) . + @rm $$($(1)_PATH).manifest @rm -rf $$($(1)_TMPDIR) - $(1)_INSTALL_DIR ?= $$(libdir)/java + $(1)_INSTALL_DIR ?= $$(jardir) $(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$$($(1)_NAME).jar diff --git a/mk/lib.mk b/mk/lib.mk index f7c8c6b3aa84..4ad5c636c8d4 100644 --- a/mk/lib.mk +++ b/mk/lib.mk @@ -14,17 +14,40 @@ dist-files := OS = $(shell uname -s) +# Hack to define a literal space. +space := +space += + + +# Hack to define a literal newline. +define newline + + +endef + + # Default installation paths. prefix ?= /usr/local libdir ?= $(prefix)/lib bindir ?= $(prefix)/bin libexecdir ?= $(prefix)/libexec datadir ?= $(prefix)/share +jardir ?= $(datadir)/java localstatedir ?= $(prefix)/var sysconfdir ?= $(prefix)/etc mandir ?= $(prefix)/share/man +# Initialise support for build directories. +builddir ?= + +ifdef builddir + buildprefix = $(builddir)/ +else + buildprefix = +endif + + # Pass -fPIC if we're building dynamic libraries. BUILD_SHARED_LIBS ?= 1 @@ -44,7 +67,6 @@ ifeq ($(BUILD_SHARED_LIBS), 1) SET_RPATH_TO_LIBS ?= 1 endif - # Pass -g if we want debug info. BUILD_DEBUG ?= 1 diff --git a/mk/libraries.mk b/mk/libraries.mk index 3b292e988dca..3cd7a53107bd 100644 --- a/mk/libraries.mk +++ b/mk/libraries.mk @@ -49,9 +49,9 @@ endif # built, otherwise a static library. define build-library $(1)_NAME ?= $(1) - _d := $$(strip $$($(1)_DIR)) + _d := $(buildprefix)$$(strip $$($(1)_DIR)) _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - $(1)_OBJS := $$(addsuffix .o, $$(basename $$(_srcs))) + $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) _libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH)) ifeq (CYGWIN,$(findstring CYGWIN,$(OS))) @@ -86,9 +86,12 @@ define build-library $(1)_PATH := $$(_d)/$$($(1)_NAME).$(SO_EXT) $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ - $$(trace-ld) $(CXX) -o $$@ -shared $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) + $$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED) - $(1)_LDFLAGS_USE += -L$$(_d) -Wl,-rpath,$$(abspath $$(_d)) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) + ifneq ($(OS), Darwin) + $(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d)) + endif + $(1)_LDFLAGS_USE += -L$$(_d) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) $(1)_INSTALL_PATH := $(DESTDIR)$$($(1)_INSTALL_DIR)/$$($(1)_NAME).$(SO_EXT) @@ -100,10 +103,12 @@ define build-library $$(trace-ld) $(CXX) -o $$@ -shared $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) $(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) - ifeq ($(SET_RPATH_TO_LIBS), 1) - $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR) - else - $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath-link,$$($(1)_INSTALL_DIR) + ifneq ($(OS), Darwin) + ifeq ($(SET_RPATH_TO_LIBS), 1) + $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR) + else + $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath-link,$$($(1)_INSTALL_DIR) + endif endif ifdef $(1)_FORCE_INSTALL diff --git a/mk/patterns.mk b/mk/patterns.mk index 6b2cfd017050..3219d9629fbf 100644 --- a/mk/patterns.mk +++ b/mk/patterns.mk @@ -1,8 +1,11 @@ -%.o: %.cc +$(buildprefix)%.o: %.cc + @mkdir -p "$(dir $@)" $(trace-cxx) $(CXX) -o $@ -c $< $(GLOBAL_CXXFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(CXXFLAGS) $($@_CXXFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP -%.o: %.cpp +$(buildprefix)%.o: %.cpp + @mkdir -p "$(dir $@)" $(trace-cxx) $(CXX) -o $@ -c $< $(GLOBAL_CXXFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(CXXFLAGS) $($@_CXXFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP -%.o: %.c +$(buildprefix)%.o: %.c + @mkdir -p "$(dir $@)" $(trace-cc) $(CC) -o $@ -c $< $(GLOBAL_CFLAGS) $(CFLAGS) $($@_CFLAGS) -MMD -MF $(call filename-to-dep, $@) -MP diff --git a/mk/programs.mk b/mk/programs.mk index 72afdf95251b..3ac64494e3a5 100644 --- a/mk/programs.mk +++ b/mk/programs.mk @@ -23,9 +23,9 @@ programs-list := # - $(1)_INSTALL_DIR: the directory where the program will be # installed; defaults to $(bindir). define build-program - _d := $$($(1)_DIR) + _d := $(buildprefix)$$($(1)_DIR) _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) - $(1)_OBJS := $$(addsuffix .o, $$(basename $$(_srcs))) + $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) _libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH)) $(1)_PATH := $$(_d)/$(1) diff --git a/mk/templates.mk b/mk/templates.mk index ab99168bb7a5..c7ac7afbff27 100644 --- a/mk/templates.mk +++ b/mk/templates.mk @@ -8,8 +8,12 @@ define instantiate-template endef +ifneq ($(MAKECMDGOALS), clean) + %.h: %.h.in $(trace-gen) rm -f $@ && ./config.status --quiet --header=$@ %: %.in $(trace-gen) rm -f $@ && ./config.status --quiet --file=$@ + +endif diff --git a/release.nix b/release.nix index af0e2362baf8..a08cf7a96c81 100644 --- a/release.nix +++ b/release.nix @@ -122,15 +122,16 @@ let in runCommand "nix-binary-tarball-${version}" - { exportReferencesGraph = [ "closure" toplevel ]; + { exportReferencesGraph = [ "closure1" toplevel "closure2" cacert ]; buildInputs = [ perl ]; meta.description = "Distribution-independent Nix bootstrap binaries for ${system}"; } '' - storePaths=$(perl ${pathsFromGraph} ./closure) - printRegistration=1 perl ${pathsFromGraph} ./closure > $TMPDIR/reginfo + storePaths=$(perl ${pathsFromGraph} ./closure1 ./closure2) + printRegistration=1 perl ${pathsFromGraph} ./closure1 ./closure2 > $TMPDIR/reginfo substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \ - --subst-var-by nix ${toplevel} + --subst-var-by nix ${toplevel} \ + --subst-var-by cacert ${cacert} chmod +x $TMPDIR/install dir=nix-${version}-${system} fn=$out/$dir.tar.bz2 diff --git a/scripts/download-from-binary-cache.pl.in b/scripts/download-from-binary-cache.pl.in index e272f139cf8c..6285a0503682 100644 --- a/scripts/download-from-binary-cache.pl.in +++ b/scripts/download-from-binary-cache.pl.in @@ -42,9 +42,16 @@ my $curlIdCount = 1; my %requests; my %scheduled; my $caBundle = $ENV{"SSL_CERT_FILE"} // $ENV{"CURL_CA_BUNDLE"} // $ENV{"OPENSSL_X509_CERT_FILE"}; +$caBundle = "/etc/ssl/certs/ca-bundle.crt" if !$caBundle && -f "/etc/ssl/certs/ca-bundle.crt"; +$caBundle = "/etc/ssl/certs/ca-certificates.crt" if !$caBundle && -f "/etc/ssl/certs/ca-certificates.crt"; my $userName = getpwuid($<) || $ENV{"USER"} or die "cannot figure out user name"; +sub isTrue { + my ($x) = @_; + return $x eq "true" || $x eq "1"; +} + my $requireSignedBinaryCaches = ($Nix::Config::config{"signed-binary-caches"} // "0") ne "0"; my $curlConnectTimeout = int( @@ -67,6 +74,7 @@ sub addRequest { $curl->setopt(CURLOPT_WRITEDATA, $fh); $curl->setopt(CURLOPT_FOLLOWLOCATION, 1); $curl->setopt(CURLOPT_CAINFO, $caBundle) if defined $caBundle; + $curl->setopt(CURLOPT_SSL_VERIFYPEER, 0) unless isTrue($Nix::Config::config{"verify-https-binary-caches"} // "1"); $curl->setopt(CURLOPT_USERAGENT, "Nix/$Nix::Config::version"); $curl->setopt(CURLOPT_NOBODY, 1) if $head; $curl->setopt(CURLOPT_FAILONERROR, 1); @@ -218,7 +226,7 @@ sub getAvailableCaches { } my @urls = strToList($Nix::Config::config{"binary-caches"} // - ($Nix::Config::storeDir eq "/nix/store" ? "http://cache.nixos.org" : "")); + ($Nix::Config::storeDir eq "/nix/store" ? "https://cache.nixos.org" : "")); my $urlsFiles = $Nix::Config::config{"binary-cache-files"} // "$Nix::Config::stateDir/profiles/per-user/$userName/channels/binary-caches/*"; diff --git a/scripts/install-nix-from-closure.sh b/scripts/install-nix-from-closure.sh index 60ec1ea93219..c9ba9a2a280a 100644 --- a/scripts/install-nix-from-closure.sh +++ b/scripts/install-nix-from-closure.sh @@ -5,6 +5,7 @@ set -e dest="/nix" self="$(dirname "$0")" nix="@nix@" +cacert="@cacert@" if ! [ -e $self/.reginfo ]; then echo "$0: incomplete installer (.reginfo is missing)" >&2 @@ -66,26 +67,25 @@ fi . $nix/etc/profile.d/nix.sh -if ! $nix/bin/nix-env -i $nix; then +if ! $nix/bin/nix-env -i "$nix"; then echo "$0: unable to install Nix into your default profile" >&2 exit 1 fi +# Install an SSL certificate bundle. +if [ -z "$SSL_CERT_FILE" -o ! -f "$SSL_CERT_FILE" ]; then + $nix/bin/nix-env -i "$cacert" + export SSL_CERT_FILE="$HOME/.nix-profile/etc/ca-bundle.crt" +fi + # Subscribe the user to the Nixpkgs channel and fetch it. if ! $nix/bin/nix-channel --list | grep -q "^nixpkgs "; then - if [ -n "$SSL_CERT_FILE" ]; then - $nix/bin/nix-channel --add https://nixos.org/channels/nixpkgs-unstable - else - $nix/bin/nix-channel --add http://nixos.org/channels/nixpkgs-unstable - fi + $nix/bin/nix-channel --add https://nixos.org/channels/nixpkgs-unstable fi if [ -z "$_NIX_INSTALLER_TEST" ]; then $nix/bin/nix-channel --update nixpkgs fi -# Install an SSL certificate bundle. -$nix/bin/nix-env -iA nixpkgs.cacert || true - # Make the shell source nix.sh during login. p=$NIX_LINK/etc/profile.d/nix.sh diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 7dd7968c314a..a91b54bd589f 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -10,9 +10,9 @@ if [ -n "$HOME" ]; then export PATH=$NIX_LINK/bin:$NIX_LINK/sbin:$PATH - # Subscribe the root user to the Nixpkgs channel by default. + # Subscribe the user to the Nixpkgs channel by default. if [ ! -e $HOME/.nix-channels ]; then - echo "http://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels + echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels fi # Append ~/.nix-defexpr/channels/nixpkgs to $NIX_PATH so that diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2ff9756108ad..298f6a3a60e3 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -247,7 +247,6 @@ EvalState::EvalState(const Strings & _searchPath) EvalState::~EvalState() { fileEvalCache.clear(); - printCanaries(); } @@ -1514,26 +1513,6 @@ void EvalState::printStats() } -void EvalState::printCanaries() -{ -#if HAVE_BOEHMGC - if (!settings.get("debug-gc", false)) return; - - GC_gcollect(); - - if (gcCanaries.empty()) { - printMsg(lvlError, "all canaries have been garbage-collected"); - return; - } - - printMsg(lvlError, "the following canaries have not been garbage-collected:"); - - for (auto i : gcCanaries) - printMsg(lvlError, format(" %1%") % i->string.s); -#endif -} - - size_t valueSize(Value & v) { std::set<const void *> seen; diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 8bf65c2c55de..78942927fd24 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -287,8 +287,6 @@ public: /* Print statistics. */ void printStats(); - void printCanaries(); - private: unsigned long nrEnvs; @@ -320,12 +318,6 @@ private: friend struct ExprOpConcatLists; friend struct ExprSelect; friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); - -#if HAVE_BOEHMGC - std::set<Value *> gcCanaries; - friend void canaryFinalizer(GC_PTR obj, GC_PTR client_data); - friend void prim_gcCanary(EvalState & state, const Pos & pos, Value * * args, Value & v); -#endif }; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index e7b79604699b..cd7b287e29c3 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -417,32 +417,6 @@ static void prim_trace(EvalState & state, const Pos & pos, Value * * args, Value } -#if HAVE_BOEHMGC -void canaryFinalizer(GC_PTR obj, GC_PTR client_data) -{ - Value * v = (Value *) obj; - EvalState & state(* (EvalState *) client_data); - printMsg(lvlError, format("canary ‘%1%’ garbage-collected") % v->string.s); - auto i = state.gcCanaries.find(v); - assert(i != state.gcCanaries.end()); - state.gcCanaries.erase(i); -} -#endif - - -void prim_gcCanary(EvalState & state, const Pos & pos, Value * * args, Value & v) -{ - string s = state.forceStringNoCtx(*args[0], pos); - state.mkList(v, 1); - Value * canary = v.list.elems[0] = state.allocValue(); -#if HAVE_BOEHMGC - state.gcCanaries.insert(canary); - GC_register_finalizer(canary, canaryFinalizer, &state, 0, 0); -#endif - mkString(*canary, s); -} - - void prim_valueSize(EvalState & state, const Pos & pos, Value * * args, Value & v) { /* We're not forcing the argument on purpose. */ @@ -756,8 +730,12 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va { PathSet context; Path path = state.coerceToPath(pos, *args[0], context); - if (!context.empty()) - throw EvalError(format("string ‘%1%’ cannot refer to other paths, at %2%") % path % pos); + try { + realiseContext(context); + } catch (InvalidPathError & e) { + throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%") + % path % e.path % pos); + } mkString(v, readFile(path).c_str()); } @@ -1556,7 +1534,6 @@ void EvalState::createBaseEnv() // Debugging addPrimOp("__trace", 2, prim_trace); - addPrimOp("__gcCanary", 1, prim_gcCanary); addPrimOp("__valueSize", 1, prim_valueSize); // Paths diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index bf5688a1e606..9c74a614e2e4 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -16,7 +16,6 @@ #include <sys/stat.h> #include <unistd.h> #include <signal.h> -#include <spawn.h> extern char * * environ; @@ -293,8 +292,9 @@ int handleExceptions(const string & programName, std::function<void()> fun) RunPager::RunPager() { - string pager = getEnv("PAGER"); - if (!isatty(STDOUT_FILENO) || pager.empty()) return; + if (!isatty(STDOUT_FILENO)) return; + string pager = getEnv("PAGER", "default"); + if (pager == "" || pager == "cat") return; /* Ignore SIGINT. The pager will handle it (and we'll get SIGPIPE). */ @@ -309,35 +309,18 @@ RunPager::RunPager() Pipe toPager; toPager.create(); - // FIXME: should do this in the child environment. - if (!getenv("LESS")) - setenv("LESS", "FRSXMK", 1); - - /* Start the pager using posix_spawn. */ - pid_t pid_; - const char * argv[] = { "sh", "-c", pager.c_str(), 0 }; - - posix_spawn_file_actions_t fileActions; - int err = posix_spawn_file_actions_init(&fileActions); - if (err) throw SysError(err, "creating POSIX file actions"); - err = posix_spawn_file_actions_adddup2(&fileActions, toPager.readSide, STDIN_FILENO); - if (err) throw SysError(err, "adding to POSIX file actions"); - - posix_spawnattr_t spawnAttrs; - err = posix_spawnattr_init(&spawnAttrs); - if (err) throw SysError(err, "creating POSIX spawn attrs"); -#ifdef POSIX_SPAWN_USEVFORK - err = posix_spawnattr_setflags(&spawnAttrs, POSIX_SPAWN_USEVFORK); - if (err) throw SysError(err, "setting POSIX spawn attr flag"); -#endif - - err = posix_spawn(&pid_, "/bin/sh", &fileActions, &spawnAttrs, (char * const *) argv, environ); - - posix_spawn_file_actions_destroy(&fileActions); - posix_spawnattr_destroy(&spawnAttrs); - - if (err) throw SysError(err, format("running ‘%1%’") % pager); - pid = pid_; + pid = startProcess([&]() { + if (dup2(toPager.readSide, STDIN_FILENO) == -1) + throw SysError("dupping stdin"); + if (!getenv("LESS")) + setenv("LESS", "FRSXMK", 1); + if (pager != "default") + execl("/bin/sh", "sh", "-c", pager.c_str(), NULL); + execlp("pager", "pager", NULL); + execlp("less", "less", NULL); + execlp("more", "more", NULL); + throw SysError(format("executing ‘%1%’") % pager); + }); if (dup2(toPager.writeSide, STDOUT_FILENO) == -1) throw SysError("dupping stdout"); @@ -346,10 +329,14 @@ RunPager::RunPager() RunPager::~RunPager() { - if (pid != -1) { - std::cout.flush(); - close(STDOUT_FILENO); - pid.wait(true); + try { + if (pid != -1) { + std::cout.flush(); + close(STDOUT_FILENO); + pid.wait(true); + } + } catch (...) { + ignoreException(); } } diff --git a/src/libmain/stack.cc b/src/libmain/stack.cc index b670e695d140..41b617d98be2 100644 --- a/src/libmain/stack.cc +++ b/src/libmain/stack.cc @@ -32,7 +32,7 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx) if (diff < 0) diff = -diff; if (diff < 4096) { char msg[] = "error: stack overflow (possible infinite recursion)\n"; - write(2, msg, strlen(msg)); + (void) write(2, msg, strlen(msg)); _exit(1); // maybe abort instead? } } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 539d0b21b278..08f44b392b00 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -415,18 +415,6 @@ static void commonChildInit(Pipe & logPipe) } -/* Convert a string list to an array of char pointers. Careful: the - string list should outlive the array. */ -const char * * strings2CharPtrs(const Strings & ss) -{ - const char * * arr = new const char * [ss.size() + 1]; - const char * * p = arr; - foreach (Strings::const_iterator, i, ss) *p++ = i->c_str(); - *p = 0; - return arr; -} - - ////////////////////////////////////////////////////////////////////// @@ -816,8 +804,8 @@ private: /* Start building a derivation. */ void startBuilder(); - /* Initialise the builder's process. */ - void initChild(); + /* Run the builder's process. */ + void runChild(); friend int childEntry(void *); @@ -1914,9 +1902,11 @@ void DerivationGoal::startBuilder() builderOut.create(); /* Fork a child to build the package. */ + ProcessOptions options; + options.allowVfork = !buildUser.enabled(); pid = startProcess([&]() { - initChild(); - }); + runChild(); + }, options); /* parent */ pid.setSeparatePG(true); @@ -1936,7 +1926,7 @@ void DerivationGoal::startBuilder() } -void DerivationGoal::initChild() +void DerivationGoal::runChild() { /* Warning: in the child we should absolutely not make any SQLite calls! */ @@ -1986,9 +1976,11 @@ void DerivationGoal::initChild() /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; - sethostname(hostname, sizeof(hostname)); + if (sethostname(hostname, sizeof(hostname)) == -1) + throw SysError("cannot set host name"); char domainname[] = "(none)"; // kernel default - setdomainname(domainname, sizeof(domainname)); + if (setdomainname(domainname, sizeof(domainname)) == -1) + throw SysError("cannot set domain name"); /* Make all filesystems private. This is necessary because subtrees may have been mounted as "shared" @@ -2122,11 +2114,7 @@ void DerivationGoal::initChild() Strings envStrs; foreach (Environment::const_iterator, i, env) envStrs.push_back(rewriteHashes(i->first + "=" + i->second, rewritesToTmp)); - const char * * envArr = strings2CharPtrs(envStrs); - - Path program = drv.builder.c_str(); - std::vector<const char *> args; /* careful with c_str()! */ - string user; /* must be here for its c_str()! */ + auto envArr = stringsToCharPtrs(envStrs); /* If we are running in `build-users' mode, then switch to the user we allocated above. Make sure that we drop all root @@ -2135,8 +2123,6 @@ void DerivationGoal::initChild() setuid() when run as root sets the real, effective and saved UIDs. */ if (buildUser.enabled()) { - printMsg(lvlChatty, format("switching to user ‘%1%’") % buildUser.getUser()); - if (setgroups(0, 0) == -1) throw SysError("cannot clear the set of supplementary groups"); @@ -2152,29 +2138,25 @@ void DerivationGoal::initChild() } /* Fill in the arguments. */ + Strings args; string builderBasename = baseNameOf(drv.builder); - args.push_back(builderBasename.c_str()); - foreach (Strings::iterator, i, drv.args) { - auto re = rewriteHashes(*i, rewritesToTmp); - auto cstr = new char[re.length()+1]; - std::strcpy(cstr, re.c_str()); - - args.push_back(cstr); - } - args.push_back(0); + args.push_back(builderBasename); + foreach (Strings::iterator, i, drv.args) + args.push_back(rewriteHashes(*i, rewritesToTmp)); + auto argArr = stringsToCharPtrs(args); restoreSIGPIPE(); /* Indicate that we managed to set up the build environment. */ - writeToStderr("\n"); + writeFull(STDERR_FILENO, "\n"); /* Execute the program. This should not return. */ - execve(program.c_str(), (char * *) &args[0], (char * *) envArr); + execve(drv.builder.c_str(), (char * *) &argArr[0], (char * *) &envArr[0]); throw SysError(format("executing ‘%1%’") % drv.builder); } catch (std::exception & e) { - writeToStderr("while setting up the build environment: " + string(e.what()) + "\n"); + writeFull(STDERR_FILENO, "while setting up the build environment: " + string(e.what()) + "\n"); _exit(1); } } @@ -2487,7 +2469,7 @@ void DerivationGoal::handleChildOutput(int fd, const string & data) BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size()); if (err != BZ_OK) throw Error(format("cannot write to compressed log file (BZip2 error = %1%)") % err); } else if (fdLogFile != -1) - writeFull(fdLogFile, (unsigned char *) data.data(), data.size()); + writeFull(fdLogFile, data); } if (hook && fd == hook->fromHook.readSide) @@ -2797,7 +2779,7 @@ void SubstitutionGoal::tryToRun() args.push_back("--substitute"); args.push_back(storePath); args.push_back(destPath); - const char * * argArr = strings2CharPtrs(args); + auto argArr = stringsToCharPtrs(args); /* Fork the substitute program. */ pid = startProcess([&]() { @@ -2807,7 +2789,7 @@ void SubstitutionGoal::tryToRun() if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1) throw SysError("cannot dup output pipe into stdout"); - execv(sub.c_str(), (char * *) argArr); + execv(sub.c_str(), (char * *) &argArr[0]); throw SysError(format("executing ‘%1%’") % sub); }); diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 49cb11d23290..7959a592d987 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -191,7 +191,7 @@ void LocalStore::addTempRoot(const Path & path) lockFile(fdTempRoots, ltWrite, true); string s = path + '\0'; - writeFull(fdTempRoots, (const unsigned char *) s.data(), s.size()); + writeFull(fdTempRoots, s); /* Downgrade to a read lock. */ debug(format("downgrading to read lock on ‘%1%’") % fnTempRoots); @@ -231,7 +231,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) if (lockFile(*fd, ltWrite, false)) { printMsg(lvlError, format("removing stale temporary roots file ‘%1%’") % path); unlink(path.c_str()); - writeFull(*fd, (const unsigned char *) "d", 1); + writeFull(*fd, "d"); continue; } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index fc48c0405650..3ad80bc4e6f4 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -358,7 +358,8 @@ LocalStore::~LocalStore() i->second.to.close(); i->second.from.close(); i->second.error.close(); - i->second.pid.wait(true); + if (i->second.pid != -1) + i->second.pid.wait(true); } } catch (...) { ignoreException(); @@ -498,7 +499,7 @@ void LocalStore::makeStoreWritable() if (unshare(CLONE_NEWNS) == -1) throw SysError("setting up a private mount namespace"); - if (mount(0, settings.nixStore.c_str(), 0, MS_REMOUNT | MS_BIND, 0) == -1) + if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) throw SysError(format("remounting %1% writable") % settings.nixStore); } #endif diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc index f26684afacb9..9db37e8f9aaa 100644 --- a/src/libstore/pathlocks.cc +++ b/src/libstore/pathlocks.cc @@ -33,7 +33,7 @@ void deleteLockFile(const Path & path, int fd) other processes waiting on this lock that the lock is stale (deleted). */ unlink(path.c_str()); - writeFull(fd, (const unsigned char *) "d", 1); + writeFull(fd, "d"); /* Note that the result of unlink() is ignored; removing the lock file is an optimisation, not a necessity. */ } diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index cabde051bd02..d08913246321 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -110,7 +110,7 @@ void RemoteStore::connectToDaemon() applications... */ AutoCloseFD fdPrevDir = open(".", O_RDONLY); if (fdPrevDir == -1) throw SysError("couldn't open current directory"); - chdir(dirOf(socketPath).c_str()); + if (chdir(dirOf(socketPath).c_str()) == -1) throw SysError(format("couldn't change to directory of ‘%1%’") % socketPath); Path socketPathRel = "./" + baseNameOf(socketPath); struct sockaddr_un addr; diff --git a/src/libutil/types.hh b/src/libutil/types.hh index 030996a060e2..160884ee1ad7 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -73,7 +73,6 @@ class SysError : public Error public: int errNo; SysError(const FormatOrString & fs); - SysError(int errNo, const FormatOrString & fs); }; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 60be02cd4647..dcdb438e03b2 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -45,14 +45,8 @@ BaseError & BaseError::addPrefix(const FormatOrString & fs) SysError::SysError(const FormatOrString & fs) - : SysError(errno, fs) -{ -} - - -SysError::SysError(int errNo, const FormatOrString & fs) - : Error(format("%1%: %2%") % fs.s % strerror(errNo)) - , errNo(errNo) + : Error(format("%1%: %2%") % fs.s % strerror(errno)) + , errNo(errno) { } @@ -271,7 +265,7 @@ void writeFile(const Path & path, const string & s) AutoCloseFD fd = open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666); if (fd == -1) throw SysError(format("opening file ‘%1%’") % path); - writeFull(fd, (unsigned char *) s.data(), s.size()); + writeFull(fd, s); } @@ -298,7 +292,7 @@ string readLine(int fd) void writeLine(int fd, string s) { s += '\n'; - writeFull(fd, (const unsigned char *) s.data(), s.size()); + writeFull(fd, s); } @@ -489,18 +483,13 @@ void warnOnce(bool & haveWarned, const FormatOrString & fs) } -static void defaultWriteToStderr(const unsigned char * buf, size_t count) -{ - writeFull(STDERR_FILENO, buf, count); -} - - void writeToStderr(const string & s) { try { - auto p = _writeToStderr; - if (!p) p = defaultWriteToStderr; - p((const unsigned char *) s.data(), s.size()); + if (_writeToStderr) + _writeToStderr((const unsigned char *) s.data(), s.size()); + else + writeFull(STDERR_FILENO, s); } catch (SysError & e) { /* Ignore failing writes to stderr if we're in an exception handler, otherwise throw an exception. We need to ignore @@ -512,7 +501,7 @@ void writeToStderr(const string & s) } -void (*_writeToStderr) (const unsigned char * buf, size_t count) = defaultWriteToStderr; +void (*_writeToStderr) (const unsigned char * buf, size_t count) = 0; void readFull(int fd, unsigned char * buf, size_t count) @@ -546,6 +535,12 @@ void writeFull(int fd, const unsigned char * buf, size_t count) } +void writeFull(int fd, const string & s) +{ + writeFull(fd, (const unsigned char *) s.data(), s.size()); +} + + string drainFD(int fd) { string result; @@ -831,6 +826,9 @@ void killUser(uid_t uid) users to which the current process can send signals. So we fork a process, switch to uid, and send a mass kill. */ + ProcessOptions options; + options.allowVfork = false; + Pid pid = startProcess([&]() { if (setuid(uid) == -1) @@ -853,7 +851,7 @@ void killUser(uid_t uid) } _exit(0); - }); + }, options); int status = pid.wait(true); if (status != 0) @@ -869,46 +867,64 @@ void killUser(uid_t uid) ////////////////////////////////////////////////////////////////////// -pid_t startProcess(std::function<void()> fun, - bool dieWithParent, const string & errorPrefix, bool runExitHandlers) +/* Wrapper around vfork to prevent the child process from clobbering + the caller's stack frame in the parent. */ +static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); +static pid_t doFork(bool allowVfork, std::function<void()> fun) { +#ifdef __linux__ + pid_t pid = allowVfork ? vfork() : fork(); +#else pid_t pid = fork(); - if (pid == -1) throw SysError("unable to fork"); +#endif + if (pid != 0) return pid; + fun(); + abort(); +} - if (pid == 0) { - _writeToStderr = 0; + +pid_t startProcess(std::function<void()> fun, const ProcessOptions & options) +{ + auto wrapper = [&]() { + if (!options.allowVfork) _writeToStderr = 0; try { #if __linux__ - if (dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) + if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) throw SysError("setting death signal"); #endif restoreAffinity(); fun(); } catch (std::exception & e) { try { - std::cerr << errorPrefix << e.what() << "\n"; + std::cerr << options.errorPrefix << e.what() << "\n"; } catch (...) { } } catch (...) { } - if (runExitHandlers) + if (options.runExitHandlers) exit(1); else _exit(1); - } + }; + + pid_t pid = doFork(options.allowVfork, wrapper); + if (pid == -1) throw SysError("unable to fork"); return pid; } +std::vector<const char *> stringsToCharPtrs(const Strings & ss) +{ + std::vector<const char *> res; + for (auto & s : ss) res.push_back(s.c_str()); + res.push_back(0); + return res; +} + + string runProgram(Path program, bool searchPath, const Strings & args) { checkInterrupt(); - std::vector<const char *> cargs; /* careful with c_str()! */ - cargs.push_back(program.c_str()); - for (Strings::const_iterator i = args.begin(); i != args.end(); ++i) - cargs.push_back(i->c_str()); - cargs.push_back(0); - /* Create a pipe. */ Pipe pipe; pipe.create(); @@ -918,6 +934,10 @@ string runProgram(Path program, bool searchPath, const Strings & args) if (dup2(pipe.writeSide, STDOUT_FILENO) == -1) throw SysError("dupping stdout"); + Strings args_(args); + args_.push_front(program); + auto cargs = stringsToCharPtrs(args_); + if (searchPath) execvp(program.c_str(), (char * *) &cargs[0]); else diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 628b8a0e1f09..186ee71f45d0 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -171,6 +171,7 @@ extern void (*_writeToStderr) (const unsigned char * buf, size_t count); requested number of bytes. */ void readFull(int fd, unsigned char * buf, size_t count); void writeFull(int fd, const unsigned char * buf, size_t count); +void writeFull(int fd, const string & s); MakeError(EndOfFile, Error) @@ -269,8 +270,16 @@ void killUser(uid_t uid); /* Fork a process that runs the given function, and return the child pid to the caller. */ -pid_t startProcess(std::function<void()> fun, bool dieWithParent = true, - const string & errorPrefix = "error: ", bool runExitHandlers = false); +struct ProcessOptions +{ + string errorPrefix; + bool dieWithParent; + bool runExitHandlers; + bool allowVfork; + ProcessOptions() : errorPrefix("error: "), dieWithParent(true), runExitHandlers(false), allowVfork(true) { }; +}; + +pid_t startProcess(std::function<void()> fun, const ProcessOptions & options = ProcessOptions()); /* Run a program and return its stdout in a string (i.e., like the @@ -280,6 +289,11 @@ string runProgram(Path program, bool searchPath = false, MakeError(ExecError, Error) +/* Convert a list of strings to a null-terminated vector of char + *'s. The result must not be accessed beyond the lifetime of the + list of strings. */ +std::vector<const char *> stringsToCharPtrs(const Strings & ss); + /* Close all file descriptors except stdin, stdout, stderr, and those listed in the given set. Good practice in child processes. */ void closeMostFDs(const set<int> & exceptions); diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 3864ab935de0..bed7de0859a3 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -513,11 +513,11 @@ static void performOp(bool trusted, unsigned int clientVersion, } case wopOptimiseStore: - startWork(); - store->optimiseStore(); - stopWork(); - writeInt(1, to); - break; + startWork(); + store->optimiseStore(); + stopWork(); + writeInt(1, to); + break; default: throw Error(format("invalid operation %1%") % op); @@ -610,6 +610,8 @@ static void processConnection(bool trusted) assert(!canSendStderr); }; + canSendStderr = false; + _isInterrupted = false; printMsg(lvlDebug, format("%1% operations") % opCount); } @@ -696,7 +698,8 @@ static PeerInfo getPeerInfo(int remote) static void daemonLoop(char * * argv) { - chdir("/"); + if (chdir("/") == -1) + throw SysError("cannot change current directory"); /* Get rid of children automatically; don't let them become zombies. */ @@ -726,7 +729,8 @@ static void daemonLoop(char * * argv) /* Urgh, sockaddr_un allows path names of only 108 characters. So chdir to the socket directory so that we can pass a relative path name. */ - chdir(dirOf(socketPath).c_str()); + if (chdir(dirOf(socketPath).c_str()) == -1) + throw SysError("cannot change current directory"); Path socketPathRel = "./" + baseNameOf(socketPath); struct sockaddr_un addr; @@ -746,7 +750,8 @@ static void daemonLoop(char * * argv) if (res == -1) throw SysError(format("cannot bind to socket ‘%1%’") % socketPath); - chdir("/"); /* back to the root */ + if (chdir("/") == -1) /* back to the root */ + throw SysError("cannot change current directory"); if (listen(fdSocket, 5) == -1) throw SysError(format("cannot listen on socket ‘%1%’") % socketPath); @@ -799,6 +804,11 @@ static void daemonLoop(char * * argv) % (peer.uidKnown ? user : "<unknown>")); /* Fork a child to handle the connection. */ + ProcessOptions options; + options.errorPrefix = "unexpected Nix daemon error: "; + options.dieWithParent = false; + options.runExitHandlers = true; + options.allowVfork = false; startProcess([&]() { fdSocket.close(); @@ -821,7 +831,7 @@ static void daemonLoop(char * * argv) processConnection(trusted); exit(0); - }, false, "unexpected Nix daemon error: ", true); + }, options); } catch (Interrupted & e) { throw; @@ -832,15 +842,6 @@ static void daemonLoop(char * * argv) } -void run(Strings args) -{ - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; - } - -} - - int main(int argc, char * * argv) { return handleExceptions(argv[0], [&]() { diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 9a6e178f514e..e7214e657bd5 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -86,8 +86,6 @@ void processExpr(EvalState & state, const Strings & attrPaths, } } } - - state.printCanaries(); } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index c91bca97d534..87bc8c379de5 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -488,7 +488,7 @@ static void opReadLog(Strings opFlags, Strings opArgs) if (pathExists(logPath)) { /* !!! Make this run in O(1) memory. */ string log = readFile(logPath); - writeFull(STDOUT_FILENO, (const unsigned char *) log.data(), log.size()); + writeFull(STDOUT_FILENO, log); found = true; break; } diff --git a/tests/remote-builds.nix b/tests/remote-builds.nix index 2cd5ccfc6d45..0f16026a428a 100644 --- a/tests/remote-builds.nix +++ b/tests/remote-builds.nix @@ -25,7 +25,7 @@ let system = "i686-linux"; PATH = "''${utils}/bin"; builder = "''${utils}/bin/sh"; - args = [ "-c" "if [ ${toString nr} = 5 ]; then echo FAIL; exit 1; fi; echo Hello; mkdir $out $foo; cat /proc/sys/kernel/hostname > $out/host; ln -s $out $foo/bar; sleep 5" ]; + args = [ "-c" "if [ ${toString nr} = 5 ]; then echo FAIL; exit 1; fi; echo Hello; mkdir $out $foo; cat /proc/sys/kernel/hostname > $out/host; ln -s $out $foo/bar; sleep 10" ]; outputs = [ "out" "foo" ]; } ''; |