diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 300f6ac00..84fbf1c18 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1272,6 +1272,8 @@ void DerivationGoal::inputsRealised() build hook. */ state = &DerivationGoal::tryToBuild; worker.wakeUp(shared_from_this()); + + result = BuildResult(); } @@ -1421,6 +1423,8 @@ void DerivationGoal::buildDone() debug(format("builder process for ‘%1%’ finished") % drvPath); + result.timesBuilt++; + /* So the child is gone now. */ worker.childTerminated(this); @@ -2909,17 +2913,15 @@ void DerivationGoal::registerOutputs() assert(prevInfos.size() == infos.size()); for (auto i = prevInfos.begin(), j = infos.begin(); i != prevInfos.end(); ++i, ++j) if (!(*i == *j)) { + result.isNonDeterministic = true; Path prev = i->path + checkSuffix; - if (pathExists(prev)) - throw NotDeterministic( - format("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round") - % i->path % drvPath % prev); - else - throw NotDeterministic( - format("output ‘%1%’ of ‘%2%’ differs from previous round") - % i->path % drvPath); + auto msg = pathExists(prev) + ? fmt("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round", i->path, drvPath, prev) + : fmt("output ‘%1%’ of ‘%2%’ differs from previous round", i->path, drvPath); + if (settings.get("enforce-determinism", true)) + throw NotDeterministic(msg); + printError(msg); } - abort(); // shouldn't happen } if (settings.keepFailed) { @@ -2932,7 +2934,6 @@ void DerivationGoal::registerOutputs() throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst); } } - } if (curRound < nrRounds) { @@ -3792,12 +3793,13 @@ void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode) worker.run(goals); PathSet failed; - for (auto & i : goals) + for (auto & i : goals) { if (i->getExitCode() != Goal::ecSuccess) { DerivationGoal * i2 = dynamic_cast(i.get()); if (i2) failed.insert(i2->getDrvPath()); else failed.insert(dynamic_cast(i.get())->getStorePath()); } + } if (!failed.empty()) throw Error(worker.exitStatus(), "build of %s failed", showPaths(failed)); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 2ea74d90e..ee2b6b286 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -208,7 +208,18 @@ struct BuildResult NotDeterministic, } status = MiscFailure; std::string errorMsg; + + /* How many times this build was performed. */ + unsigned int timesBuilt = 0; + + /* If timesBuilt > 1, whether some builds did not produce the same + result. (Note that 'isNonDeterministic = false' does not mean + the build is deterministic, just that we don't have evidence of + non-determinism.) */ + bool isNonDeterministic = false; + //time_t startTime = 0, stopTime = 0; + bool success() { return status == Built || status == Substituted || status == AlreadyValid; }