From 409c004cba8e07246d99352fe300f38795daf84b Mon Sep 17 00:00:00 2001 From: Morgan Jones Date: Sun, 4 Jan 2026 22:05:00 -0800 Subject: [PATCH] libexpr-c: fix changing eval settings having no effect Using the Rust bindings (which call into the C bindings) to set eval-related settings was not working. Since EvalSettings were defined in libcmd, we need to move them to libexpr if libexpr-c wants to use them. Since libcmd enforces a dependency on libflake, we also need to modify config-global to absorb duplicate registrations and support callbacks for customizing behavior that we only need in libcmd. Note that we add back some of the global setting variables with this, but this does fix the C API. --- src/libcmd/common-eval-args.cc | 11 ++++------- src/libexpr-c/nix_api_expr.cc | 17 +++++++++-------- src/libexpr-c/nix_api_expr_internal.h | 8 ++++---- src/libexpr/eval-settings.cc | 5 +++++ src/libexpr/include/nix/expr/eval-settings.hh | 5 +++++ src/libflake-c/nix_api_flake.cc | 2 +- src/libutil/config-global.cc | 11 ++++++++++- src/libutil/include/nix/util/config-global.hh | 1 + 8 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index 865901febf4..c457a49f50b 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -19,9 +19,8 @@ namespace nix { -EvalSettings evalSettings{ - settings.readOnlyMode, - { +static GlobalConfig::Register rEvalSettings(&evalSettings, [] { + evalSettings.lookupPathHooks = { { "flake", [](EvalState & state, std::string_view rest) { @@ -40,10 +39,8 @@ EvalSettings evalSettings{ return state.storePath(storePath); }, }, - }, -}; - -static GlobalConfig::Register rEvalSettings(&evalSettings); + }; +}); flake::Settings flakeSettings; diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index bfbd0a9c361..8acdecf49a9 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -6,6 +6,7 @@ #include "nix/expr/eval-gc.hh" #include "nix/store/globals.hh" #include "nix/expr/eval-settings.hh" +#include "nix/fetchers/fetch-settings.hh" #include "nix/util/ref.hh" #include "nix_api_expr.h" @@ -137,8 +138,8 @@ nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Sto return unsafe_new_with_self([&](auto * self) { return nix_eval_state_builder{ .store = nix::ref(store->ptr), - .settings = nix::EvalSettings{/* &bool */ self->readOnlyMode}, - .fetchSettings = nix::fetchers::Settings{}, + .settings = &nix::evalSettings, + .fetchSettings = &nix::fetchSettings, .readOnlyMode = true, }; }); @@ -159,9 +160,9 @@ nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_buil context->last_err_code = NIX_OK; try { // TODO: load in one go? - builder->settings.readOnlyMode = nix::settings.readOnlyMode; - loadConfFile(builder->settings); - loadConfFile(builder->fetchSettings); + builder->settings->readOnlyMode = nix::settings.readOnlyMode; + loadConfFile(*builder->settings); + loadConfFile(*builder->fetchSettings); } NIXC_CATCH_ERRS } @@ -188,9 +189,9 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder try { return unsafe_new_with_self([&](auto * self) { return EvalState{ - .fetchSettings = std::move(builder->fetchSettings), - .settings = std::move(builder->settings), - .state = nix::EvalState(builder->lookupPath, builder->store, self->fetchSettings, self->settings), + .fetchSettings = builder->fetchSettings, + .settings = builder->settings, + .state = nix::EvalState(builder->lookupPath, builder->store, *self->fetchSettings, *self->settings), }; }); } diff --git a/src/libexpr-c/nix_api_expr_internal.h b/src/libexpr-c/nix_api_expr_internal.h index 07c7a2194df..150c4b93159 100644 --- a/src/libexpr-c/nix_api_expr_internal.h +++ b/src/libexpr-c/nix_api_expr_internal.h @@ -13,8 +13,8 @@ extern "C" { struct nix_eval_state_builder { nix::ref store; - nix::EvalSettings settings; - nix::fetchers::Settings fetchSettings; + nix::EvalSettings * settings; + nix::fetchers::Settings * fetchSettings; nix::LookupPath lookupPath; // TODO: make an EvalSettings setting own this instead? bool readOnlyMode; @@ -22,8 +22,8 @@ struct nix_eval_state_builder struct EvalState { - nix::fetchers::Settings fetchSettings; - nix::EvalSettings settings; + nix::fetchers::Settings * fetchSettings; + nix::EvalSettings * settings; nix::EvalState state; }; diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc index 27205864b8b..e38268e5f5d 100644 --- a/src/libexpr/eval-settings.cc +++ b/src/libexpr/eval-settings.cc @@ -1,4 +1,5 @@ #include "nix/util/users.hh" +#include "nix/util/config-global.hh" #include "nix/store/globals.hh" #include "nix/store/profiles.hh" #include "nix/expr/eval.hh" @@ -118,4 +119,8 @@ std::filesystem::path getNixDefExpr() return settings.useXDGBaseDirectories ? getStateDir() / "defexpr" : getHome() / ".nix-defexpr"; } +EvalSettings evalSettings{settings.readOnlyMode}; + +static GlobalConfig::Register rEvalSettings(&evalSettings); + } // namespace nix diff --git a/src/libexpr/include/nix/expr/eval-settings.hh b/src/libexpr/include/nix/expr/eval-settings.hh index f367541ec2f..50c7b7d6085 100644 --- a/src/libexpr/include/nix/expr/eval-settings.hh +++ b/src/libexpr/include/nix/expr/eval-settings.hh @@ -412,4 +412,9 @@ std::filesystem::path getNixDefExpr(); */ constexpr size_t evalStackSize = 60 * 1024 * 1024; +/** + * EvalSettings instance from libexpr. + */ +extern EvalSettings evalSettings; + } // namespace nix diff --git a/src/libflake-c/nix_api_flake.cc b/src/libflake-c/nix_api_flake.cc index 793db44b438..ba7b6bd7f15 100644 --- a/src/libflake-c/nix_api_flake.cc +++ b/src/libflake-c/nix_api_flake.cc @@ -32,7 +32,7 @@ nix_err nix_flake_settings_add_to_eval_state_builder( { nix_clear_err(context); try { - settings->settings->configureEvalSettings(builder->settings); + settings->settings->configureEvalSettings(*builder->settings); } NIXC_CATCH_ERRS } diff --git a/src/libutil/config-global.cc b/src/libutil/config-global.cc index b63b4aaa1bb..2dd81f5c203 100644 --- a/src/libutil/config-global.cc +++ b/src/libutil/config-global.cc @@ -61,7 +61,16 @@ GlobalConfig globalConfig; GlobalConfig::Register::Register(Config * config) { - configRegistrations().emplace_back(config); + auto regs = configRegistrations(); + if (std::find(regs.begin(), regs.end(), config) == regs.end()) { + configRegistrations().emplace_back(config); + } +} + +GlobalConfig::Register::Register(Config * config, std::function && callback) + : Register(config) +{ + callback(); } ExperimentalFeatureSettings experimentalFeatureSettings; diff --git a/src/libutil/include/nix/util/config-global.hh b/src/libutil/include/nix/util/config-global.hh index 5074351e046..de6923c1de7 100644 --- a/src/libutil/include/nix/util/config-global.hh +++ b/src/libutil/include/nix/util/config-global.hh @@ -26,6 +26,7 @@ struct GlobalConfig : public AbstractConfig struct Register { Register(Config * config); + Register(Config * config, std::function && callback); }; };