aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-05-15 12:12:20 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 08:35:29 +0200
commit66834a2d66bdcd36013afd7c3325acd9acf4a0b6 (patch)
treee0329bcfbd24bcb6fd56f0ad94597c0050d49496
parentcf1670f9a6541e42f22d58e2de5940e64cb6637e (diff)
Support for the nested build case
-rw-r--r--libbuild2/context.hxx9
-rw-r--r--libbuild2/module.cxx2
-rw-r--r--libbuild2/rule.cxx79
3 files changed, 56 insertions, 34 deletions
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index 8e68784..2a9c93e 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -428,7 +428,7 @@ namespace build2
//
const loaded_modules_lock* modules_lock;
- // Nested context for updating build system modules.
+ // Nested context for updating build system modules and ad hoc recipes.
//
// Note that such a context itself should normally have modules_context
// setup to point to itself (see import_module() for details).
@@ -438,9 +438,10 @@ namespace build2
public:
// If module_context is absent, then automatic updating of build system
- // modules is disabled. If it is NULL, then the context will be created
- // lazily if and when necessary. Otherwise, it should be a properly setup
- // context (including, normally, a self-reference in modules_context).
+ // modules and ad hoc recipes is disabled. If it is NULL, then the context
+ // will be created lazily if and when necessary. Otherwise, it should be a
+ // properly setup context (including, normally, a self-reference in
+ // modules_context).
//
explicit
context (scheduler&,
diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx
index ce6c9d6..cfedefe 100644
--- a/libbuild2/module.cxx
+++ b/libbuild2/module.cxx
@@ -363,7 +363,7 @@ namespace build2
{
// This could be initial or exclusive load.
//
- // @@ TODO
+ // @@ TODO: see the ad hoc recipe case as a reference.
//
fail (loc) << "nested build system module updates not yet supported";
}
diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx
index a4ae830..32f161b 100644
--- a/libbuild2/rule.cxx
+++ b/libbuild2/rule.cxx
@@ -855,6 +855,7 @@ namespace build2
// Update the library target in the module context.
//
const target* l (nullptr);
+ do // Breakout loop.
{
bool nested (ctx.module_context == &ctx);
@@ -881,49 +882,69 @@ namespace build2
path bf (pd / std_buildfile_file);
scope& rs (load_project (ctx, pd, pd, false /* forwarded */));
+ auto find_target = [&ctx, &rs, &pd, &id] ()
+ {
+ const target_type* tt (rs.find_target_type ("libs"));
+ assert (tt != nullptr);
+
+ const target* t (
+ ctx.targets.find (*tt, pd, dir_path () /* out */, id));
+ assert (t != nullptr);
+
+ return t;
+ };
+
// If the project has already been loaded then, as an optimization,
// check if the target has already been updated (this will make a
// difference we if we have identical recipes in several buildfiles).
//
if (!source_once (rs, rs, bf))
{
- const target_type* tt (rs.find_target_type ("libs"));
- assert (tt != nullptr);
-
- l = ctx.targets.find (*tt, pd, dir_path () /* out */, id);
- assert (l != nullptr);
+ l = find_target ();
- if (l->executed_state (perform_update_id) == target_state::unknown)
- l = nullptr;
+ if (l->executed_state (perform_update_id) != target_state::unknown)
+ break;
}
- if (l == nullptr)
+ if (nested)
{
- if (nested)
- {
- // @@ TODO: we probably want to make this work.
+ // This means there is a perform update action already in progress
+ // in this context. So we are going to switch the phase and
+ // perform direct match and update (similar how we do this for
+ // generated headers).
+ //
+ // Note that since neither match nor execute are serial phases, it
+ // means other targets in this context can be matched and executed
+ // in paralellel with us.
+ //
+ if (l == nullptr)
+ l = find_target ();
- fail (loc) << "nested ad hoc recipe updates not yet supported";
- }
- else
+ phase_switch mp (ctx, run_phase::match);
+ if (build2::match (perform_update_id, *l) != target_state::unchanged)
{
- // Cutoff the existing diagnostics stack and push our own entry.
- //
- diag_frame::stack_guard diag_cutoff (nullptr);
-
- auto df = make_diag_frame (
- [this, &t] (const diag_record& dr)
- {
- dr << info (loc) << "while updating ad hoc recipe for target "
- << t;
- });
-
- l = &update_in_module_context (
- ctx, rs, names {name (pd, "libs", id)},
- loc, bf);
+ phase_switch ep (ctx, run_phase::execute);
+ execute (a, *l);
}
}
- }
+ else
+ {
+ // Cutoff the existing diagnostics stack and push our own entry.
+ //
+ diag_frame::stack_guard diag_cutoff (nullptr);
+
+ auto df = make_diag_frame (
+ [this, &t] (const diag_record& dr)
+ {
+ dr << info (loc) << "while updating ad hoc recipe for target "
+ << t;
+ });
+
+ l = &update_in_module_context (
+ ctx, rs, names {name (pd, "libs", id)},
+ loc, bf);
+ }
+ } while (false);
// Load the library.
//