diff options
37 files changed, 202 insertions, 113 deletions
diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml index 431c0e6d3570..1865bb37c860 100644 --- a/doc/manual/command-ref/conf-file.xml +++ b/doc/manual/command-ref/conf-file.xml @@ -254,6 +254,25 @@ false</literal>.</para> </varlistentry> + <varlistentry xml:id="conf-extra-platforms"><term><literal>extra-platforms</literal></term> + + <listitem><para>Platforms other than the native one which + this machine is capable of building for. This can be useful for + supporting additional architectures on compatible machines: + i686-linux can be built on x86_64-linux machines (and the default + for this setting reflects this); armv7 is backwards-compatible with + armv6 and armv5tel; some aarch64 machines can also natively run + 32-bit ARM code; and qemu-user may be used to support non-native + platforms (though this may be slow and buggy). Most values for this + are not enabled by default because build systems will often + misdetect the target platform and generate incompatible code, so you + may wish to cross-check the results of using this option against + proper natively-built versions of your + derivations.</para></listitem> + + </varlistentry> + + <varlistentry xml:id="conf-extra-substituters"><term><literal>extra-substituters</literal></term> <listitem><para>Additional binary caches appended to those diff --git a/doc/manual/command-ref/nix-collect-garbage.xml b/doc/manual/command-ref/nix-collect-garbage.xml index 35a78c5b2015..43e06879691c 100644 --- a/doc/manual/command-ref/nix-collect-garbage.xml +++ b/doc/manual/command-ref/nix-collect-garbage.xml @@ -22,12 +22,6 @@ <arg><option>--delete-old</option></arg> <arg><option>-d</option></arg> <arg><option>--delete-older-than</option> <replaceable>period</replaceable></arg> - <group choice='opt'> - <arg choice='plain'><option>--print-roots</option></arg> - <arg choice='plain'><option>--print-live</option></arg> - <arg choice='plain'><option>--print-dead</option></arg> - <arg choice='plain'><option>--delete</option></arg> - </group> <arg><option>--max-freed</option> <replaceable>bytes</replaceable></arg> <arg><option>--dry-run</option></arg> </cmdsynopsis> diff --git a/doc/manual/command-ref/opt-common-syn.xml b/doc/manual/command-ref/opt-common-syn.xml index 168bef080f4f..b610b54b9620 100644 --- a/doc/manual/command-ref/opt-common-syn.xml +++ b/doc/manual/command-ref/opt-common-syn.xml @@ -9,6 +9,9 @@ </group> </arg> <arg> + <arg choice='plain'><option>--quiet</option></arg> +</arg> +<arg> <group choice='plain'> <arg choice='plain'><option>--no-build-output</option></arg> <arg choice='plain'><option>-Q</option></arg> diff --git a/doc/manual/command-ref/opt-common.xml b/doc/manual/command-ref/opt-common.xml index bcb60b30125c..4c572e129445 100644 --- a/doc/manual/command-ref/opt-common.xml +++ b/doc/manual/command-ref/opt-common.xml @@ -75,6 +75,23 @@ </varlistentry> +<varlistentry><term><option>--quiet</option></term> + + <listitem> + + <para>Decreases the level of verbosity of diagnostic messages + printed on standard error. This is the inverse option to + <option>-v</option> / <option>--verbose</option>. + </para> + + <para>This option may be specified repeatedly. See the previous + verbosity levels list.</para> + + </listitem> + +</varlistentry> + + <varlistentry><term><option>--no-build-output</option> / <option>-Q</option></term> <listitem><para>By default, output written by builders to standard diff --git a/doc/manual/expressions/advanced-attributes.xml b/doc/manual/expressions/advanced-attributes.xml index f3cf98371302..dfd013b5cf31 100644 --- a/doc/manual/expressions/advanced-attributes.xml +++ b/doc/manual/expressions/advanced-attributes.xml @@ -112,7 +112,13 @@ impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ]; linkend="fixed-output-drvs">fixed-output derivations</link>, where impurities such as these are okay since (the hash of) the output is known in advance. It is ignored for all other - derivations.</para></listitem> + derivations.</para> + + <warning><para><varname>impureEnvVars</varname> implementation takes + environment variables from the current builder process. When a daemon is + building its environmental variables are used. Without the daemon, the + environmental variables come from the environment of the + <command>nix-build</command>.</para></warning></listitem> </varlistentry> diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc index 9cd01bb61bf5..38dbe3e58b26 100644 --- a/src/build-remote/build-remote.cc +++ b/src/build-remote/build-remote.cc @@ -98,7 +98,9 @@ int main (int argc, char * * argv) source >> drvPath; auto requiredFeatures = readStrings<std::set<std::string>>(source); - auto canBuildLocally = amWilling && (neededSystem == settings.thisSystem); + auto canBuildLocally = amWilling + && ( neededSystem == settings.thisSystem + || settings.extraPlatforms.get().count(neededSystem) > 0); /* Error ignored here, will be caught later */ mkdir(currentLoad.c_str(), 0777); diff --git a/src/build-remote/local.mk b/src/build-remote/local.mk index 64368a43ff73..50b0409d1886 100644 --- a/src/build-remote/local.mk +++ b/src/build-remote/local.mk @@ -4,6 +4,6 @@ build-remote_DIR := $(d) build-remote_INSTALL_DIR := $(libexecdir)/nix -build-remote_LIBS = libmain libutil libformat libstore +build-remote_LIBS = libmain libformat libstore libutil build-remote_SOURCES := $(d)/build-remote.cc diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc index b284daa3c2f7..0474865c6d7d 100644 --- a/src/libexpr/attr-set.cc +++ b/src/libexpr/attr-set.cc @@ -24,13 +24,15 @@ static void * allocBytes(size_t n) /* Allocate a new array of attributes for an attribute set with a specific capacity. The space is implicitly reserved after the Bindings structure. */ -Bindings * EvalState::allocBindings(Bindings::size_t capacity) +Bindings * EvalState::allocBindings(size_t capacity) { - return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings(capacity); + if (capacity > std::numeric_limits<Bindings::size_t>::max()) + throw Error("attribute set of size %d is too big", capacity); + return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity); } -void EvalState::mkAttrs(Value & v, unsigned int capacity) +void EvalState::mkAttrs(Value & v, size_t capacity) { if (capacity == 0) { v = vEmptySet; diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 37b977736e28..353097f89713 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -317,10 +317,20 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store) if (settings.restrictEval || settings.pureEval) { allowedPaths = PathSet(); + for (auto & i : searchPath) { auto r = resolveSearchPathElem(i); if (!r.first) continue; - allowedPaths->insert(r.second); + + auto path = r.second; + + if (store->isInStore(r.second)) { + PathSet closure; + store->computeFSClosure(store->toStorePath(r.second), closure); + for (auto & path : closure) + allowedPaths->insert(path); + } else + allowedPaths->insert(r.second); } } @@ -422,7 +432,7 @@ Value * EvalState::addConstant(const string & name, Value & v) Value * EvalState::addPrimOp(const string & name, - unsigned int arity, PrimOpFun primOp) + size_t arity, PrimOpFun primOp) { if (arity == 0) { Value v; @@ -528,7 +538,7 @@ Value & mkString(Value & v, const string & s, const PathSet & context) { mkString(v, s.c_str()); if (!context.empty()) { - unsigned int n = 0; + size_t n = 0; v.string.context = (const char * *) allocBytes((context.size() + 1) * sizeof(char *)); for (auto & i : context) @@ -547,7 +557,7 @@ void mkPath(Value & v, const char * s) inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) { - for (unsigned int l = var.level; l; --l, env = env->up) ; + for (size_t l = var.level; l; --l, env = env->up) ; if (!var.fromWith) return env->values[var.displ]; @@ -566,7 +576,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) } if (!env->prevWith) throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos); - for (unsigned int l = env->prevWith; l; --l, env = env->up) ; + for (size_t l = env->prevWith; l; --l, env = env->up) ; } } @@ -578,14 +588,15 @@ Value * EvalState::allocValue() } -Env & EvalState::allocEnv(unsigned int size) +Env & EvalState::allocEnv(size_t size) { - assert(size <= std::numeric_limits<decltype(Env::size)>::max()); + if (size > std::numeric_limits<decltype(Env::size)>::max()) + throw Error("environment size %d is too big", size); nrEnvs++; nrValuesInEnvs += size; Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *)); - env->size = size; + env->size = (decltype(Env::size)) size; /* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */ @@ -593,7 +604,7 @@ Env & EvalState::allocEnv(unsigned int size) } -void EvalState::mkList(Value & v, unsigned int size) +void EvalState::mkList(Value & v, size_t size) { clearValue(v); if (size == 1) @@ -628,7 +639,7 @@ void EvalState::mkThunk_(Value & v, Expr * expr) void EvalState::mkPos(Value & v, Pos * pos) { - if (pos) { + if (pos && pos->file.set()) { mkAttrs(v, 3); mkString(*allocAttr(v, sFile), pos->file); mkInt(*allocAttr(v, sLine), pos->line); @@ -805,7 +816,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) /* The recursive attributes are evaluated in the new environment, while the inherited attributes are evaluated in the original environment. */ - unsigned int displ = 0; + size_t displ = 0; for (auto & i : attrs) { Value * vAttr; if (hasOverrides && !i.second.inherited) { @@ -879,7 +890,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) /* The recursive attributes are evaluated in the new environment, while the inherited attributes are evaluated in the original environment. */ - unsigned int displ = 0; + size_t displ = 0; for (auto & i : attrs->attrs) env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2); @@ -890,7 +901,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) void ExprList::eval(EvalState & state, Env & env, Value & v) { state.mkList(v, elems.size()); - for (unsigned int n = 0; n < elems.size(); ++n) + for (size_t n = 0; n < elems.size(); ++n) v.listElems()[n] = elems[n]->maybeThunk(state, env); } @@ -1012,22 +1023,22 @@ void ExprApp::eval(EvalState & state, Env & env, Value & v) void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos) { /* Figure out the number of arguments still needed. */ - unsigned int argsDone = 0; + size_t argsDone = 0; Value * primOp = &fun; while (primOp->type == tPrimOpApp) { argsDone++; primOp = primOp->primOpApp.left; } assert(primOp->type == tPrimOp); - unsigned int arity = primOp->primOp->arity; - unsigned int argsLeft = arity - argsDone; + auto arity = primOp->primOp->arity; + auto argsLeft = arity - argsDone; if (argsLeft == 1) { /* We have all the arguments, so call the primop. */ /* Put all the arguments in an array. */ Value * vArgs[arity]; - unsigned int n = arity - 1; + auto n = arity - 1; vArgs[n--] = &arg; for (Value * arg = &fun; arg->type == tPrimOpApp; arg = arg->primOpApp.left) vArgs[n--] = arg->primOpApp.right; @@ -1076,13 +1087,13 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po ExprLambda & lambda(*fun.lambda.fun); - unsigned int size = + auto size = (lambda.arg.empty() ? 0 : 1) + (lambda.matchAttrs ? lambda.formals->formals.size() : 0); Env & env2(allocEnv(size)); env2.up = fun.lambda.env; - unsigned int displ = 0; + size_t displ = 0; if (!lambda.matchAttrs) env2.values[displ++] = &arg; @@ -1096,7 +1107,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po /* For each formal argument, get the actual argument. If there is no matching actual argument but the formal argument has a default, use the default. */ - unsigned int attrsUsed = 0; + size_t attrsUsed = 0; for (auto & i : lambda.formals->formals) { Bindings::iterator j = arg.attrs->find(i.name); if (j == arg.attrs->end()) { @@ -1294,15 +1305,15 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) } -void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos) +void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Pos & pos) { nrListConcats++; Value * nonEmpty = 0; - unsigned int len = 0; - for (unsigned int n = 0; n < nrLists; ++n) { + size_t len = 0; + for (size_t n = 0; n < nrLists; ++n) { forceList(*lists[n], pos); - unsigned int l = lists[n]->listSize(); + auto l = lists[n]->listSize(); len += l; if (l) nonEmpty = lists[n]; } @@ -1314,8 +1325,8 @@ void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, co mkList(v, len); auto out = v.listElems(); - for (unsigned int n = 0, pos = 0; n < nrLists; ++n) { - unsigned int l = lists[n]->listSize(); + for (size_t n = 0, pos = 0; n < nrLists; ++n) { + auto l = lists[n]->listSize(); if (l) memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *)); pos += l; @@ -1410,7 +1421,7 @@ void EvalState::forceValueDeep(Value & v) } else if (v.isList()) { - for (unsigned int n = 0; n < v.listSize(); ++n) + for (size_t n = 0; n < v.listSize(); ++n) recurse(*v.listElems()[n]); } }; @@ -1562,7 +1573,7 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context, if (v.isList()) { string result; - for (unsigned int n = 0; n < v.listSize(); ++n) { + for (size_t n = 0; n < v.listSize(); ++n) { result += coerceToString(pos, *v.listElems()[n], context, coerceMore, copyToStore); if (n < v.listSize() - 1 @@ -1649,7 +1660,7 @@ bool EvalState::eqValues(Value & v1, Value & v2) case tList2: case tListN: if (v1.listSize() != v2.listSize()) return false; - for (unsigned int n = 0; n < v1.listSize(); ++n) + for (size_t n = 0; n < v1.listSize(); ++n) if (!eqValues(*v1.listElems()[n], *v2.listElems()[n])) return false; return true; @@ -1740,26 +1751,26 @@ void EvalState::printStats() v = lvlInfo; printMsg(v, format("calls to %1% primops:") % primOpCalls.size()); - typedef std::multimap<unsigned int, Symbol> PrimOpCalls_; + typedef std::multimap<size_t, Symbol> PrimOpCalls_; PrimOpCalls_ primOpCalls_; for (auto & i : primOpCalls) - primOpCalls_.insert(std::pair<unsigned int, Symbol>(i.second, i.first)); + primOpCalls_.insert(std::pair<size_t, Symbol>(i.second, i.first)); for (auto i = primOpCalls_.rbegin(); i != primOpCalls_.rend(); ++i) printMsg(v, format("%1$10d %2%") % i->first % i->second); printMsg(v, format("calls to %1% functions:") % functionCalls.size()); - typedef std::multimap<unsigned int, ExprLambda *> FunctionCalls_; + typedef std::multimap<size_t, ExprLambda *> FunctionCalls_; FunctionCalls_ functionCalls_; for (auto & i : functionCalls) - functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i.second, i.first)); + functionCalls_.insert(std::pair<size_t, ExprLambda *>(i.second, i.first)); for (auto i = functionCalls_.rbegin(); i != functionCalls_.rend(); ++i) printMsg(v, format("%1$10d %2%") % i->first % i->second->showNamePos()); printMsg(v, format("evaluations of %1% attributes:") % attrSelects.size()); - typedef std::multimap<unsigned int, Pos> AttrSelects_; + typedef std::multimap<size_t, Pos> AttrSelects_; AttrSelects_ attrSelects_; for (auto & i : attrSelects) - attrSelects_.insert(std::pair<unsigned int, Pos>(i.second, i.first)); + attrSelects_.insert(std::pair<size_t, Pos>(i.second, i.first)); for (auto i = attrSelects_.rbegin(); i != attrSelects_.rend(); ++i) printMsg(v, format("%1$10d %2%") % i->first % i->second); @@ -1810,7 +1821,7 @@ size_t valueSize(Value & v) if (seen.find(v.listElems()) == seen.end()) { seen.insert(v.listElems()); sz += v.listSize() * sizeof(Value *); - for (unsigned int n = 0; n < v.listSize(); ++n) + for (size_t n = 0; n < v.listSize(); ++n) sz += doValue(*v.listElems()[n]); } break; @@ -1846,7 +1857,7 @@ size_t valueSize(Value & v) size_t sz = sizeof(Env) + sizeof(Value *) * env.size; - for (unsigned int i = 0; i < env.size; ++i) + for (size_t i = 0; i < env.size; ++i) if (env.values[i]) sz += doValue(*env.values[i]); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 9d8799b7906b..86e93a5ac9ce 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -214,7 +214,7 @@ private: Value * addConstant(const string & name, Value & v); Value * addPrimOp(const string & name, - unsigned int arity, PrimOpFun primOp); + size_t arity, PrimOpFun primOp); public: @@ -248,18 +248,18 @@ public: /* Allocation primitives. */ Value * allocValue(); - Env & allocEnv(unsigned int size); + Env & allocEnv(size_t size); Value * allocAttr(Value & vAttrs, const Symbol & name); - Bindings * allocBindings(Bindings::size_t capacity); + Bindings * allocBindings(size_t capacity); - void mkList(Value & v, unsigned int length); - void mkAttrs(Value & v, unsigned int capacity); + void mkList(Value & v, size_t length); + void mkAttrs(Value & v, size_t capacity); void mkThunk_(Value & v, Expr * expr); void mkPos(Value & v, Pos * pos); - void concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos); + void concatLists(Value & v, size_t nrLists, Value * * lists, const Pos & pos); /* Print statistics. */ void printStats(); @@ -282,15 +282,15 @@ private: bool countCalls; - typedef std::map<Symbol, unsigned int> PrimOpCalls; + typedef std::map<Symbol, size_t> PrimOpCalls; PrimOpCalls primOpCalls; - typedef std::map<ExprLambda *, unsigned int> FunctionCalls; + typedef std::map<ExprLambda *, size_t> FunctionCalls; FunctionCalls functionCalls; void incrFunctionCall(ExprLambda * fun); - typedef std::map<Pos, unsigned int> AttrSelects; + typedef std::map<Pos, size_t> AttrSelects; AttrSelects attrSelects; friend struct ExprOpUpdate; diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 8c8f39640681..b486595f07ab 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -255,7 +255,7 @@ struct ExprWith : Expr { Pos pos; Expr * attrs, * body; - unsigned int prevWith; + size_t prevWith; ExprWith(const Pos & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { }; COMMON_METHODS }; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index ef11dd609217..e3f4521844e8 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -136,8 +136,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex whitespace-only final lines are not taken into account. (So the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */ bool atStartOfLine = true; /* = seen only whitespace in the current line */ - unsigned int minIndent = 1000000; - unsigned int curIndent = 0; + size_t minIndent = 1000000; + size_t curIndent = 0; for (auto & i : es) { ExprIndStr * e = dynamic_cast<ExprIndStr *>(i); if (!e) { @@ -148,7 +148,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex } continue; } - for (unsigned int j = 0; j < e->s.size(); ++j) { + for (size_t j = 0; j < e->s.size(); ++j) { if (atStartOfLine) { if (e->s[j] == ' ') curIndent++; @@ -170,8 +170,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex /* Strip spaces from each line. */ vector<Expr *> * es2 = new vector<Expr *>; atStartOfLine = true; - unsigned int curDropped = 0; - unsigned int n = es.size(); + size_t curDropped = 0; + size_t n = es.size(); for (vector<Expr *>::iterator i = es.begin(); i != es.end(); ++i, --n) { ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i); if (!e) { @@ -182,7 +182,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex } string s2; - for (unsigned int j = 0; j < e->s.size(); ++j) { + for (size_t j = 0; j < e->s.size(); ++j) { if (atStartOfLine) { if (e->s[j] == ' ') { if (curDropped++ >= minIndent) diff --git a/src/libexpr/symbol-table.hh b/src/libexpr/symbol-table.hh index c2ee49dd32fb..44929f7eea06 100644 --- a/src/libexpr/symbol-table.hh +++ b/src/libexpr/symbol-table.hh @@ -69,7 +69,7 @@ public: return Symbol(&*res.first); } - unsigned int size() const + size_t size() const { return symbols.size(); } diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 9df516f062ef..66b41a158400 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -128,7 +128,7 @@ struct Value const char * path; Bindings * attrs; struct { - unsigned int size; + size_t size; Value * * elems; } bigList; Value * smallList[2]; @@ -166,7 +166,7 @@ struct Value return type == tList1 || type == tList2 ? smallList : bigList.elems; } - unsigned int listSize() const + size_t listSize() const { return type == tList1 ? 1 : type == tList2 ? 2 : bigList.size; } diff --git a/src/libmain/stack.cc b/src/libmain/stack.cc index cc0eea68fca3..13896aeecb6e 100644 --- a/src/libmain/stack.cc +++ b/src/libmain/stack.cc @@ -30,7 +30,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"; - [[gnu::unused]] int res = write(2, msg, strlen(msg)); + [[gnu::unused]] auto res = write(2, msg, strlen(msg)); _exit(1); // maybe abort instead? } } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index e5285ad9a938..f70ab8108fd7 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -842,9 +842,9 @@ private: BuildResult result; /* The current round, if we're building multiple times. */ - unsigned int curRound = 1; + size_t curRound = 1; - unsigned int nrRounds; + size_t nrRounds; /* Path registration info from the previous round, if we're building multiple times. Since this contains the hash, it @@ -1169,7 +1169,7 @@ void DerivationGoal::outputsSubstituted() return; } - unsigned int nrInvalid = checkPathValidity(false, buildMode == bmRepair).size(); + auto nrInvalid = checkPathValidity(false, buildMode == bmRepair).size(); if (buildMode == bmNormal && nrInvalid == 0) { done(BuildResult::Substituted); return; @@ -2499,6 +2499,10 @@ void setupSeccomp() seccomp_arch_add(ctx, SCMP_ARCH_X32) != 0) throw SysError("unable to add X32 seccomp architecture"); + if (settings.thisSystem == "aarch64-linux" && + seccomp_arch_add(ctx, SCMP_ARCH_ARM) != 0) + printError("unsable to add ARM seccomp architecture; this may result in spurious build failures if running 32-bit ARM processes."); + /* Prevent builders from creating setuid/setgid binaries. */ for (int perm : { S_ISUID, S_ISGID }) { if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1, @@ -2699,8 +2703,8 @@ void DerivationGoal::runChild() } else { if (errno != EINVAL) throw SysError("mounting /dev/pts"); - doBind("/dev/pts", "/dev/pts"); - doBind("/dev/ptmx", "/dev/ptmx"); + doBind("/dev/pts", chrootRootDir + "/dev/pts"); + doBind("/dev/ptmx", chrootRootDir + "/dev/ptmx"); } } @@ -3245,6 +3249,8 @@ void DerivationGoal::registerOutputs() info.ultimate = true; worker.store.signPathInfo(info); + if (!info.references.empty()) info.ca.clear(); + infos.push_back(info); } diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index a0a0d78b7d30..74b861281ee0 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -57,16 +57,8 @@ bool BasicDerivation::isBuiltin() const bool BasicDerivation::canBuildLocally() const { return platform == settings.thisSystem - || isBuiltin() -#if __linux__ - || (platform == "i686-linux" && settings.thisSystem == "x86_64-linux") - || (platform == "armv6l-linux" && settings.thisSystem == "armv7l-linux") - || (platform == "armv5tel-linux" && (settings.thisSystem == "armv7l-linux" || settings.thisSystem == "armv6l-linux")) -#elif __FreeBSD__ - || (platform == "i686-linux" && settings.thisSystem == "x86_64-freebsd") - || (platform == "i686-linux" && settings.thisSystem == "i686-freebsd") -#endif - ; + || settings.extraPlatforms.get().count(platform) > 0 + || isBuiltin(); } diff --git a/src/libstore/download.cc b/src/libstore/download.cc index 4d7f5690192d..18f9094f82e0 100644 --- a/src/libstore/download.cc +++ b/src/libstore/download.cc @@ -173,7 +173,11 @@ struct CurlDownloader : public Downloader int progressCallback(double dltotal, double dlnow) { - act.progress(dlnow, dltotal); + try { + act.progress(dlnow, dltotal); + } catch (nix::Interrupted &) { + assert(_isInterrupted); + } return _isInterrupted; } @@ -730,8 +734,8 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa Hash gotHash = unpack ? hashPath(expectedHash.type, store->toRealPath(storePath)).first : hashFile(expectedHash.type, store->toRealPath(storePath)); - throw nix::Error("hash mismatch in file downloaded from '%s': expected hash '%s', got '%s'", - url, expectedHash.to_string(), gotHash.to_string()); + throw nix::Error("hash mismatch in file downloaded from '%s': got hash '%s' instead of the expected hash '%s'", + url, gotHash.to_string(), expectedHash.to_string()); } return store->toRealPath(storePath); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 7430bbedbe44..9360096aae8c 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -295,6 +295,13 @@ public: "Nix store has a valid signature (that is, one signed using a key " "listed in 'trusted-public-keys'."}; + Setting<StringSet> extraPlatforms{this, + std::string{SYSTEM} == "x86_64-linux" ? StringSet{"i686-linux"} : StringSet{}, + "extra-platforms", + "Additional platforms that can be built on the local system. " + "These may be supported natively (e.g. armv7 on some aarch64 CPUs " + "or using hacks like qemu-user."}; + Setting<Strings> substituters{this, nixStore == "/nix/store" ? Strings{"https://cache.nixos.org/"} : Strings(), "substituters", diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index b63584f28a30..ef8c2811bd86 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -581,7 +581,8 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & uint64_t LocalStore::addValidPath(State & state, const ValidPathInfo & info, bool checkOutputs) { - assert(info.ca == "" || info.isContentAddressed(*this)); + if (info.ca != "" && !info.isContentAddressed(*this)) + throw Error("cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't", info.path); state.stmtRegisterValidPath.use() (info.path) diff --git a/src/libstore/references.cc b/src/libstore/references.cc index ba9f18b9ca5e..5b7eb1f846af 100644 --- a/src/libstore/references.cc +++ b/src/libstore/references.cc @@ -13,7 +13,7 @@ namespace nix { static unsigned int refLength = 32; /* characters */ -static void search(const unsigned char * s, unsigned int len, +static void search(const unsigned char * s, size_t len, StringSet & hashes, StringSet & seen) { static bool initialised = false; @@ -25,7 +25,7 @@ static void search(const unsigned char * s, unsigned int len, initialised = true; } - for (unsigned int i = 0; i + refLength <= len; ) { + for (size_t i = 0; i + refLength <= len; ) { int j; bool match = true; for (j = refLength - 1; j >= 0; --j) @@ -73,7 +73,7 @@ void RefScanSink::operator () (const unsigned char * data, size_t len) search(data, len, hashes, seen); - unsigned int tailLen = len <= refLength ? len : refLength; + size_t tailLen = len <= refLength ? len : refLength; tail = string(tail, tail.size() < refLength - tailLen ? 0 : tail.size() - (refLength - tailLen)) + string((const char *) data + len - tailLen, tailLen); diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc index 81cb5e98c763..e1782f8c4bd9 100644 --- a/src/libutil/compression.cc +++ b/src/libutil/compression.cc @@ -369,7 +369,20 @@ struct BzipSink : CompressionSink void write(const unsigned char * data, size_t len) override { + /* Bzip2's 'avail_in' parameter is an unsigned int, so we need + to split the input into chunks of at most 4 GiB. */ + while (len) { + auto n = std::min((size_t) std::numeric_limits<decltype(strm.avail_in)>::max(), len); + writeInternal(data, n); + data += n; + len -= n; + } + } + + void writeInternal(const unsigned char * data, size_t len) + { assert(!finished); + assert(len <= std::numeric_limits<decltype(strm.avail_in)>::max()); strm.next_in = (char *) data; strm.avail_in = len; @@ -475,8 +488,6 @@ struct BrotliSink : CompressionSink void write(const unsigned char * data, size_t len) override { - assert(!finished); - // Don't feed brotli too much at once const size_t CHUNK_SIZE = sizeof(outbuf) << 2; while (len) { @@ -486,7 +497,7 @@ struct BrotliSink : CompressionSink len -= n; } } - private: + void writeInternal(const unsigned char * data, size_t len) { assert(!finished); diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index a01d651e1ef5..9d82f13a5e38 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -82,7 +82,7 @@ static string printHash32(const Hash & hash) string s; s.reserve(len); - for (int n = len - 1; n >= 0; n--) { + for (int n = (int) len - 1; n >= 0; n--) { unsigned int b = n * 5; unsigned int i = b / 8; unsigned int j = b % 8; diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index d0b4552e3399..6e703c52a1e3 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -227,7 +227,7 @@ inline Sink & operator << (Sink & sink, uint64_t n) buf[4] = (n >> 32) & 0xff; buf[5] = (n >> 40) & 0xff; buf[6] = (n >> 48) & 0xff; - buf[7] = (n >> 56) & 0xff; + buf[7] = (unsigned char) (n >> 56) & 0xff; sink(buf, sizeof(buf)); return sink; } @@ -259,7 +259,7 @@ T readNum(Source & source) if (n > std::numeric_limits<T>::max()) throw SerialisationError("serialised integer %d is too large for type '%s'", n, typeid(T).name()); - return n; + return (T) n; } diff --git a/src/libutil/xml-writer.cc b/src/libutil/xml-writer.cc index 98bd058d18be..e5cc2e9fc719 100644 --- a/src/libutil/xml-writer.cc +++ b/src/libutil/xml-writer.cc @@ -28,7 +28,7 @@ void XMLWriter::close() } -void XMLWriter::indent_(unsigned int depth) +void XMLWriter::indent_(size_t depth) { if (!indent) return; output << string(depth * 2, ' '); @@ -75,7 +75,7 @@ void XMLWriter::writeAttrs(const XMLAttrs & attrs) { for (auto & i : attrs) { output << " " << i.first << "=\""; - for (unsigned int j = 0; j < i.second.size(); ++j) { + for (size_t j = 0; j < i.second.size(); ++j) { char c = i.second[j]; if (c == '"') output << """; else if (c == '<') output << "<"; diff --git a/src/libutil/xml-writer.hh b/src/libutil/xml-writer.hh index 3cefe3712c08..b98b445265a2 100644 --- a/src/libutil/xml-writer.hh +++ b/src/libutil/xml-writer.hh @@ -44,7 +44,7 @@ public: private: void writeAttrs(const XMLAttrs & attrs); - void indent_(unsigned int depth); + void indent_(size_t depth); }; diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index a63b3e07ae77..21d99878a518 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -354,7 +354,7 @@ void mainWrapped(int argc, char * * argv) // Build or fetch all dependencies of the derivation. for (const auto & input : drv.inputDrvs) if (std::all_of(envExclude.cbegin(), envExclude.cend(), [&](const string & exclude) { return !std::regex_search(input.first, std::regex(exclude)); })) - pathsToBuild.insert(input.first); + pathsToBuild.insert(makeDrvPathWithOutputs(input.first, input.second)); for (const auto & src : drv.inputSrcs) pathsToBuild.insert(src); diff --git a/src/nix-channel/local.mk b/src/nix-channel/local.mk index 49fc105c6f79..c14e8c359ca0 100644 --- a/src/nix-channel/local.mk +++ b/src/nix-channel/local.mk @@ -2,6 +2,6 @@ programs += nix-channel nix-channel_DIR := $(d) -nix-channel_LIBS = libmain libutil libformat libstore +nix-channel_LIBS = libmain libformat libstore libutil nix-channel_SOURCES := $(d)/nix-channel.cc diff --git a/src/nix-copy-closure/local.mk b/src/nix-copy-closure/local.mk index 42bb34dd8201..5018ab975b44 100644 --- a/src/nix-copy-closure/local.mk +++ b/src/nix-copy-closure/local.mk @@ -2,6 +2,6 @@ programs += nix-copy-closure nix-copy-closure_DIR := $(d) -nix-copy-closure_LIBS = libmain libutil libformat libstore +nix-copy-closure_LIBS = libmain libformat libstore libutil nix-copy-closure_SOURCES := $(d)/nix-copy-closure.cc diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 97e66cbd937e..f60ff9e07182 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -198,13 +198,13 @@ static Path getDefNixExprPath() } -static int getPriority(EvalState & state, DrvInfo & drv) +static long getPriority(EvalState & state, DrvInfo & drv) { return drv.queryMetaInt("priority", 0); } -static int comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2) +static long comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2) { return getPriority(state, drv2) - getPriority(state, drv1); } @@ -270,7 +270,7 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, for (auto & j : matches) { DrvName drvName(j.first.queryName()); - int d = 1; + long d = 1; Newest::iterator k = newest.find(drvName.name); @@ -578,7 +578,7 @@ static void upgradeDerivations(Globals & globals, (upgradeType == utEq && d == 0) || upgradeType == utAlways) { - int d2 = -1; + long d2 = -1; if (bestElem != availElems.end()) { d2 = comparePriorities(*globals.state, *bestElem, *j); if (d2 == 0) d2 = compareVersions(bestVersion, newName.version); @@ -784,22 +784,22 @@ typedef list<Strings> Table; void printTable(Table & table) { - unsigned int nrColumns = table.size() > 0 ? table.front().size() : 0; + auto nrColumns = table.size() > 0 ? table.front().size() : 0; - vector<unsigned int> widths; + vector<size_t> widths; widths.resize(nrColumns); for (auto & i : table) { assert(i.size() == nrColumns); Strings::iterator j; - unsigned int column; + size_t column; for (j = i.begin(), column = 0; j != i.end(); ++j, ++column) if (j->size() > widths[column]) widths[column] = j->size(); } for (auto & i : table) { Strings::iterator j; - unsigned int column; + size_t column; for (j = i.begin(), column = 0; j != i.end(); ++j, ++column) { string s = *j; replace(s.begin(), s.end(), '\n', ' '); diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index 51dedcf0a092..abdfa5e58f93 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -47,8 +47,7 @@ static string makeNode(const string & id, const string & label, static string symbolicName(const string & path) { string p = baseNameOf(path); - int dash = p.find('-'); - return string(p, dash + 1); + return string(p, p.find('-') + 1); } diff --git a/tests/lang/eval-okay-builtins-add.exp b/tests/lang/eval-okay-builtins-add.exp new file mode 100644 index 000000000000..0350b518a7ec --- /dev/null +++ b/tests/lang/eval-okay-builtins-add.exp @@ -0,0 +1 @@ +[ 5 4 "int" "tt" "float" 4 ] diff --git a/tests/lang/eval-okay-builtins-add.nix b/tests/lang/eval-okay-builtins-add.nix new file mode 100644 index 000000000000..c841816222a5 --- /dev/null +++ b/tests/lang/eval-okay-builtins-add.nix @@ -0,0 +1,8 @@ +[ +(builtins.add 2 3) +(builtins.add 2 2) +(builtins.typeOf (builtins.add 2 2)) +("t" + "t") +(builtins.typeOf (builtins.add 2.0 2)) +(builtins.add 2.0 2) +] diff --git a/tests/lang/eval-okay-getattrpos-undefined.exp b/tests/lang/eval-okay-getattrpos-undefined.exp new file mode 100644 index 000000000000..19765bd501b6 --- /dev/null +++ b/tests/lang/eval-okay-getattrpos-undefined.exp @@ -0,0 +1 @@ +null diff --git a/tests/lang/eval-okay-getattrpos-undefined.nix b/tests/lang/eval-okay-getattrpos-undefined.nix new file mode 100644 index 000000000000..14dd38f7734c --- /dev/null +++ b/tests/lang/eval-okay-getattrpos-undefined.nix @@ -0,0 +1 @@ +builtins.unsafeGetAttrPos "abort" builtins diff --git a/tests/lang/eval-okay-nested-with.exp b/tests/lang/eval-okay-nested-with.exp new file mode 100644 index 000000000000..0cfbf08886fc --- /dev/null +++ b/tests/lang/eval-okay-nested-with.exp @@ -0,0 +1 @@ +2 diff --git a/tests/lang/eval-okay-nested-with.nix b/tests/lang/eval-okay-nested-with.nix new file mode 100644 index 000000000000..ba9d79aa79b1 --- /dev/null +++ b/tests/lang/eval-okay-nested-with.nix @@ -0,0 +1,3 @@ +with { x = 1; }; +with { x = 2; }; +x |