aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/context.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/context.hxx')
-rw-r--r--libbuild2/context.hxx94
1 files changed, 70 insertions, 24 deletions
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index 828c41e..81ac970 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -178,34 +178,35 @@ namespace build2
// match - search prerequisites and match rules
// execute - execute the matched rule
//
- // The build system starts with a "serial load" phase and then continues
- // with parallel match and execute. Match, however, can be interrupted
- // both with load and execute.
+ // The build system starts with a serial "initial load" phase and then
+ // continues with parallel match and execute. Match, however, can be
+ // interrupted both with load and execute.
//
- // Match can be interrupted with "exclusive load" in order to load
- // additional buildfiles. Similarly, it can be interrupted with (parallel)
- // execute in order to build targetd required to complete the match (for
- // example, generated source code or source code generators themselves).
+ // Match can be interrupted with a (serial) "interrupting load" in order
+ // to load additional buildfiles. Similarly, it can be interrupted with
+ // (parallel) execute in order to build targetd required to complete the
+ // match (for example, generated source code or source code generators
+ // themselves).
//
// Such interruptions are performed by phase change that is protected by
// phase_mutex (which is also used to synchronize the state changes
// between phases).
//
- // Serial load can perform arbitrary changes to the build state. Exclusive
- // load, however, can only perform "island appends". That is, it can
- // create new "nodes" (variables, scopes, etc) but not (semantically)
- // change already existing nodes or invalidate any references to such (the
- // idea here is that one should be able to load additional buildfiles as
- // long as they don't interfere with the existing build state). The
- // "islands" are identified by the load_generation number (1 for the
- // initial/serial load). It is incremented in case of a phase switch and
- // can be stored in various "nodes" to verify modifications are only done
- // "within the islands". Another example of invalidation would be
- // insertion of a new scope "under" an existing target thus changing its
- // scope hierarchy (and potentially even its base scope). This would be
- // bad because we may have made decisions based on the original hierarchy,
- // for example, we may have queried a variable which in the new hierarchy
- // would "see" a new value from the newly inserted scope.
+ // Initial load can perform arbitrary changes to the build state.
+ // Interrupting load, however, can only perform what we call "island
+ // appends". That is, it can create new "nodes" (variables, scopes, etc)
+ // but not (semantically) change already existing nodes or invalidate any
+ // references to such (the idea here is that one should be able to load
+ // additional buildfiles as long as they don't interfere with the existing
+ // build state). The "islands" are identified by the load_generation
+ // number (1 for the initial load). It is incremented in case of a phase
+ // switch and can be stored in various "nodes" to verify modifications are
+ // only done "within the islands". Another example of invalidation would
+ // be insertion of a new scope "under" an existing target thus changing
+ // its scope hierarchy (and potentially even its base scope). This would
+ // be bad because we may have made decisions based on the original
+ // hierarchy, for example, we may have queried a variable which in the new
+ // hierarchy would "see" a new value from the newly inserted scope.
//
// The special load_generation value 0 indicates initialization before
// anything has been loaded. Currently, it is changed to 1 at the end
@@ -351,10 +352,52 @@ namespace build2
(current_mname.empty () && current_oname == mo));
};
+ // Operation callbacks.
+ //
+ // An entity (module, core) can register a function that will be called
+ // when an action is executed on a set of targets. The pre callback is
+ // called before any recipes for the action are matched and the post --
+ // after all have been executed. The post callback is called even if
+ // execution has failed.
+ //
+ // The callback should only be registered during the load phase. Note
+ // that it's registered for the inner action, meaning that it will be
+ // called for any outer action (which is discernible from the first
+ // argument of the callback). Note also that meta-operations other than
+ // perform never actually execute any recipes and it probably only makes
+ // sense to register these callbacks for the perform_* actions.
+ //
+ // Note that the callbacks will also be called when building a build
+ // system module or an ad hoc C++ recipe. See create_module_context() for
+ // details.
+ //
+ // Note also that if the callbacks are registered from a module load
+ // function, then there are nuances with interrupted load phases. See the
+ // compilation database handling in the cc module for details.
+ //
+ // See also scope::operation_callback.
+ //
+ struct operation_callback
+ {
+ using pre_callback =
+ void (context&, action, const action_targets&);
+
+ using post_callback =
+ void (context&, action, const action_targets&, bool failed);
+
+ function<pre_callback> pre;
+ function<post_callback> post;
+ };
+
+ using operation_callback_map = multimap<action_id, operation_callback>;
+
+ operation_callback_map operation_callbacks;
+
// Meta/operation-specific context-global auxiliary data storage.
//
- // Note: cleared by current_[meta_]operation() below. Normally set by
- // meta/operation-specific callbacks from [mate_]operation_info.
+ // Normally set by meta/operation-specific callbacks from
+ // [mata_]operation_info. The operation data is cleared by
+ // current_operation() below.
//
// Note also: watch out for MT-safety in the data itself.
//
@@ -759,6 +802,9 @@ namespace build2
// Set current meta-operation and operation.
//
+ // Note that the context instance is not to be re-used between different
+ // meta-operations.
+ //
void
current_meta_operation (const meta_operation_info&);