diff options
-rw-r--r-- | libbuild2/context.hxx | 9 | ||||
-rw-r--r-- | libbuild2/module.cxx | 2 | ||||
-rw-r--r-- | libbuild2/rule.cxx | 79 |
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. // |