From cae260a15874dab1dfa505a1f11ae98be2f03afd Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 25 Aug 2024 13:41:56 +0200 Subject: [PATCH] libstore: diagnose local build failure in goal this should be done where we're actually trying to build something, not in the main worker loop that shouldn't have to be aware of such details Change-Id: I07276740c0e2e5591a8ce4828a4bfc705396527e --- src/libstore/build/local-derivation-goal.cc | 17 +++++++++++++++- src/libstore/build/worker.cc | 13 ------------ tests/functional/build-jobless.sh | 22 +++++++++++++++++++++ tests/functional/meson.build | 1 + 4 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 tests/functional/build-jobless.sh diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 1e3c4109d..8587ad662 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -1,6 +1,7 @@ #include "local-derivation-goal.hh" #include "indirect-root-store.hh" #include "hook-instance.hh" +#include "machines.hh" #include "store-api.hh" #include "worker.hh" #include "builtins.hh" @@ -159,7 +160,21 @@ Goal::WorkResult LocalDerivationGoal::tryLocalBuild(bool inBuildSlot) if (!inBuildSlot) { state = &DerivationGoal::tryToBuild; outputLocks.unlock(); - return WaitForSlot{}; + if (0U != settings.maxBuildJobs) { + return WaitForSlot{}; + } + if (getMachines().empty()) { + throw Error( + "unable to start any build; either set '--max-jobs' to a non-zero value or enable " + "remote builds.\n" + "https://docs.lix.systems/manual/lix/stable/advanced-topics/distributed-builds.html" + ); + } else { + throw Error( + "unable to start any build; remote machines may not have all required system features.\n" + "https://docs.lix.systems/manual/lix/stable/advanced-topics/distributed-builds.html" + ); + } } assert(derivationType); diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index 9740cdd4d..4a70b272a 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -1,5 +1,4 @@ #include "charptr-cast.hh" -#include "machines.hh" #include "worker.hh" #include "substitution-goal.hh" #include "drv-output-substitution-goal.hh" @@ -381,18 +380,6 @@ void Worker::run(const Goals & _topGoals) if (!children.empty() || !waitingForAWhile.empty()) waitForInput(); else { - if (awake.empty() && 0U == settings.maxBuildJobs) - { - if (getMachines().empty()) - throw Error("unable to start any build; either increase '--max-jobs' " - "or enable remote builds." - "\nhttps://docs.lix.systems/manual/lix/stable/advanced-topics/distributed-builds.html"); - else - throw Error("unable to start any build; remote machines may not have " - "all required system features." - "\nhttps://docs.lix.systems/manual/lix/stable/advanced-topics/distributed-builds.html"); - - } assert(!awake.empty()); } } diff --git a/tests/functional/build-jobless.sh b/tests/functional/build-jobless.sh new file mode 100644 index 000000000..9bf850009 --- /dev/null +++ b/tests/functional/build-jobless.sh @@ -0,0 +1,22 @@ +source common.sh + +drv=' +builtins.derivation { + name = "foo"; + builder = /bin/sh; + system = builtins.currentSystem; + requiredSystemFeatures = [ "glitter" ]; +} +' + +# -j0 without remote machines diagnoses build start failure +! out="$(nix-build 2>&1 -j0 --expr "$drv" \ + --builders '' \ + --system-features 'glitter')" +<<<"$out" grepQuiet 'error: unable to start any build; either set '\''--max-jobs'\'' to a non-zero value or enable remote builds.' + +# -j0 with remote machines and missing features also diagnoses +! out="$(nix-build 2>&1 -j0 --expr "$drv" \ + --builders "ssh://localhost?remote-store=$TEST_ROOT/machine1" \ + --system-features 'glitter')" +<<<"$out" grepQuiet 'error: unable to start any build; remote machines may not have all required system features.' diff --git a/tests/functional/meson.build b/tests/functional/meson.build index fb8d77a57..5d4ce3f4b 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -130,6 +130,7 @@ functional_tests_scripts = [ 'build-remote-trustless-should-pass-2.sh', 'build-remote-trustless-should-pass-3.sh', 'build-remote-trustless-should-fail-0.sh', + 'build-jobless.sh', 'nar-access.sh', 'impure-eval.sh', 'pure-eval.sh',