From 8384a087afc7e29e900a3ce96d55ab2f5c2a74c2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 7 Oct 2024 08:17:49 +0200 Subject: Expose custom save function in config module It can generally be useful, for example, to complete relative paths before saving them to config.build (if abs_dir_path does not fit). --- libbuild2/config/init.cxx | 5 +++- libbuild2/config/module.cxx | 11 +++++--- libbuild2/config/module.hxx | 23 +++++++---------- libbuild2/config/operation.cxx | 2 +- libbuild2/config/utility.cxx | 16 +++++++++--- libbuild2/config/utility.hxx | 58 ++++++++++++++++++++++++++++++++---------- libbuild2/config/utility.ixx | 17 +++++++++---- 7 files changed, 90 insertions(+), 42 deletions(-) diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 2f134c4..b8ba31d 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -38,7 +38,10 @@ namespace build2 // the entire values. // static pair - save_environment (const value& d, const value* b, names& storage) + save_environment (const scope&, + const value& d, + const value* b, + names& storage) { if (b == nullptr) return make_pair (reverse (d, storage, true /* reduce */), "="); diff --git a/libbuild2/config/module.cxx b/libbuild2/config/module.cxx index 713d30c..faae865 100644 --- a/libbuild2/config/module.cxx +++ b/libbuild2/config/module.cxx @@ -14,7 +14,7 @@ namespace build2 bool module:: save_variable (const variable& var, optional flags, - save_variable_function* save) + save_variable_function* func) { const string& n (var.name); @@ -45,15 +45,18 @@ namespace build2 return false; } - sv.push_back (saved_variable {var, flags, save}); + sv.push_back (saved_variable {var, flags, func}); return true; } void module:: - save_variable (scope& rs, const variable& var, optional flags) + save_variable (scope& rs, + const variable& var, + optional flags, + save_variable_function* func) { if (module* m = rs.find_module (module::name)) - m->save_variable (var, flags); + m->save_variable (var, flags, func); } void module:: diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx index 8d3ff67..77109ce 100644 --- a/libbuild2/config/module.hxx +++ b/libbuild2/config/module.hxx @@ -22,20 +22,12 @@ namespace build2 namespace config { // An ordered list of build system modules each with an ordered list of - // config.* variables and their "save flags" (see save_variable()) that - // are used (as opposed to just being specified) in this configuration. - // Populated by the config utility functions (required(), optional()) and - // saved in the order populated. If flags are absent, then this variable - // was marked as "unsaved" (always transient). + // config.* variables and their save flags/function (see save_variable()) + // that are used (as opposed to just being specified) in this + // configuration. Populated by the config utility functions (required(), + // optional()) and saved in the order populated. If flags are absent, then + // this variable was marked as "unsaved" (always transient). // - // The optional save function can be used to implement custom variable - // saving, for example, as a difference appended to the base value. The - // second half of the result is the assignment operator to use. - // - using save_variable_function = - pair (const value&, - const value* base, - names& storage); struct saved_variable { reference_wrapper var; @@ -151,7 +143,10 @@ namespace build2 save_variable_function* = nullptr); static void - save_variable (scope&, const variable&, optional); + save_variable (scope&, + const variable&, + optional, + save_variable_function*); bool save_module (const char* name, int prio = 0); diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index b1716cf..6e7ef18 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -558,7 +558,7 @@ namespace build2 storage.clear (); pair p ( sv.save != nullptr - ? sv.save (v, base, storage) + ? sv.save (rs, v, base, storage) : make_pair (reverse (v, storage, true /* reduce */), "=")); // Might becomes empty after a custom save function had at it. diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx index 6574367..aa0d5af 100644 --- a/libbuild2/config/utility.cxx +++ b/libbuild2/config/utility.cxx @@ -7,7 +7,14 @@ using namespace std; namespace build2 { - void (*config_save_variable) (scope&, const variable&, optional); + void + (*config_save_variable) (scope&, + const variable&, + optional, + pair (*)(const scope&, + const value&, + const value*, + names&)); void (*config_save_environment) (scope&, const char*); void (*config_save_module) (scope&, const char*, int); const string& (*config_preprocess_create) (context&, @@ -21,7 +28,10 @@ namespace build2 namespace config { pair - lookup_config_impl (scope& rs, const variable& var, uint64_t sflags) + lookup_config_impl (scope& rs, + const variable& var, + uint64_t sflags, + save_variable_function* sfunc) { // This is a stripped-down version of the default value case. @@ -71,7 +81,7 @@ namespace build2 } if (l.defined ()) - save_variable (rs, var, sflags); + save_variable (rs, var, sflags, sfunc); return pair (l, n); } diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx index 1e2ff53..3b67c6c 100644 --- a/libbuild2/config/utility.hxx +++ b/libbuild2/config/utility.hxx @@ -29,13 +29,22 @@ namespace build2 // disfigure hooks (for example, for second-level configuration). These are // accessed through the config module entry points (which are NULL for // transient configurations). Note also that the exact interpretation of the - // save flags and module order depends on the config module implementation - // (which may ignore them as not applicable). An implementation may also - // define custom save flags (for example, accessible through the config.save - // attribute). Such flags should start from 0x100000000. + // save flags/function and module order depends on the config module + // implementation (which may ignore them as not applicable). An + // implementation may also define custom save flags (for example, accessible + // through the config.save attribute). Such flags should start from + // 0x100000000. + // + // See below for the save function (last argument) semantics. // LIBBUILD2_SYMEXPORT extern void - (*config_save_variable) (scope&, const variable&, optional); + (*config_save_variable) (scope&, + const variable&, + optional, + pair (*)(const scope&, + const value&, + const value*, + names&)); LIBBUILD2_SYMEXPORT extern void (*config_save_environment) (scope&, const char*); @@ -75,11 +84,27 @@ namespace build2 const uint64_t save_false_omitted = 0x08; // Treat false as undefined. const uint64_t save_base = 0x10; // Custom save with base. + // The optional save function can be used to implement custom variable + // saving, for example, as a difference appended to the base value or to + // complete relative paths (if abs_dir_path does not fit). The base + // argument is the value of this variable from the outer scope (if any) + // and is only calculated if the save_base flag is specified. The second + // half of the result is the assignment operator to use. + // + using save_variable_function = + pair (const scope& rs, + const value&, + const value* base, + names& storage); + inline void - save_variable (scope& rs, const variable& var, uint64_t flags = 0) + save_variable (scope& rs, + const variable& var, + uint64_t flags = 0, + save_variable_function* func = nullptr) { if (config_save_variable != nullptr) - config_save_variable (rs, var, flags); + config_save_variable (rs, var, flags, func); } // Mark a variable as "unsaved" (always transient). @@ -91,7 +116,7 @@ namespace build2 unsave_variable (scope& rs, const variable& var) { if (config_save_variable != nullptr) - config_save_variable (rs, var, nullopt); + config_save_variable (rs, var, nullopt, nullptr); } // Mark an environment variable to be saved during hermetic configuration. @@ -256,35 +281,40 @@ namespace build2 lookup lookup_config (scope& rs, const variable&, - uint64_t save_flags = 0); + uint64_t save_flags = 0, + save_variable_function* = nullptr); lookup lookup_config (bool& new_value, scope& rs, const variable&, - uint64_t save_flags = 0); + uint64_t save_flags = 0, + save_variable_function* = nullptr); // Note that the variable is expected to have already been entered. // inline lookup lookup_config (scope& rs, const string& var, - uint64_t save_flags = 0) + uint64_t save_flags = 0, + save_variable_function* func = nullptr) { // Note: go straight for the public variable pool. // - return lookup_config (rs, rs.ctx.var_pool[var], save_flags); + return lookup_config (rs, rs.ctx.var_pool[var], save_flags, func); } inline lookup lookup_config (bool& new_value, scope& rs, const string& var, - uint64_t save_flags = 0) + uint64_t save_flags = 0, + save_variable_function* func = nullptr) { // Note: go straight for the public variable pool. // - return lookup_config (new_value, rs, rs.ctx.var_pool[var], save_flags); + return lookup_config ( + new_value, rs, rs.ctx.var_pool[var], save_flags, func); } // Lookup a config.* variable value and, if the value is undefined, set it diff --git a/libbuild2/config/utility.ixx b/libbuild2/config/utility.ixx index d8348bd..87f628c 100644 --- a/libbuild2/config/utility.ixx +++ b/libbuild2/config/utility.ixx @@ -6,25 +6,32 @@ namespace build2 namespace config { LIBBUILD2_SYMEXPORT pair - lookup_config_impl (scope&, const variable&, uint64_t); + lookup_config_impl (scope&, + const variable&, + uint64_t, + save_variable_function*); template pair lookup_config_impl (scope&, const variable&, T&&, uint64_t, bool); inline lookup - lookup_config (scope& rs, const variable& var, uint64_t sflags) + lookup_config (scope& rs, + const variable& var, + uint64_t sflags, + save_variable_function* func) { - return lookup_config_impl (rs, var, sflags).first; + return lookup_config_impl (rs, var, sflags, func).first; } inline lookup lookup_config (bool& new_value, scope& rs, const variable& var, - uint64_t sflags) + uint64_t sflags, + save_variable_function* func) { - auto r (lookup_config_impl (rs, var, sflags)); + auto r (lookup_config_impl (rs, var, sflags, func)); new_value = new_value || r.second; return r.first; } -- cgit v1.1