diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index 08ffe7750..b261ee027 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -1,4 +1,5 @@ #include "lix/libstore/build/derivation-goal.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/file-system.hh" #include "lix/libstore/build/hook-instance.hh" #include "lix/libstore/build/worker.hh" @@ -176,7 +177,7 @@ try { co_return co_await loadDerivation(); } - (co_await waitForGoals(worker.goalFactory().makePathSubstitutionGoal(drvPath))).value(); + TRY_AWAIT(waitForGoals(worker.goalFactory().makePathSubstitutionGoal(drvPath))); co_return co_await loadDerivation(); } catch (...) { co_return result::current_exception(); @@ -302,7 +303,7 @@ try { } if (!dependencies.empty()) { /* to prevent hang (no wake-up event) */ - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await outputsSubstitutionTried(); } catch (...) { @@ -447,7 +448,7 @@ try { } if (!dependencies.empty()) {/* to prevent hang (no wake-up event) */ - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await inputsRealised(); } catch (...) { @@ -513,7 +514,7 @@ try { co_return done(BuildResult::AlreadyValid, assertPathValidity()); } - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); co_return co_await closureRepaired(); } catch (...) { co_return result::current_exception(); @@ -618,7 +619,7 @@ try { pathResolved, wantedOutputs, buildMode); resolvedDrvGoal = dependency.first; - (co_await waitForGoals(std::move(dependency))).value(); + TRY_AWAIT(waitForGoals(std::move(dependency))); co_return co_await resolvedFinished(); } diff --git a/lix/libstore/build/drv-output-substitution-goal.cc b/lix/libstore/build/drv-output-substitution-goal.cc index 9d33e9b31..ace2f5161 100644 --- a/lix/libstore/build/drv-output-substitution-goal.cc +++ b/lix/libstore/build/drv-output-substitution-goal.cc @@ -1,5 +1,6 @@ #include "lix/libstore/build/drv-output-substitution-goal.hh" #include "lix/libstore/build-result.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/finally.hh" #include "lix/libstore/build/worker.hh" #include "lix/libstore/build/substitution-goal.hh" @@ -126,7 +127,7 @@ try { dependencies.add(worker.goalFactory().makePathSubstitutionGoal(outputInfo->outPath)); if (!dependencies.empty()) { - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await outPathValid(); } catch (...) { diff --git a/lix/libstore/build/substitution-goal.cc b/lix/libstore/build/substitution-goal.cc index 50ee7ff7f..2501495f9 100644 --- a/lix/libstore/build/substitution-goal.cc +++ b/lix/libstore/build/substitution-goal.cc @@ -1,6 +1,7 @@ #include "lix/libstore/build/worker.hh" #include "lix/libstore/build/substitution-goal.hh" #include "lix/libstore/nar-info.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/signals.hh" #include "lix/libutil/finally.hh" #include @@ -166,7 +167,7 @@ try { dependencies.add(worker.goalFactory().makePathSubstitutionGoal(i)); if (!dependencies.empty()) {/* to prevent hang (no wake-up event) */ - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await referencesValid(); } catch (...) { diff --git a/lix/libutil/async.hh b/lix/libutil/async.hh new file mode 100644 index 000000000..72dd644fe --- /dev/null +++ b/lix/libutil/async.hh @@ -0,0 +1,28 @@ +#pragma once +///@file + +#include "lix/libutil/result.hh" + +namespace nix { +namespace detail { +inline void materializeResult(Result r) +{ + r.value(); +} + +template +inline T materializeResult(Result r) +{ + return std::move(r.value()); +} +} +} + +// force materialization of the value. result::value() returns only an rvalue reference +// and is thus unsuitable for use in e.g. range for without materialization. ideally we +// would wrap the expression in `auto()`, but apple clang fails when given `auto(void)` +#define LIX_TRY_AWAIT(...) (::nix::detail::materializeResult(co_await (__VA_ARGS__))) + +#if LIX_UR_COMPILER_UWU +# define TRY_AWAIT LIX_TRY_AWAIT +#endif diff --git a/lix/libutil/meson.build b/lix/libutil/meson.build index 1f8904b3b..4a04698cb 100644 --- a/lix/libutil/meson.build +++ b/lix/libutil/meson.build @@ -55,6 +55,7 @@ libutil_headers = files( 'args/root.hh', 'args.hh', 'async-collect.hh', + 'async.hh', 'async-semaphore.hh', 'backed-string-view.hh', 'box_ptr.hh', diff --git a/meson.build b/meson.build index dab2e063f..88130c9ca 100644 --- a/meson.build +++ b/meson.build @@ -138,6 +138,15 @@ endif cxx = meson.get_compiler('cpp') +# tag define to tell us we are compiling lix itself and can thus make +# non-namespaced aliases of a utility defines visible. this spares us +# writing LIX_TRY_AWAIT, LIX_RUN_ASYNC_IN, and others in our own code +# without being forced to hide the headers we take these defines from +add_project_arguments( + '-DLIX_UR_COMPILER_UWU', + language : 'cpp', +) + # clangd breaks when GCC is using precompiled headers lmao # https://git.lix.systems/lix-project/lix/issues/374