aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/config/init.cxx45
-rw-r--r--libbuild2/config/module.cxx24
-rw-r--r--libbuild2/config/module.hxx13
-rw-r--r--libbuild2/config/operation.cxx16
-rw-r--r--libbuild2/config/utility.cxx3
-rw-r--r--libbuild2/config/utility.hxx47
-rw-r--r--libbuild2/context.hxx10
7 files changed, 131 insertions, 27 deletions
diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx
index df71fae..1513a47 100644
--- a/libbuild2/config/init.cxx
+++ b/libbuild2/config/init.cxx
@@ -96,35 +96,38 @@ namespace build2
auto& c_p (vp.insert<vector<pair<string, string>>> (
"config.config.persist", true /* ovr */, v_p));
- // Only create the module if we are configuring or creating or if it was
- // requested with config.config.module (useful if we need to call
- // $config.save() during other meta-operations).
+ // Only create the module if we are configuring, creating, or
+ // disfiguring or if it was requested with config.config.module (useful
+ // if we need to call $config.save() during other meta-operations).
//
- // Detecting the former (configuring/creating) is a bit tricky since the
- // build2 core may not yet know if this is the case. But we know.
+ // Detecting the former (configure/disfigure/creating) is a bit tricky
+ // since the build2 core may not yet know if this is the case. But we
+ // know.
//
auto& c_m (vp.insert<bool> ("config.config.module", false /*ovr*/, v_p));
- const string& mname (ctx.current_mname);
- const string& oname (ctx.current_oname);
-
- if (( mname == "configure" || mname == "create") ||
- (mname.empty () && (oname == "configure" || oname == "create")) ||
+ bool d;
+ if ((d = ctx.bootstrap_meta_operation ("disfigure")) ||
+ ctx.bootstrap_meta_operation ("configure") ||
+ ctx.bootstrap_meta_operation ("create") ||
cast_false<bool> (rs.vars[c_m]))
{
- // Used as a variable prefix by configure_execute().
- //
- vp.insert ("config");
-
auto& m (extra.set_module (new module));
- // Adjust priority for the config module and import pseudo-module so
- // that their variables come first in config.build.
- //
- m.save_module ("config", INT32_MIN);
- m.save_module ("import", INT32_MIN);
+ if (!d)
+ {
+ // Used as a variable prefix by configure_execute().
+ //
+ vp.insert ("config");
+
+ // Adjust priority for the config module and import pseudo-module so
+ // that their variables come first in config.build.
+ //
+ m.save_module ("config", INT32_MIN);
+ m.save_module ("import", INT32_MIN);
- m.save_variable (c_p, save_null_omitted);
+ m.save_variable (c_p, save_null_omitted);
+ }
}
// Register the config function family if this is the first instance of
@@ -319,6 +322,8 @@ namespace build2
config_save_variable = &module::save_variable;
config_save_module = &module::save_module;
config_preprocess_create = &preprocess_create;
+ config_configure_post = &module::configure_post;
+ config_disfigure_pre = &module::disfigure_pre;
return mod_functions;
}
diff --git a/libbuild2/config/module.cxx b/libbuild2/config/module.cxx
index 96107cc..6b0c82a 100644
--- a/libbuild2/config/module.cxx
+++ b/libbuild2/config/module.cxx
@@ -67,6 +67,30 @@ namespace build2
m->save_module (name, prio);
}
+ bool module::
+ configure_post (scope& rs, configure_post_hook* h)
+ {
+ if (module* m = rs.find_module<module> (module::name))
+ {
+ m->configure_post_.push_back (h);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool module::
+ disfigure_pre (scope& rs, disfigure_pre_hook* h)
+ {
+ if (module* m = rs.find_module<module> (module::name))
+ {
+ m->disfigure_pre_.push_back (h);
+ return true;
+ }
+
+ return false;
+ }
+
const string module::name ("config");
const uint64_t module::version (1);
}
diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx
index 5cb4faa..96220ac 100644
--- a/libbuild2/config/module.hxx
+++ b/libbuild2/config/module.hxx
@@ -15,6 +15,8 @@
#include <libbuild2/module.hxx>
#include <libbuild2/variable.hxx>
+#include <libbuild2/config/utility.hxx>
+
namespace build2
{
namespace config
@@ -94,6 +96,17 @@ namespace build2
i->second.find (var) != i->second.end ();
}
+ // Configure/disfigure hooks.
+ //
+ static bool
+ configure_post (scope&, configure_post_hook*);
+
+ static bool
+ disfigure_pre (scope&, disfigure_pre_hook*);
+
+ small_vector<configure_post_hook*, 1> configure_post_;
+ small_vector<disfigure_pre_hook*, 1> disfigure_pre_;
+
// Cached (during init) config.config.persist value, if defined.
//
const vector<pair<string, string>>* persist = nullptr;
diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx
index c606d09..b07df42 100644
--- a/libbuild2/config/operation.cxx
+++ b/libbuild2/config/operation.cxx
@@ -590,6 +590,15 @@ namespace build2
fail << "operation-specific configuration not yet supported";
}
+ if (c_s == nullptr)
+ {
+ if (module* m = rs.find_module<module> (module::name))
+ {
+ for (auto hook: m->configure_post_)
+ hook (a, rs);
+ }
+ }
+
// Configure subprojects that have been loaded.
//
if (const subprojects* ps = *rs.root_extra->subprojects)
@@ -892,6 +901,12 @@ namespace build2
}
}
+ if (module* m = rs.find_module<module> (module::name))
+ {
+ for (auto hook: m->disfigure_pre_)
+ r = hook (a, rs) || r;
+ }
+
// We distinguish between a complete disfigure and operation-
// specific.
//
@@ -937,6 +952,7 @@ namespace build2
}
else
{
+ fail << "operation-specific disfiguration not yet supported";
}
return r;
diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx
index b3f94be..b10c980 100644
--- a/libbuild2/config/utility.cxx
+++ b/libbuild2/config/utility.cxx
@@ -14,6 +14,9 @@ namespace build2
vector_view<opspec>&,
bool,
const location&);
+ bool (*config_configure_post) (scope&, bool (*)(action, const scope&));
+ bool (*config_disfigure_pre) (scope&, bool (*)(action, const scope&));
+
namespace config
{
pair<lookup, bool>
diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx
index fb3023b..209ef5c 100644
--- a/libbuild2/config/utility.hxx
+++ b/libbuild2/config/utility.hxx
@@ -22,13 +22,14 @@ namespace build2
//
// The only persistence-specific aspects of this functionality are marking
// of the variables as to be persisted (saved, potentially with flags),
- // establishing the module saving order (priority), and configuration
- // creation (the create meta-operation implementation) 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
+ // establishing the module saving order (priority), configuration creation
+ // (the create meta-operation implementation), as well as configure and
+ // 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.
//
LIBBUILD2_SYMEXPORT extern void
@@ -44,6 +45,12 @@ namespace build2
bool,
const location&);
+ LIBBUILD2_SYMEXPORT extern bool
+ (*config_configure_post) (scope&, bool (*)(action, const scope&));
+
+ LIBBUILD2_SYMEXPORT extern bool
+ (*config_disfigure_pre) (scope&, bool (*)(action, const scope&));
+
namespace config
{
// Mark the variable to be saved during configuration.
@@ -77,6 +84,32 @@ namespace build2
config_save_module (rs, module, prio);
}
+ // Post-configure and pre-disfigure hooks. Normally used to save/remove
+ // persistent state. Return true if anything has been done (used for
+ // diagnostics).
+ //
+ // The registration functions return true if the hook has been registered.
+ //
+ // Note that the hooks are called for the top-level project and all its
+ // subprojects (if registered in the subproject root scope), from outer to
+ // inner for configure and from inner to outer for disfigure. It's the
+ // responsibility of the hook implementation to handle any aggregation.
+ //
+ using configure_post_hook = bool (action, const scope&);
+ using disfigure_pre_hook = bool (action, const scope&);
+
+ inline bool
+ configure_post (scope& rs, configure_post_hook* h)
+ {
+ return config_configure_post != nullptr && config_configure_post (rs, h);
+ }
+
+ inline bool
+ disfigure_pre (scope& rs, disfigure_pre_hook* h)
+ {
+ return config_disfigure_pre != nullptr && config_disfigure_pre (rs, h);
+ }
+
// Lookup a config.* variable value and, if the value is defined, mark it
// as saved.
//
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index a8b6b01..c4e1259 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -265,6 +265,16 @@ namespace build2
const operation_info* current_inner_oif;
const operation_info* current_outer_oif;
+ // Check whether this is the specified meta-operation during bootstrap
+ // (when current_mif may not be yet known).
+ //
+ bool
+ bootstrap_meta_operation (const char* mo)
+ {
+ return ((current_mname == mo ) ||
+ (current_mname.empty () && current_oname == mo));
+ };
+
// Current operation number (1-based) in the meta-operation batch.
//
size_t current_on;