diff options
Diffstat (limited to 'libbuild2/context.hxx')
-rw-r--r-- | libbuild2/context.hxx | 94 |
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&); |