From 8b7f8b56f11145c1be5188113cbcdbea27e99525 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Wed, 23 Jun 2010 14:34:08 +0000 Subject: [PATCH 01/15] Added support for passing an (impure) NIX_BUILD_CORES variable to build expressions. This patch adds the configuration file variable "build-cores" and the command line argument "--cores". These settings specify the number of CPU cores to utilize for parallel building within a job, i.e. by passing an appropriate "-j" flag to GNU Make. The default value is 1, which means that parallel building is *disabled*. If the number of build cores is specified as 0 (synonymously: "guess" or "auto"), then the actual value is supposed to be auto-detected by builders at run-time, i.e by calling the nproc(1) utility from coreutils. The environment variable $NIX_BUILD_CORES is available to builders, but the contents of that variable does *not* influence the hash that goes into the $out store path, i.e. the number of build cores to be utilized can be changed at will without requiring any re-builds. --- nix.conf.example | 12 ++++++++++++ src/libmain/shared.cc | 14 ++++++++++++++ src/libstore/build.cc | 3 +++ src/libstore/globals.cc | 1 + src/libstore/globals.hh | 5 +++++ 5 files changed, 35 insertions(+) diff --git a/nix.conf.example b/nix.conf.example index e17cf3c25f..6175d86149 100644 --- a/nix.conf.example +++ b/nix.conf.example @@ -59,6 +59,18 @@ #build-max-jobs = 1 +### Option `build-cores' +# +# This option defines the number of CPU cores to utilize in parallel +# within a build job, i.e. by passing an appropriate `-jN' flag to +# GNU make. The default is 1, meaning that parallel building within +# jobs is disabled. Passing the special values `0', `auto', or +# `guess' causes Nix to try and auto-detect the number of available +# cores on the local host. This setting can be overridden using the +# `--cores' command line switch. +#build-cores = 1 + + ### Option `build-max-silent-time' # # This option defines the maximum number of seconds that a builder can diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 3fbec4b524..19aa1e71cc 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -135,6 +135,12 @@ static void initAndRun(int argc, char * * argv) /* Get some settings from the configuration file. */ thisSystem = querySetting("system", SYSTEM); maxBuildJobs = queryIntSetting("build-max-jobs", 1); + string tmp = querySetting("build-cores", "/UNDEFINED"); + std::transform(tmp.begin(), tmp.end(), tmp.begin(), tolower); + if (tmp == "auto" || tmp == "guess") + buildCores = 0; + else + buildCores = queryIntSetting("build-cores", 1); maxSilentTime = queryIntSetting("build-max-silent-time", 0); /* Catch SIGINT. */ @@ -226,6 +232,14 @@ static void initAndRun(int argc, char * * argv) tryFallback = true; else if (arg == "--max-jobs" || arg == "-j") maxBuildJobs = getIntArg(arg, i, args.end()); + else if (arg == "--cores") { + string tmp = *(++i); + std::transform(tmp.begin(), tmp.end(), tmp.begin(), tolower); + if (tmp == "auto" || tmp == "guess") + buildCores = 0u; + else + buildCores = getIntArg(arg, --i, args.end()); + } else if (arg == "--readonly-mode") readOnlyMode = true; else if (arg == "--max-silent-time") diff --git a/src/libstore/build.cc b/src/libstore/build.cc index f901c1f7d9..a53c23bf44 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1411,6 +1411,9 @@ void DerivationGoal::startBuilder() in the store or in the build directory). */ env["NIX_STORE"] = nixStore; + /* The maximum number of cores to utilize for parallel building. */ + env["NIX_BUILD_CORES"] = (format("%d") % buildCores).str(); + /* Add all bindings specified in the derivation. */ foreach (StringPairs::iterator, i, drv.env) env[i->first] = i->second; diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index cc0e44e8e3..75d2f69c2b 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -22,6 +22,7 @@ bool keepGoing = false; bool tryFallback = false; Verbosity buildVerbosity = lvlInfo; unsigned int maxBuildJobs = 1; +unsigned int buildCores = 1; bool readOnlyMode = false; string thisSystem = "unset"; time_t maxSilentTime = 0; diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index d3388e309c..a74a741d67 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -55,6 +55,11 @@ extern Verbosity buildVerbosity; /* Maximum number of parallel build jobs. 0 means unlimited. */ extern unsigned int maxBuildJobs; +/* Number of CPU cores to utilize in parallel within a build, i.e. by passing + this number to Make via '-j'. 0 means that the number of actual CPU cores on + the local host ought to be auto-detected. */ +extern unsigned int buildCores; + /* Read-only mode. Don't copy stuff to the store, don't change the database. */ extern bool readOnlyMode; From 560ab22f7db8238672ed3117ef8bf0de8baf9155 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 23 Jun 2010 21:11:33 +0000 Subject: [PATCH 02/15] * Ignore packages that don't have a version. * Work on a manifest instead of a channel directory. --- scripts/generate-patches.pl.in | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/scripts/generate-patches.pl.in b/scripts/generate-patches.pl.in index 148b7d81f1..d538df12e5 100755 --- a/scripts/generate-patches.pl.in +++ b/scripts/generate-patches.pl.in @@ -20,11 +20,11 @@ die unless scalar @ARGV == 5; my $hashAlgo = "sha256"; -my $cacheDir = $ARGV[0]; +my $narDir = $ARGV[0]; my $patchesDir = $ARGV[1]; my $patchesURL = $ARGV[2]; -my $srcDir = $ARGV[3]; -my $dstDir = $ARGV[4]; +my $srcManifest = $ARGV[3]; +my $dstManifest = $ARGV[4]; my $tmpDir = tempdir("nix-generate-patches.XXXXXX", CLEANUP => 1, TMPDIR => 1) or die "cannot create a temporary directory"; @@ -41,10 +41,10 @@ my %dstNarFiles; my %dstLocalPaths; my %dstPatches; -readManifest "$srcDir/MANIFEST", +readManifest "$srcManifest", \%srcNarFiles, \%srcLocalPaths, \%srcPatches; -readManifest "$dstDir/MANIFEST", +readManifest "$dstManifest", \%dstNarFiles, \%dstLocalPaths, \%dstPatches; @@ -55,8 +55,7 @@ sub findOutputPaths { foreach my $p (keys %{$narFiles}) { - # Ignore store expressions. - next if ($p =~ /\.store$/); + # Ignore derivations. next if ($p =~ /\.drv$/); # Ignore builders (too much ambiguity -- they're all called @@ -85,6 +84,7 @@ sub getNameVersion { $p =~ /\/[0-9a-z]+((?:-[a-zA-Z][^\/-]*)+)([^\/]*)$/; my $name = $1; my $version = $2; + return undef unless defined $name && defined $version; $name =~ s/^-//; $version =~ s/^-//; return ($name, $version); @@ -112,14 +112,14 @@ sub getNarBz2 { my $storePath = shift; my $narFileList = $$narFiles{$storePath}; - die "missing store expression $storePath" unless defined $narFileList; + die "missing path $storePath" unless defined $narFileList; my $narFile = @{$narFileList}[0]; die unless defined $narFile; $narFile->{url} =~ /\/([^\/]+)$/; die unless defined $1; - return "$cacheDir/$1"; + return "$narDir/$1"; } @@ -213,6 +213,7 @@ foreach my $p (keys %dstOutPaths) { # this path. (my $name, my $version) = getNameVersion $p; + next unless defined $name && defined $version; my @closest = (); my $closestVersion; @@ -222,6 +223,8 @@ foreach my $p (keys %dstOutPaths) { foreach my $q (keys %srcOutPaths) { (my $name2, my $version2) = getNameVersion $q; + next unless defined $name2 && defined $version2; + if ($name eq $name2) { # If the sizes differ too much, then skip. This @@ -241,11 +244,11 @@ foreach my $p (keys %dstOutPaths) { # If the numbers of weighted uses differ too much, then # skip. This disambiguates between, e.g., the bootstrap # GCC and the final GCC in Nixpkgs. - my $srcUses = computeUses \%srcNarFiles, $q; - my $dstUses = computeUses \%dstNarFiles, $p; - $ratio = $srcUses / $dstUses; - $ratio = 1 / $ratio if $ratio < 1; - print " USE $srcUses $dstUses $ratio $q\n"; +# my $srcUses = computeUses \%srcNarFiles, $q; +# my $dstUses = computeUses \%dstNarFiles, $p; +# $ratio = $srcUses / $dstUses; +# $ratio = 1 / $ratio if $ratio < 1; +# print " USE $srcUses $dstUses $ratio $q\n"; # if ($ratio >= 2) { # print " SKIPPING $q due to use ratio $ratio ($srcUses $dstUses)\n"; @@ -404,5 +407,5 @@ do { # Rewrite the manifest of the destination (with the new patches). -writeManifest "$dstDir/MANIFEST", +writeManifest "${dstManifest}", \%dstNarFiles, \%dstPatches; From a17071fef15115dc0e7052ebe091ffe8457f77d0 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 24 Jun 2010 17:51:04 +0000 Subject: [PATCH 03/15] Include to ensure that strcpy(), strlen(), and memset() are declared. An "using namespace std" was added locally in those functions that refer to names from . That is not pretty, but it's a very portable solution, because strcpy() and friends will be found in both the 'std' and in the global namespace. --- src/libstore/build.cc | 2 ++ src/libstore/remote-store.cc | 2 ++ src/nix-worker/nix-worker.cc | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index a53c23bf44..ef2f7adf31 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -2638,6 +2639,7 @@ void Worker::waitForInput() timeout.tv_sec = std::max((time_t) 0, lastWokenUp + wakeUpInterval - before); } else lastWokenUp = 0; + using namespace std; /* Use select() to wait for the input side of any logger pipe to become `available'. Note that `available' (i.e., non-blocking) includes EOF. */ diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 5143143f57..9db90c872a 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -13,6 +13,7 @@ #include #include +#include namespace nix { @@ -158,6 +159,7 @@ void RemoteStore::connectToDaemon() addr.sun_family = AF_UNIX; if (socketPathRel.size() >= sizeof(addr.sun_path)) throw Error(format("socket path `%1%' is too long") % socketPathRel); + using namespace std; strcpy(addr.sun_path, socketPathRel.c_str()); if (connect(fdSocket, (struct sockaddr *) &addr, sizeof(addr)) == -1) diff --git a/src/nix-worker/nix-worker.cc b/src/nix-worker/nix-worker.cc index bd2209c6d7..0052fbb7d5 100644 --- a/src/nix-worker/nix-worker.cc +++ b/src/nix-worker/nix-worker.cc @@ -7,6 +7,7 @@ #include "globals.hh" #include +#include #include #include #include @@ -111,6 +112,7 @@ static bool isFarSideClosed(int socket) time and wouldn't have to worry about races. */ static void sigPollHandler(int sigNo) { + using namespace std; try { /* Check that the far side actually closed. We're still getting spurious signals every once in a while. I.e., From bcec46057c0a99be3f0094cddfe0b06f27919f74 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 24 Jun 2010 17:51:13 +0000 Subject: [PATCH 04/15] src/libutil/util.cc: include to ensure that PATH_MAX is defined --- src/libutil/util.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 98912e7a00..c79ce1041c 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include "util.hh" From 4c21c016c578ced9d612ea3040ea225e57c477ec Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 24 Jun 2010 17:51:19 +0000 Subject: [PATCH 05/15] configure.ac: make flex and bison required programs The build fails if these tools aren't available. --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 8d3f308d71..079521fe59 100644 --- a/configure.ac +++ b/configure.ac @@ -155,8 +155,8 @@ NEED_PROG(patch, patch) AC_PATH_PROG(xmllint, xmllint, false) AC_PATH_PROG(xsltproc, xsltproc, false) AC_PATH_PROG(w3m, w3m, false) -AC_PATH_PROG(flex, flex, false) -AC_PATH_PROG(bison, bison, false) +NEED_PROG(flex, flex) +NEED_PROG(bison, bison) NEED_PROG(perl, perl) NEED_PROG(sed, sed) NEED_PROG(tar, tar) From d63375d52998e91c4d79563727baa29eb0753251 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 24 Jun 2010 17:51:24 +0000 Subject: [PATCH 06/15] configure.ac: Incredibly enough, tr(1) on Solaris doesn't understand A-Z syntax for ranges. --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 079521fe59..5af8aa5818 100644 --- a/configure.ac +++ b/configure.ac @@ -10,8 +10,8 @@ AC_CANONICAL_HOST # Construct a Nix system name (like "i686-linux"). AC_MSG_CHECKING([for the canonical Nix system name]) -cpu_name=$(uname -p | tr 'A-Z ' 'a-z_') -machine_name=$(uname -m | tr 'A-Z ' 'a-z_') +cpu_name=$(uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' 'abcdefghijklmnopqrstuvwxyz_') +machine_name=$(uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' 'abcdefghijklmnopqrstuvwxyz_') case $machine_name in i*86) @@ -30,7 +30,7 @@ case $machine_name in ;; esac -sys_name=$(uname -s | tr 'A-Z ' 'a-z_') +sys_name=$(uname -s | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' 'abcdefghijklmnopqrstuvwxyz_') case $sys_name in cygwin*) From af09fe12ddf356d93855cfe7b84d607e3103103a Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 24 Jun 2010 17:51:31 +0000 Subject: [PATCH 07/15] Fix build of bsdiff-4.3 on machines that don't have , such as Solaris. --- configure.ac | 4 ++++ src/bsdiff-4.3/Makefile.am | 2 +- src/bsdiff-4.3/compat-include/err.h | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/bsdiff-4.3/compat-include/err.h diff --git a/configure.ac b/configure.ac index 5af8aa5818..b21fd44800 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,10 @@ AC_CHECK_HEADERS([locale], [], [], []) AC_LANG_POP(C++) +# Check for . +AC_CHECK_HEADER([err.h], [], [bsddiff_compat_include="-Icompat-include"]) +AC_SUBST([bsddiff_compat_include]) + # Check whether we have the personality() syscall, which allows us to # do i686-linux builds on x86_64-linux machines. AC_CHECK_HEADERS([sys/personality.h]) diff --git a/src/bsdiff-4.3/Makefile.am b/src/bsdiff-4.3/Makefile.am index 4b3af07837..953139f559 100644 --- a/src/bsdiff-4.3/Makefile.am +++ b/src/bsdiff-4.3/Makefile.am @@ -8,4 +8,4 @@ bspatch_SOURCES = bspatch.c bspatch_LDADD = ${bzip2_lib} -AM_CFLAGS = -O3 ${bzip2_include} +AM_CFLAGS = -O3 ${bzip2_include} ${bsddiff_compat_include} diff --git a/src/bsdiff-4.3/compat-include/err.h b/src/bsdiff-4.3/compat-include/err.h new file mode 100644 index 0000000000..a851ded6f9 --- /dev/null +++ b/src/bsdiff-4.3/compat-include/err.h @@ -0,0 +1,12 @@ +/* Simulate BSD's functionality. */ + +#ifndef COMPAT_ERR_H_INCLUDED +#define COMPAT_ERR_H_INCLUDED 1 + +#include +#include + +#define err(rc,...) do { fprintf(stderr,__VA_ARGS__); exit(rc); } while(0) +#define errx(rc,...) do { fprintf(stderr,__VA_ARGS__); exit(rc); } while(0) + +#endif From a0d29040f79b365598fe75d01f72d29ab538206b Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 24 Jun 2010 22:22:24 +0000 Subject: [PATCH 08/15] Revert "configure.ac: make flex and bison required programs" This reverts commit 22405. Apparently, these programs aren't necessarily required when building from a release archive. --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b21fd44800..94a92c7ce5 100644 --- a/configure.ac +++ b/configure.ac @@ -159,8 +159,8 @@ NEED_PROG(patch, patch) AC_PATH_PROG(xmllint, xmllint, false) AC_PATH_PROG(xsltproc, xsltproc, false) AC_PATH_PROG(w3m, w3m, false) -NEED_PROG(flex, flex) -NEED_PROG(bison, bison) +AC_PATH_PROG(flex, flex, false) +AC_PATH_PROG(bison, bison, false) NEED_PROG(perl, perl) NEED_PROG(sed, sed) NEED_PROG(tar, tar) From 60b632b173e633cc5346f8a5491ef637e1f78166 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Fri, 25 Jun 2010 14:05:37 +0000 Subject: [PATCH 09/15] tests/build-hook.hook.sh: prefer more portable `...` syntax over $(...) for running sub-shells The /bin/sh interpreter on Solaris doesn't understand $(...) syntax for running sub-shells. Consequently, this test fails on Solaris. To remedy the situation, the script either needs to be run by /bin/bash -- which is non-standard --, or it needs to use the ancient but portable `...` syntax. --- tests/build-hook.hook.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/build-hook.hook.sh b/tests/build-hook.hook.sh index 18eba283e1..83fa3bf787 100755 --- a/tests/build-hook.hook.sh +++ b/tests/build-hook.hook.sh @@ -6,11 +6,11 @@ drv=$4 echo "HOOK for $drv" >&2 -outPath=$(sed 's/Derive(\[("out",\"\([^\"]*\)\".*/\1/' $drv) +outPath=`sed 's/Derive(\[("out",\"\([^\"]*\)\".*/\1/' $drv` echo "output path is $outPath" >&2 -if $(echo $outPath | grep -q input-1); then +if `echo $outPath | grep -q input-1`; then echo "# accept" >&2 read x echo "got $x" From 7e043d28a64b38e18511140a9a42494977ca6015 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Thu, 15 Jul 2010 14:35:20 +0000 Subject: [PATCH 10/15] src/bsdiff-4.3/Makefile.am: include the 'compat-include' directory in distribution tarballs --- src/bsdiff-4.3/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bsdiff-4.3/Makefile.am b/src/bsdiff-4.3/Makefile.am index 953139f559..57970bc55c 100644 --- a/src/bsdiff-4.3/Makefile.am +++ b/src/bsdiff-4.3/Makefile.am @@ -1,3 +1,5 @@ +EXTRA_DIST = compat-include + libexec_PROGRAMS = bsdiff bspatch bsdiff_SOURCES = bsdiff.c From 532d766c279daf190728b4815b92f04623e7fb7f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 21 Jul 2010 11:30:23 +0000 Subject: [PATCH 11/15] * Don't barf if the source NAR for a patch has disappeared. --- scripts/generate-patches.pl.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/generate-patches.pl.in b/scripts/generate-patches.pl.in index d538df12e5..dba6473508 100755 --- a/scripts/generate-patches.pl.in +++ b/scripts/generate-patches.pl.in @@ -64,7 +64,7 @@ sub findOutputPaths { next if ($p =~ /\.patch$/); # Don't bother including tar files etc. - next if ($p =~ /\.tar\.(gz|bz2)$/ || $p =~ /\.zip$/ || $p =~ /\.bin$/); + next if ($p =~ /\.tar$/ || $p =~ /\.tar\.(gz|bz2|Z|lzma|xz)$/ || $p =~ /\.zip$/ || $p =~ /\.bin$/ || $p =~ /\.tgz$/ || $p =~ /\.rpm$/ || $p =~ /cvs-export$/ || $p =~ /fetchhg$/); $outPaths{$p} = 1; } @@ -291,6 +291,11 @@ foreach my $p (keys %dstOutPaths) { my $srcNarBz2 = getNarBz2 \%srcNarFiles, $closest; my $dstNarBz2 = getNarBz2 \%dstNarFiles, $p; + if (! -f $srcNarBz2) { + warn "patch source archive $srcNarBz2 is missing\n"; + next; + } + system("@bunzip2@ < $srcNarBz2 > $tmpDir/A") == 0 or die "cannot unpack $srcNarBz2"; From 7af6a2fd71e95bdc28e0015b1e89a9b81ef32711 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Aug 2010 11:54:44 +0000 Subject: [PATCH 12/15] * intersectAttrs: optimise for the case where the second set is larger than the first set. (That's usually the case with callPackage.) --- src/libexpr/primops.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 42c8586116..68f66acc74 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -788,13 +788,13 @@ static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v) state.forceAttrs(*args[1]); state.mkAttrs(v); - - foreach (Bindings::iterator, i, *args[1]->attrs) { - Bindings::iterator j = args[0]->attrs->find(i->first); - if (j != args[0]->attrs->end()) { - Attr & a = (*v.attrs)[i->first]; - mkCopy(a.value, i->second.value); - a.pos = i->second.pos; + + foreach (Bindings::iterator, i, *args[0]->attrs) { + Bindings::iterator j = args[1]->attrs->find(i->first); + if (j != args[1]->attrs->end()) { + Attr & a = (*v.attrs)[j->first]; + mkCopy(a.value, j->second.value); + a.pos = j->second.pos; } } } From 6d6200f37afe10e8da3b08582a926245538af5d6 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Aug 2010 16:31:05 +0000 Subject: [PATCH 13/15] * Optimisation in the // operator: if one of the sets is empty, return the other set. --- src/libexpr/eval.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index eb1d8d432c..96bda43a32 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -750,13 +750,15 @@ void ExprOpImpl::eval(EvalState & state, Env & env, Value & v) void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) { - Value v2; - state.evalAttrs(env, e1, v2); - - state.cloneAttrs(v2, v); - + Value v1, v2; + state.evalAttrs(env, e1, v1); state.evalAttrs(env, e2, v2); - + + if (v1.attrs->size() == 0) { v = v2; return; } + if (v2.attrs->size() == 0) { v = v1; return; } + + state.cloneAttrs(v1, v); + foreach (Bindings::iterator, i, *v2.attrs) { Attr & a = (*v.attrs)[i->first]; mkCopy(a.value, i->second.value); From 315d8fbd7570532e008b03d50226f53fa9e460db Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Aug 2010 09:32:42 +0000 Subject: [PATCH 14/15] * Set the default system filter to "*". This ensures that (for instance) "nix-env -i wine" works on x86_64-linux, even though Wine is built on i686-linux. In the event that there are multiple matching derivations, prefer those built for the current system. --- src/nix-env/nix-env.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 12a256a091..92ce41067d 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -247,11 +247,12 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, } /* If `newestOnly', if a selector matches multiple derivations - with the same name, pick the one with the highest priority. - If there are multiple derivations with the same priority, - pick the one with the highest version. If there are - multiple derivations with the same priority and name and - version, then pick the first one. */ + with the same name, pick the one matching the current + system. If there are still multiple derivations, pick the + one with the highest priority. If there are still multiple + derivations, pick the one with the highest version. + Finally, if there are still multiple derivations, + arbitrarily pick the first one. */ if (newestOnly) { /* Map from package names to derivations. */ @@ -266,7 +267,12 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, Newest::iterator k = newest.find(drvName.name); if (k != newest.end()) { - d = comparePriorities(state, j->first, k->second.first); + d = j->first.system == k->second.first.system ? 0 : + j->first.system == thisSystem ? 1 : + k->second.first.system == thisSystem ? -1 : 0; + printMsg(lvlError, format("%1% %2% %3% %4%") % j->first.system % k->second.first.system % thisSystem % d); + if (d == 0) + d = comparePriorities(state, j->first, k->second.first); if (d == 0) d = compareVersions(drvName.version, DrvName(k->second.first.name).version); } @@ -1230,7 +1236,7 @@ void run(Strings args) globals.instSource.type = srcUnknown; globals.instSource.nixExprPath = getDefNixExprPath(); - globals.instSource.systemFilter = thisSystem; + globals.instSource.systemFilter = "*"; globals.dryRun = false; globals.preserveInstalled = false; From 750be19ae865da3ee03c132a287148f2402ad72b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 4 Aug 2010 12:23:59 +0000 Subject: [PATCH 15/15] * Remove "auto" and "guess" as synonyms for 0 in the handling of build-cores and --cores. They're superfluous and just complicate the parsing. --- nix.conf.example | 11 +++++------ src/libmain/shared.cc | 17 +++-------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/nix.conf.example b/nix.conf.example index 6175d86149..7063bed54c 100644 --- a/nix.conf.example +++ b/nix.conf.example @@ -62,12 +62,11 @@ ### Option `build-cores' # # This option defines the number of CPU cores to utilize in parallel -# within a build job, i.e. by passing an appropriate `-jN' flag to -# GNU make. The default is 1, meaning that parallel building within -# jobs is disabled. Passing the special values `0', `auto', or -# `guess' causes Nix to try and auto-detect the number of available -# cores on the local host. This setting can be overridden using the -# `--cores' command line switch. +# within a build job, i.e. by passing an appropriate `-jN' flag to GNU +# make. The default is 1, meaning that parallel building within jobs +# is disabled. Passing the special value `0' causes Nix to try and +# auto-detect the number of available cores on the local host. This +# setting can be overridden using the `--cores' command line switch. #build-cores = 1 diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 19aa1e71cc..eddc4e64b3 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -135,12 +135,7 @@ static void initAndRun(int argc, char * * argv) /* Get some settings from the configuration file. */ thisSystem = querySetting("system", SYSTEM); maxBuildJobs = queryIntSetting("build-max-jobs", 1); - string tmp = querySetting("build-cores", "/UNDEFINED"); - std::transform(tmp.begin(), tmp.end(), tmp.begin(), tolower); - if (tmp == "auto" || tmp == "guess") - buildCores = 0; - else - buildCores = queryIntSetting("build-cores", 1); + buildCores = queryIntSetting("build-cores", 1); maxSilentTime = queryIntSetting("build-max-silent-time", 0); /* Catch SIGINT. */ @@ -232,14 +227,8 @@ static void initAndRun(int argc, char * * argv) tryFallback = true; else if (arg == "--max-jobs" || arg == "-j") maxBuildJobs = getIntArg(arg, i, args.end()); - else if (arg == "--cores") { - string tmp = *(++i); - std::transform(tmp.begin(), tmp.end(), tmp.begin(), tolower); - if (tmp == "auto" || tmp == "guess") - buildCores = 0u; - else - buildCores = getIntArg(arg, --i, args.end()); - } + else if (arg == "--cores") + buildCores = getIntArg(arg, i, args.end()); else if (arg == "--readonly-mode") readOnlyMode = true; else if (arg == "--max-silent-time")