diff options
Diffstat (limited to 'libbuild2/adhoc-rule-cxx.cxx')
-rw-r--r-- | libbuild2/adhoc-rule-cxx.cxx | 109 |
1 files changed, 98 insertions, 11 deletions
diff --git a/libbuild2/adhoc-rule-cxx.cxx b/libbuild2/adhoc-rule-cxx.cxx index dc795df..8a91809 100644 --- a/libbuild2/adhoc-rule-cxx.cxx +++ b/libbuild2/adhoc-rule-cxx.cxx @@ -25,6 +25,13 @@ namespace build2 return true; } + recipe cxx_rule_v1:: + apply (action, target&) const + { + assert (false); // This (or the match_extra version) must be overriden. + return empty_recipe; + } + // adhoc_cxx_rule // adhoc_cxx_rule:: @@ -95,8 +102,10 @@ namespace build2 load_module_library (const path& lib, const string& sym, string& err); bool adhoc_cxx_rule:: - match (action a, target& t, const string& hint, match_extra& me) const + match (action a, target& xt, const string& hint, match_extra& me) const { + const target& t (xt); // See adhoc_rule::match() for background. + if (pattern != nullptr && !pattern->match (a, t, hint, me)) return false; @@ -302,9 +311,9 @@ namespace build2 // auto_thread_env penv (nullptr); context& ctx (*t.ctx.module_context); - scheduler::phase_guard pg (ctx.sched); + scheduler::phase_guard pg (*ctx.sched); - const uint16_t verbosity (3); // Project creation command verbosity. + uint16_t verbosity (3); // Project creation command verbosity. // Project and location signatures. // @@ -326,6 +335,17 @@ namespace build2 if (!create && (create = !check_sig (bf, psig))) rmdir_r (ctx, pd, false, verbosity); // Never dry-run. + auto diag = [verbosity] (const path& f) + { + if (verb >= verbosity) + { + if (verb >= 2) + text << "cat >" << f; + else if (verb) + print_diag ("save", f); + } + }; + path of; ofdstream ofs; @@ -338,6 +358,46 @@ namespace build2 // This way the configuration will be always in sync with ~build2 // and we can update the recipe manually (e.g., for debugging). // + // Should we use ~build2 or ~build2-no-warnings? This case is similar + // to private host/module configurations in that the user doesn't have + // any control over the options used, etc. So it would be natural to + // use the no-warnings variant. However, unlike with tools/modules + // which can be configured in a user-created configuration (and which + // will normally be the case during development), for recipes it's + // always this automatically-create configuration. It feels like the + // best we can do is use ~build2-no-warnings by default but switch to + // ~build2 if the project is configured for development + // (config.<project>.develop). + // + string cfg; + { + const project_name& pn (named_project (rs)); + + if (!pn.empty ()) + { + string var ("config." + pn.variable () + ".develop"); + + if (lookup l = rs[var]) + { + // The value could be untyped if the project didn't declare this + // variable. Let's handle that case gracefully. + // + try + { + if (convert<bool> (*l)) + cfg = "~build2"; + } + catch (const invalid_argument& e) + { + fail << "invalid " << var << " value: " << e; + } + } + } + + if (cfg.empty ()) + cfg = "~build2-no-warnings"; + } + create_project ( pd, dir_path (), /* amalgamation */ @@ -346,7 +406,7 @@ namespace build2 {"cxx."}, /* root_modules */ "", /* root_post */ string ("config"), /* config_module */ - string ("config.config.load = ~build2"), /* config_file */ + "config.config.load = " + cfg, /* config_file */ false, /* buildfile */ "build2 core", /* who */ verbosity); /* verbosity */ @@ -356,8 +416,7 @@ namespace build2 // of = path (pd / "rule.cxx"); - if (verb >= verbosity) - text << (verb >= 2 ? "cat >" : "save ") << of; + diag (of); ofs.open (of); @@ -377,6 +436,8 @@ namespace build2 << "#include <libbuild2/depdb.hxx>" << '\n' << "#include <libbuild2/scope.hxx>" << '\n' << "#include <libbuild2/target.hxx>" << '\n' + << "#include <libbuild2/recipe.hxx>" << '\n' + << "#include <libbuild2/dyndep.hxx>" << '\n' << "#include <libbuild2/context.hxx>" << '\n' << "#include <libbuild2/variable.hxx>" << '\n' << "#include <libbuild2/algorithm.hxx>" << '\n' @@ -486,8 +547,7 @@ namespace build2 // of = bf; - if (verb >= verbosity) - text << (verb >= 2 ? "cat >" : "save ") << of; + diag (of); ofs.open (of); @@ -559,8 +619,7 @@ namespace build2 entry_time et (file_time (of)); - if (verb >= verbosity) - text << (verb >= 2 ? "cat >" : "save ") << of; + diag (of); ofs.open (of); @@ -665,13 +724,41 @@ namespace build2 } } - return impl->match (a, t, hint, me); + return impl->match (a, xt, hint, me); } #endif // BUILD2_BOOTSTRAP || LIBBUILD2_STATIC_BUILD recipe adhoc_cxx_rule:: apply (action a, target& t, match_extra& me) const { + // Handle matching explicit group member (see adhoc_rule::match() for + // background). + // + if (const group* g = (t.group != nullptr + ? t.group->is_a<group> () + : nullptr)) + { + // @@ Hm, this looks very similar to how we handle ad hoc group members. + // Shouldn't impl be given a chance to translate options or some + // such? + // + match_sync (a, *g, 0 /* options */); + return group_recipe; // Execute the group's recipe. + } + + // Note that while we probably could call pattern's apply_group_members() + // here, apply_group_prerequisites() is normally called after adding + // prerequisites but before matching, which can only be done from the + // rule's implementation. Also, for apply_group_members(), there is the + // explicit group special case which may also require custom logic. + // So it feels best to leave both to the implementation. + return impl.load (memory_order_relaxed)->apply (a, t, me); } + + void adhoc_cxx_rule:: + reapply (action a, target& t, match_extra& me) const + { + return impl.load (memory_order_relaxed)->reapply (a, t, me); + } } |