From 421d0a4d1a7786e90407072b378cc060d325907d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 23 Aug 2019 09:46:11 +0200 Subject: Variables --- build2/b.cxx | 10 +-- build2/cc/pkgconfig.cxx | 13 +++- libbuild2/algorithm.cxx | 18 +++-- libbuild2/config/operation.cxx | 30 +++++--- libbuild2/context.cxx | 31 +------- libbuild2/context.hxx | 165 +++++++++++++++++++++-------------------- libbuild2/dist/operation.cxx | 4 +- libbuild2/file.cxx | 94 +++++++++++++---------- libbuild2/operation.cxx | 18 +++-- libbuild2/prerequisite.cxx | 26 ------- libbuild2/prerequisite.hxx | 32 -------- libbuild2/prerequisite.ixx | 34 --------- libbuild2/scope.ixx | 4 +- libbuild2/target.cxx | 28 +++++++ libbuild2/target.hxx | 32 ++++++++ libbuild2/target.ixx | 28 +++++++ libbuild2/test/rule.cxx | 8 +- libbuild2/version/init.cxx | 16 ++-- 18 files changed, 306 insertions(+), 285 deletions(-) delete mode 100644 libbuild2/prerequisite.ixx diff --git a/build2/b.cxx b/build2/b.cxx index cb9c2c0..af51a31 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -794,7 +794,7 @@ main (int argc, char* argv[]) // limitations as for pre-processing). // scope& gs (ctx->global_scope.rw ()); - gs.assign (var_build_meta_operation) = mname; + gs.assign (ctx->var_build_meta_operation) = mname; for (auto oit (opspecs.begin ()); oit != opspecs.end (); ++oit) { @@ -1041,7 +1041,7 @@ main (int argc, char* argv[]) // See if the bootstrap process set/changed src_root. // - value& v (rs.assign (var_src_root)); + value& v (rs.assign (ctx->var_src_root)); if (v) { @@ -1103,7 +1103,7 @@ main (int argc, char* argv[]) // command line and import). // if (forwarded) - rs.assign (var_forwarded) = true; + rs.assign (ctx->var_forwarded) = true; // Sync local variable that are used below with actual values. // @@ -1140,7 +1140,7 @@ main (int argc, char* argv[]) // Note that the subprojects variable has already been processed // and converted to a map by the bootstrap_src() call above. // - if (auto l = rs.vars[var_subprojects]) + if (auto l = rs.vars[ctx->var_subprojects]) { for (const auto& p: cast (l)) { @@ -1413,7 +1413,7 @@ main (int argc, char* argv[]) trace << " out_root: " << out_root; trace << " src_root: " << src_root; trace << " forwarded: " << (forwarded ? "true" : "false"); - if (auto l = rs.vars[var_amalgamation]) + if (auto l = rs.vars[ctx->var_amalgamation]) { trace << " amalgamation: " << cast (l); trace << " strong scope: " << *rs.strong_scope (); diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx index 13cc752..038ecc6 100644 --- a/build2/cc/pkgconfig.cxx +++ b/build2/cc/pkgconfig.cxx @@ -1228,6 +1228,8 @@ namespace build2 { tracer trace (x, "pkgconfig_save"); + context& ctx (l.ctx); + const scope& bs (l.base_scope ()); const scope& rs (*bs.root_scope ()); @@ -1256,9 +1258,12 @@ namespace build2 ofdstream os (p); { - const project_name& n (cast (rs.vars[var_project])); + const project_name& n (project (rs)); + + if (n.empty ()) + fail << "no project name in " << rs; - lookup vl (rs.vars[var_version]); + lookup vl (rs.vars[ctx.var_version]); if (!vl) fail << "no version variable in project " << n << info << "while generating " << p; @@ -1271,12 +1276,12 @@ namespace build2 // This one is required so make something up if unspecified. // os << "Description: "; - if (const string* s = cast_null (rs[var_project_summary])) + if (const string* s = cast_null (rs[ctx.var_project_summary])) os << *s << endl; else os << n << ' ' << v << endl; - if (const string* u = cast_null (rs[var_project_url])) + if (const string* u = cast_null (rs[ctx.var_project_url])) os << "URL: " << *u << endl; } diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 12cd61f..8bc6ee1 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -1377,6 +1377,8 @@ namespace build2 static optional backlink_test (action a, target& t) { + context& ctx (t.ctx); + // Note: the order of these checks is from the least to most expensive. // Only for plain update/clean. @@ -1398,17 +1400,17 @@ namespace build2 // Only for forwarded configurations. // - if (!cast_false (rs->vars[var_forwarded])) + if (!cast_false (rs->vars[ctx.var_forwarded])) return nullopt; - lookup l (t.state[a][var_backlink]); + lookup l (t.state[a][ctx.var_backlink]); // If not found, check for some defaults in the global scope (this does // not happen automatically since target type/pattern-specific lookup // stops at the project boundary). // if (!l.defined ()) - l = t.ctx.global_scope.find (*var_backlink, t.key ()); + l = ctx.global_scope.find (*ctx.var_backlink, t.key ()); return l ? backlink_test (t, l) : nullopt; } @@ -1459,7 +1461,7 @@ namespace build2 // as a target-specific wouldn't be MT-safe). @@ Don't think this // applies to declared ad hoc members. // - lookup l (mt->state[a].vars[var_backlink]); + lookup l (mt->state[a].vars[t.ctx.var_backlink]); optional bm (l ? backlink_test (*mt, l) : m); @@ -2034,6 +2036,8 @@ namespace build2 bool ed (false); path ep; + context& ctx (ft.ctx); + auto clean_extra = [&er, &ed, &ep] (const file& f, const path* fp, const clean_extras& es) @@ -2123,7 +2127,7 @@ namespace build2 // depdb so for now we treat them as "to remove" but in the future we may // need to have two lists. // - bool clean (cast_true (ft[var_clean])); + bool clean (cast_true (ft[ctx.var_clean])); // Now clean the ad hoc group file members, if any. // @@ -2198,7 +2202,7 @@ namespace build2 // if (tr != target_state::changed && er == target_state::changed) { - if (verb > (ft.ctx.current_diag_noise ? 0 : 1) && verb < 3) + if (verb > (ctx.current_diag_noise ? 0 : 1) && verb < 3) { if (ed) text << "rm -r " << path_cast (ep); @@ -2236,7 +2240,7 @@ namespace build2 // target_state r (target_state::unchanged); - if (cast_true (g[var_clean])) + if (cast_true (g[g.ctx.var_clean])) { for (group_view gv (g.group_members (a)); gv.count != 0; --gv.count) { diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index 92c80b8..c5ff580 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -90,6 +90,8 @@ namespace build2 static void save_config (const scope& rs, const project_set& projects) { + context& ctx (rs.ctx); + path f (config_file (rs)); if (verb) @@ -107,7 +109,7 @@ namespace build2 ofs << "config.version = " << module::version << endl; - if (auto l = rs.vars[var_amalgamation]) + if (auto l = rs.vars[ctx.var_amalgamation]) { const dir_path& d (cast (l)); @@ -144,7 +146,7 @@ namespace build2 if (!l.defined ()) continue; - if (!(l.belongs (rs) || l.belongs (rs.ctx.global_scope))) + if (!(l.belongs (rs) || l.belongs (ctx.global_scope))) { // This is presumably an inherited value. But it could also be // some left-over garbage. For example, an amalgamation could @@ -311,6 +313,8 @@ namespace build2 { tracer trace ("configure_project"); + context& ctx (rs.ctx); + const dir_path& out_root (rs.out_path ()); const dir_path& src_root (rs.src_path ()); @@ -350,13 +354,13 @@ namespace build2 // Configure subprojects that have been loaded. // - if (auto l = rs.vars[var_subprojects]) + if (auto l = rs.vars[ctx.var_subprojects]) { for (auto p: cast (l)) { const dir_path& pd (p.second); dir_path out_nroot (out_root / pd); - const scope& nrs (rs.ctx.scopes.find (out_nroot)); + const scope& nrs (ctx.scopes.find (out_nroot)); // @@ Strictly speaking we need to check whether the config // module was loaded for this subproject. @@ -374,6 +378,8 @@ namespace build2 { tracer trace ("configure_forward"); + context& ctx (rs.ctx); + const dir_path& out_root (rs.out_path ()); const dir_path& src_root (rs.src_path ()); @@ -389,12 +395,12 @@ namespace build2 // Configure subprojects. Since we don't load buildfiles if configuring // a forward, we do it for all known subprojects. // - if (auto l = rs.vars[var_subprojects]) + if (auto l = rs.vars[ctx.var_subprojects]) { for (auto p: cast (l)) { dir_path out_nroot (out_root / p.second); - const scope& nrs (rs.ctx.scopes.find (out_nroot)); + const scope& nrs (ctx.scopes.find (out_nroot)); assert (nrs.out_path () == out_nroot); configure_forward (nrs, projects); @@ -592,6 +598,8 @@ namespace build2 { tracer trace ("disfigure_project"); + context& ctx (rs.ctx); + const dir_path& out_root (rs.out_path ()); const dir_path& src_root (rs.src_path ()); @@ -606,13 +614,13 @@ namespace build2 // Disfigure subprojects. Since we don't load buildfiles during // disfigure, we do it for all known subprojects. // - if (auto l = rs.vars[var_subprojects]) + if (auto l = rs.vars[ctx.var_subprojects]) { for (auto p: cast (l)) { const dir_path& pd (p.second); dir_path out_nroot (out_root / pd); - const scope& nrs (rs.ctx.scopes.find (out_nroot)); + const scope& nrs (ctx.scopes.find (out_nroot)); assert (nrs.out_path () == out_nroot); // See disfigure_load(). r = disfigure_project (a, nrs, projects) || r; @@ -695,6 +703,8 @@ namespace build2 // tracer trace ("disfigure_forward"); + context& ctx (rs.ctx); + const dir_path& out_root (rs.out_path ()); const dir_path& src_root (rs.src_path ()); @@ -706,12 +716,12 @@ namespace build2 bool r (false); - if (auto l = rs.vars[var_subprojects]) + if (auto l = rs.vars[ctx.var_subprojects]) { for (auto p: cast (l)) { dir_path out_nroot (out_root / p.second); - const scope& nrs (rs.ctx.scopes.find (out_nroot)); + const scope& nrs (ctx.scopes.find (out_nroot)); assert (nrs.out_path () == out_nroot); r = disfigure_forward (nrs, projects) || r; diff --git a/libbuild2/context.cxx b/libbuild2/context.cxx index c5b31ad..1e744c4 100644 --- a/libbuild2/context.cxx +++ b/libbuild2/context.cxx @@ -477,11 +477,10 @@ namespace build2 var_import_target = &vp.insert ("import.target"); - var_clean = &vp.insert ("clean", v_t); - var_backlink = &vp.insert ("backlink", v_t); - var_include = &vp.insert ("include", v_q); - - vp.insert (var_extension, v_t); + var_extension = &vp.insert ("extension", v_t); + var_clean = &vp.insert ("clean", v_t); + var_backlink = &vp.insert ("backlink", v_t); + var_include = &vp.insert ("include", v_q); // Backlink executables and (generated) documentation by default. // @@ -863,27 +862,5 @@ namespace build2 bool, const location&); - const variable* var_src_root; - const variable* var_out_root; - const variable* var_src_base; - const variable* var_out_base; - const variable* var_forwarded; - - const variable* var_project; - const variable* var_amalgamation; - const variable* var_subprojects; - const variable* var_version; - - const variable* var_project_url; - const variable* var_project_summary; - - const variable* var_import_target; - - const variable* var_clean; - const variable* var_backlink; - const variable* var_include; - const char var_extension[10] = "extension"; - - const variable* var_build_meta_operation; } diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx index 4680fd1..a947ca3 100644 --- a/libbuild2/context.hxx +++ b/libbuild2/context.hxx @@ -240,6 +240,90 @@ namespace build2 const variable_pool& var_pool; const variable_overrides& var_overrides; // Project and relative scope. + // Cached variables. + // + + // Note: consider printing in info meta-operation if adding anything here. + // + const variable* var_src_root; + const variable* var_out_root; + const variable* var_src_base; + const variable* var_out_base; + const variable* var_forwarded; + + const variable* var_project; + const variable* var_amalgamation; + const variable* var_subprojects; + const variable* var_version; + + // project.url + // + const variable* var_project_url; + + // project.summary + // + const variable* var_project_summary; + + // import.target + // + const variable* var_import_target; + + // [string] target visibility + // + const variable* var_extension; + + // [bool] target visibility + // + const variable* var_clean; + + // Forwarded configuration backlink mode. Valid values are: + // + // false - no link. + // true - make a link using appropriate mechanism. + // symbolic - make a symbolic link. + // hard - make a hard link. + // copy - make a copy. + // overwrite - copy over but don't remove on clean (committed gen code). + // + // Note that it can be set by a matching rule as a rule-specific variable. + // + // [string] target visibility + // + const variable* var_backlink; + + // Prerequisite inclusion/exclusion. Valid values are: + // + // false - exclude. + // true - include. + // adhoc - include but treat as an ad hoc input. + // + // If a rule uses prerequisites as inputs (as opposed to just matching + // them with the "pass-through" semantics), then the adhoc value signals + // that a prerequisite is an ad hoc input. A rule should match and execute + // such a prerequisite (whether its target type is recognized as suitable + // input or not) and assume that the rest will be handled by the user + // (e.g., it will be passed via a command line argument or some such). + // Note that this mechanism can be used to both treat unknown prerequisite + // types as inputs (for example, linker scripts) as well as prevent + // treatment of known prerequisite types as such while still matching and + // executing them (for example, plugin libraries). + // + // A rule with the "pass-through" semantics should treat the adhoc value + // the same as true. + // + // To query this value in rule implementations use the include() helpers + // from . + // + // [string] prereq visibility + // + const variable* var_include; + + // The build.* namespace. + // + // .meta_operation + // + const variable* var_build_meta_operation; + public: explicit context (scheduler&, const strings& cmd_vars = {}); @@ -442,87 +526,8 @@ namespace build2 bool lifted, const location&); - // Cached variables. - // - - // Note: consider printing in info meta-operation if adding anything here. - // - LIBBUILD2_SYMEXPORT extern const variable* var_src_root; - LIBBUILD2_SYMEXPORT extern const variable* var_out_root; - LIBBUILD2_SYMEXPORT extern const variable* var_src_base; - LIBBUILD2_SYMEXPORT extern const variable* var_out_base; - LIBBUILD2_SYMEXPORT extern const variable* var_forwarded; - - LIBBUILD2_SYMEXPORT extern const variable* var_project; - LIBBUILD2_SYMEXPORT extern const variable* var_amalgamation; - LIBBUILD2_SYMEXPORT extern const variable* var_subprojects; - LIBBUILD2_SYMEXPORT extern const variable* var_version; - - // project.url - // - LIBBUILD2_SYMEXPORT extern const variable* var_project_url; - - // project.summary - // - LIBBUILD2_SYMEXPORT extern const variable* var_project_summary; - - // import.target - // - LIBBUILD2_SYMEXPORT extern const variable* var_import_target; - - // [bool] target visibility - // - LIBBUILD2_SYMEXPORT extern const variable* var_clean; - - // Forwarded configuration backlink mode. Valid values are: - // - // false - no link. - // true - make a link using appropriate mechanism. - // symbolic - make a symbolic link. - // hard - make a hard link. - // copy - make a copy. - // overwrite - copy over but don't remove on clean (committed gen code). - // - // Note that it can be set by a matching rule as a rule-specific variable. - // - // [string] target visibility - // - LIBBUILD2_SYMEXPORT extern const variable* var_backlink; - - // Prerequisite inclusion/exclusion. Valid values are: - // - // false - exclude. - // true - include. - // adhoc - include but treat as an ad hoc input. - // - // If a rule uses prerequisites as inputs (as opposed to just matching them - // with the "pass-through" semantics), then the adhoc value signals that a - // prerequisite is an ad hoc input. A rule should match and execute such a - // prerequisite (whether its target type is recognized as suitable input or - // not) and assume that the rest will be handled by the user (e.g., it will - // be passed via a command line argument or some such). Note that this - // mechanism can be used to both treat unknown prerequisite types as inputs - // (for example, linker scripts) as well as prevent treatment of known - // prerequisite types as such while still matching and executing them (for - // example, plugin libraries). - // - // A rule with the "pass-through" semantics should treat the adhoc value - // the same as true. - // - // To query this value in rule implementations use the include() helpers - // from . - // - // [string] prereq visibility - // - LIBBUILD2_SYMEXPORT extern const variable* var_include; - + //@@ CTX TMP LIBBUILD2_SYMEXPORT extern const char var_extension[10]; // "extension" - - // The build.* namespace. - // - // .meta_operation - // - LIBBUILD2_SYMEXPORT extern const variable* var_build_meta_operation; } #include diff --git a/libbuild2/dist/operation.cxx b/libbuild2/dist/operation.cxx index 6db3626..2367329 100644 --- a/libbuild2/dist/operation.cxx +++ b/libbuild2/dist/operation.cxx @@ -228,7 +228,7 @@ namespace build2 // The same for subprojects that have been loaded. // - if (auto l = rs->vars[var_subprojects]) + if (auto l = rs->vars[ctx.var_subprojects]) { for (auto p: cast (l)) { @@ -369,7 +369,7 @@ namespace build2 const scope* srs (rs); const module::callbacks* cbs (&mod.callbacks_); - if (auto l = rs->vars[var_subprojects]) + if (auto l = rs->vars[ctx.var_subprojects]) { for (auto p: cast (l)) { diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx index 207f569..3068733 100644 --- a/libbuild2/file.cxx +++ b/libbuild2/file.cxx @@ -268,6 +268,8 @@ namespace build2 auto i (s.ctx.scopes.rw (s).insert (out_root, true /* root */)); scope& rs (i->second); + context& ctx (rs.ctx); + // Set out_path. Note that src_path is set in setup_root() below. // if (rs.out_path_ != &i->first) @@ -279,7 +281,7 @@ namespace build2 // If this is already a root scope, verify that things are consistent. // { - value& v (rs.assign (var_out_root)); + value& v (rs.assign (ctx.var_out_root)); if (!v) v = out_root; @@ -295,7 +297,7 @@ namespace build2 if (!src_root.empty ()) { - value& v (rs.assign (var_src_root)); + value& v (rs.assign (ctx.var_src_root)); if (!v) v = src_root; @@ -315,9 +317,11 @@ namespace build2 void setup_root (scope& s, bool forwarded) { + context& ctx (s.ctx); + // The caller must have made sure src_root is set on this scope. // - value& v (s.assign (var_src_root)); + value& v (s.assign (ctx.var_src_root)); assert (v); const dir_path& d (cast (v)); @@ -326,7 +330,7 @@ namespace build2 else assert (s.src_path_ == &d); - s.assign (var_forwarded) = forwarded; + s.assign (ctx.var_forwarded) = forwarded; } scope& @@ -335,17 +339,18 @@ namespace build2 const dir_path& src_base) { scope& s (i->second); + context& ctx (s.ctx); // Set src/out_base variables. // - value& ov (s.assign (var_out_base)); + value& ov (s.assign (ctx.var_out_base)); if (!ov) ov = out_base; else assert (cast (ov) == out_base); - value& sv (s.assign (var_src_base)); + value& sv (s.assign (ctx.var_src_base)); if (!sv) sv = src_base; @@ -420,7 +425,7 @@ namespace build2 // We cannot just source the buildfile since there is no scope to do // this on yet. // - auto p (extract_variable (ctx, f, *var_out_root)); + auto p (extract_variable (ctx, f, *ctx.var_out_root)); if (!p.second) fail << "variable out_root expected as first line in " << f; @@ -557,7 +562,7 @@ namespace build2 assert (*altn == s.root_extra->altn); } - if (lookup l = s.vars[var_project]) + if (lookup l = s.vars[ctx.var_project]) return cast (l); src_root = s.src_path_; @@ -589,7 +594,7 @@ namespace build2 } else { - auto p (extract_variable (ctx, f, *var_src_root)); + auto p (extract_variable (ctx, f, *ctx.var_src_root)); if (!p.second) fail << "variable src_root expected as first line in " << f; @@ -611,10 +616,10 @@ namespace build2 if (f.empty ()) fail << "no build/bootstrap.build in " << *src_root; - auto p (extract_variable (ctx, f, *var_project)); + auto p (extract_variable (ctx, f, *ctx.var_project)); if (!p.second) - fail << "variable " << var_project->name << " expected " + fail << "variable " << ctx.var_project->name << " expected " << "as a first line in " << f; name = cast (move (p.first)); @@ -714,6 +719,8 @@ namespace build2 { tracer trace ("bootstrap_src"); + context& ctx (rs.ctx); + bool r (false); const dir_path& out_root (rs.out_path ()); @@ -760,7 +767,7 @@ namespace build2 // Note: the amalgamation variable value is always a relative directory. // { - auto rp (rs.vars.insert (*var_amalgamation)); // Set NULL by default. + auto rp (rs.vars.insert (*ctx.var_amalgamation)); // Set NULL by default. value& v (rp.first); if (v && v.empty ()) // Convert empty to NULL. @@ -832,7 +839,7 @@ namespace build2 // NULL value indicates that we found no subprojects. // { - auto rp (rs.vars.insert (*var_subprojects)); // Set NULL by default. + auto rp (rs.vars.insert (*ctx.var_subprojects)); // Set NULL by default. value& v (rp.first); if (rp.second) @@ -987,13 +994,13 @@ namespace build2 } bool - bootstrapped (scope& root) + bootstrapped (scope& rs) { // Use the subprojects variable set by bootstrap_src() as an indicator. // It should either be NULL or typed (so we assume that the user will // never set it to NULL). // - auto l (root.vars[var_subprojects]); + auto l (rs.vars[rs.ctx.var_subprojects]); return l.defined () && (l->null || l->type != nullptr); } @@ -1006,6 +1013,8 @@ namespace build2 const dir_path& src_root, optional& altn) { + context& ctx (orig.ctx); + // The conditions are: // // 1. Origin is itself forwarded. @@ -1014,15 +1023,17 @@ namespace build2 // // 3. Inner/outer out-root.build exists in src_root and refers out_root. // - return (out_root != src_root && - cast_false (orig.vars[var_forwarded]) && - bootstrap_fwd (orig.ctx, src_root, altn) == out_root); + return (out_root != src_root && + cast_false (orig.vars[ctx.var_forwarded]) && + bootstrap_fwd (ctx, src_root, altn) == out_root); } void create_bootstrap_outer (scope& root) { - auto l (root.vars[var_amalgamation]); + context& ctx (root.ctx); + + auto l (root.vars[ctx.var_amalgamation]); if (!l) return; @@ -1050,7 +1061,7 @@ namespace build2 { bootstrap_out (rs, altn); // #3 happens here (or it can be #1). - value& v (rs.assign (var_src_root)); + value& v (rs.assign (ctx.var_src_root)); if (!v) { @@ -1076,7 +1087,7 @@ namespace build2 altn = rs.root_extra->altn; if (forwarded (root, rs.out_path (), rs.src_path (), altn)) - rs.assign (var_forwarded) = true; // Only upgrade (see main()). + rs.assign (ctx.var_forwarded) = true; // Only upgrade (see main()). } create_bootstrap_outer (rs); @@ -1093,9 +1104,11 @@ namespace build2 scope& create_bootstrap_inner (scope& root, const dir_path& out_base) { + context& ctx (root.ctx); + scope* r (&root); - if (auto l = root.vars[var_subprojects]) + if (auto l = root.vars[ctx.var_subprojects]) { for (const auto& p: cast (l)) { @@ -1113,7 +1126,7 @@ namespace build2 { bootstrap_out (rs, altn); - value& v (rs.assign (var_src_root)); + value& v (rs.assign (ctx.var_src_root)); if (!v) { @@ -1133,7 +1146,7 @@ namespace build2 { altn = rs.root_extra->altn; if (forwarded (root, rs.out_path (), rs.src_path (), altn)) - rs.assign (var_forwarded) = true; // Only upgrade (see main()). + rs.assign (ctx.var_forwarded) = true; // Only upgrade (see main()). } // Check if we strongly amalgamated this inner root scope. @@ -1209,7 +1222,7 @@ namespace build2 } scope& - load_project (scope& lock, + load_project (scope& s, const dir_path& out_root, const dir_path& src_root, bool forwarded, @@ -1217,7 +1230,9 @@ namespace build2 { assert (!forwarded || out_root != src_root); - auto i (create_root (lock, out_root, src_root)); + context& ctx (s.ctx); + + auto i (create_root (s, out_root, src_root)); scope& rs (i->second); if (!bootstrapped (rs)) @@ -1232,7 +1247,7 @@ namespace build2 else { if (forwarded) - rs.assign (var_forwarded) = true; // Only upgrade (see main()). + rs.assign (ctx.var_forwarded) = true; // Only upgrade (see main()). } if (load) @@ -1261,6 +1276,8 @@ namespace build2 return names {move (target)}; } + context& ctx (ibase.ctx); + // Otherwise, get the project name and convert the target to unqualified. // project_name proj (move (*target.proj)); @@ -1379,13 +1396,14 @@ namespace build2 // First check the amalgamation itself. // - if (r != &iroot && cast (r->vars[var_project]) == proj) + if (r != &iroot && + cast (r->vars[ctx.var_project]) == proj) { out_root = r->out_path (); break; } - if (auto l = r->vars[var_subprojects]) + if (auto l = r->vars[ctx.var_subprojects]) { const auto& m (cast (l)); auto i (m.find (proj)); @@ -1398,7 +1416,7 @@ namespace build2 } } - if (!r->vars[var_amalgamation]) + if (!r->vars[ctx.var_amalgamation]) break; } @@ -1415,8 +1433,6 @@ namespace build2 return names {move (target)}; } - context& ctx (ibase.ctx); - // Bootstrap the imported root scope. This is pretty similar to what we do // in main() except that here we don't try to guess src_root. // @@ -1453,7 +1469,7 @@ namespace build2 // Check that the bootstrap process set src_root. // - auto l (root->vars[*var_src_root]); + auto l (root->vars[*ctx.var_src_root]); if (l) { // Note that unlike main() here we fail hard. The idea is that if @@ -1488,7 +1504,7 @@ namespace build2 src_root = root->src_path (); if (top ? fwd : forwarded (*proot, out_root, src_root, altn)) - root->assign (var_forwarded) = true; // Only upgrade (see main()). + root->assign (ctx.var_forwarded) = true; // Only upgrade (see main()). } if (top) @@ -1501,10 +1517,10 @@ namespace build2 // Now we know this project's name as well as all its subprojects. // - if (cast (root->vars[var_project]) == proj) + if (cast (root->vars[ctx.var_project]) == proj) break; - if (auto l = root->vars[var_subprojects]) + if (auto l = root->vars[ctx.var_subprojects]) { const auto& m (cast (l)); auto i (m.find (proj)); @@ -1533,13 +1549,13 @@ namespace build2 // "Pass" the imported project's roots to the stub. // - ts.assign (var_out_root) = move (out_root); - ts.assign (var_src_root) = move (src_root); + ts.assign (ctx.var_out_root) = move (out_root); + ts.assign (ctx.var_src_root) = move (src_root); // Also pass the target being imported in the import.target variable. // { - value& v (ts.assign (var_import_target)); + value& v (ts.assign (ctx.var_import_target)); if (!target.empty ()) // Otherwise leave NULL. v = target; // Can't move (need for diagnostics below). diff --git a/libbuild2/operation.cxx b/libbuild2/operation.cxx index 19f6e4e..661c439 100644 --- a/libbuild2/operation.cxx +++ b/libbuild2/operation.cxx @@ -517,6 +517,8 @@ namespace build2 const scope& rs (*static_cast (ts[i].target)); + context& ctx (rs.ctx); + // Print [meta_]operation names. Due to the way our aliasing works, we // have to go through the [meta_]operation_table. // @@ -536,14 +538,14 @@ namespace build2 // This could be a simple project that doesn't set project name. // cout - << "project: " << cast_empty (rs[var_project]) << endl - << "version: " << cast_empty (rs[var_version]) << endl - << "summary: " << cast_empty (rs[var_project_summary]) << endl - << "url: " << cast_empty (rs[var_project_url]) << endl - << "src_root: " << cast (rs[var_src_root]) << endl - << "out_root: " << cast (rs[var_out_root]) << endl - << "amalgamation: " << cast_empty (rs[var_amalgamation]) << endl - << "subprojects: " << cast_empty (rs[var_subprojects]) << endl + << "project: " << cast_empty (rs[ctx.var_project]) << endl + << "version: " << cast_empty (rs[ctx.var_version]) << endl + << "summary: " << cast_empty (rs[ctx.var_project_summary]) << endl + << "url: " << cast_empty (rs[ctx.var_project_url]) << endl + << "src_root: " << cast (rs[ctx.var_src_root]) << endl + << "out_root: " << cast (rs[ctx.var_out_root]) << endl + << "amalgamation: " << cast_empty (rs[ctx.var_amalgamation]) << endl + << "subprojects: " << cast_empty (rs[ctx.var_subprojects]) << endl << "operations:"; print_ops (rs.root_extra->operations, operation_table); cout << endl << "meta-operations:"; print_ops (rs.root_extra->meta_operations, meta_operation_table); cout << endl; } diff --git a/libbuild2/prerequisite.cxx b/libbuild2/prerequisite.cxx index 0883b75..7b815d5 100644 --- a/libbuild2/prerequisite.cxx +++ b/libbuild2/prerequisite.cxx @@ -92,30 +92,4 @@ namespace build2 return r; } - - // include() - // - include_type - include_impl (action a, - const target& t, - const string& v, - const prerequisite& p, - const target* m) - { - include_type r (false); - - if (v == "false") r = include_type::excluded; - else if (v == "adhoc") r = include_type::adhoc; - else if (v == "true") r = include_type::normal; - else - fail << "invalid " << var_include->name << " variable value " - << "'" << v << "' specified for prerequisite " << p; - - // Call the meta-operation override, if any (currently used by dist). - // - if (auto f = t.ctx.current_mif->include) - r = f (a, t, prerequisite_member {p, m}, r); - - return r; - } } diff --git a/libbuild2/prerequisite.hxx b/libbuild2/prerequisite.hxx index 3183a29..fe6d10a 100644 --- a/libbuild2/prerequisite.hxx +++ b/libbuild2/prerequisite.hxx @@ -192,38 +192,6 @@ namespace build2 } using prerequisites = vector; - - // Helpers for dealing with the prerequisite inclusion/exclusion (the - // 'include' buildfile variable, see var_include in context.hxx). - // - // Note that the include(prerequisite_member) overload is also provided. - // - // @@ Maybe this filtering should be incorporated into *_prerequisites() and - // *_prerequisite_members() logic? Could make normal > adhoc > excluded and - // then pass the "threshold". - // - class include_type - { - public: - enum value {excluded, adhoc, normal}; - - include_type (value v): v_ (v) {} - include_type (bool v): v_ (v ? normal : excluded) {} - - operator value () const {return v_;} - explicit operator bool () const {return v_ != excluded;} - - private: - value v_; - }; - - include_type - include (action, - const target&, - const prerequisite&, - const target* = nullptr); } -#include - #endif // LIBBUILD2_PREREQUISITE_HXX diff --git a/libbuild2/prerequisite.ixx b/libbuild2/prerequisite.ixx deleted file mode 100644 index d62af49..0000000 --- a/libbuild2/prerequisite.ixx +++ /dev/null @@ -1,34 +0,0 @@ -// file : libbuild2/prerequisite.ixx -*- C++ -*- -// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -namespace build2 -{ - LIBBUILD2_SYMEXPORT include_type - include_impl (action, - const target&, - const string&, - const prerequisite&, - const target*); - - LIBBUILD2_SYMEXPORT extern const variable* var_include; // context.cxx - - inline include_type - include (action a, const target& t, const prerequisite& p, const target* m) - { - // Most of the time this variable will not be specified, so let's optimize - // for that. - // - if (p.vars.empty ()) - return true; - - const string* v (cast_null (p.vars[var_include])); - - if (v == nullptr) - return true; - - return include_impl (a, t, *v, p, m); - } -} diff --git a/libbuild2/scope.ixx b/libbuild2/scope.ixx index aa1247f..14907d3 100644 --- a/libbuild2/scope.ixx +++ b/libbuild2/scope.ixx @@ -83,9 +83,9 @@ namespace build2 } inline const project_name& - project (const scope& root) + project (const scope& rs) { - auto l (root[var_project]); + auto l (rs[rs.ctx.var_project]); return l ? cast (l) : empty_project_name; } } diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx index 5e6db5a..9d81dee 100644 --- a/libbuild2/target.cxx +++ b/libbuild2/target.cxx @@ -290,6 +290,34 @@ namespace build2 } } + // include() + // + include_type + include_impl (action a, + const target& t, + const string& v, + const prerequisite& p, + const target* m) + { + context& ctx (t.ctx); + + include_type r (false); + + if (v == "false") r = include_type::excluded; + else if (v == "adhoc") r = include_type::adhoc; + else if (v == "true") r = include_type::normal; + else + fail << "invalid " << ctx.var_include->name << " variable value " + << "'" << v << "' specified for prerequisite " << p; + + // Call the meta-operation override, if any (currently used by dist). + // + if (auto f = ctx.current_mif->include) + r = f (a, t, prerequisite_member {p, m}, r); + + return r; + } + // target_set // const target* target_set:: diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index 62b6753..f140122 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -38,6 +38,23 @@ namespace build2 LIBBUILD2_SYMEXPORT const target* search_existing (const prerequisite&); + // Prerequisite inclusion/exclusion (see include() function below). + // + class include_type + { + public: + enum value {excluded, adhoc, normal}; + + include_type (value v): v_ (v) {} + include_type (bool v): v_ (v ? normal : excluded) {} + + operator value () const {return v_;} + explicit operator bool () const {return v_ != excluded;} + + private: + value v_; + }; + // Recipe. // // The returned target state is normally changed or unchanged. If there is @@ -798,6 +815,21 @@ namespace build2 uint8_t unmark (const target*&); + // Helper for dealing with the prerequisite inclusion/exclusion (the + // 'include' buildfile variable, see var_include in context.hxx). + // + // Note that the include(prerequisite_member) overload is also provided. + // + // @@ Maybe this filtering should be incorporated into *_prerequisites() and + // *_prerequisite_members() logic? Could make normal > adhoc > excluded and + // then pass the "threshold". + // + include_type + include (action, + const target&, + const prerequisite&, + const target* = nullptr); + // A "range" that presents the prerequisites of a group and one of // its members as one continuous sequence, or, in other words, as // if they were in a single container. The group's prerequisites diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx index 980df7c..dd377b0 100644 --- a/libbuild2/target.ixx +++ b/libbuild2/target.ixx @@ -6,6 +6,8 @@ #include // mtime() +#include + namespace build2 { // target @@ -212,6 +214,32 @@ namespace build2 return m; } + // include() + // + LIBBUILD2_SYMEXPORT include_type + include_impl (action, + const target&, + const string&, + const prerequisite&, + const target*); + + inline include_type + include (action a, const target& t, const prerequisite& p, const target* m) + { + // Most of the time this variable will not be specified, so let's optimize + // for that. + // + if (p.vars.empty ()) + return true; + + const string* v (cast_null (p.vars[t.ctx.var_include])); + + if (v == nullptr) + return true; + + return include_impl (a, t, *v, p, m); + } + // group_prerequisites // inline group_prerequisites:: diff --git a/libbuild2/test/rule.cxx b/libbuild2/test/rule.cxx index c4767cf..ef9adca 100644 --- a/libbuild2/test/rule.cxx +++ b/libbuild2/test/rule.cxx @@ -384,6 +384,8 @@ namespace build2 target_state rule:: perform_script (action a, const target& t, size_t pass_n) const { + context& ctx (t.ctx); + // First pass through. // if (pass_n != 0) @@ -433,7 +435,7 @@ namespace build2 const path& buildignore_file (rs.root_extra->buildignore_file); dir_path bl; - if (cast_false (rs.vars[var_forwarded])) + if (cast_false (rs.vars[ctx.var_forwarded])) { bl = bs.src_path () / wd.leaf (bs.out_path ()); clean_backlink (bl, verb_never); @@ -490,7 +492,7 @@ namespace build2 wait_guard wg; if (!dry_run) - wg = wait_guard (t.ctx, t.ctx.count_busy (), t[a].task_count); + wg = wait_guard (ctx, ctx.count_busy (), t[a].task_count); // Result vector. // @@ -538,7 +540,7 @@ namespace build2 { scope_state& r (res.back ()); - if (!sched.async (t.ctx.count_busy (), + if (!sched.async (ctx.count_busy (), t[a].task_count, [this] (const diag_frame* ds, scope_state& r, diff --git a/libbuild2/version/init.cxx b/libbuild2/version/init.cxx index faa6e38..1c123bf 100644 --- a/libbuild2/version/init.cxx +++ b/libbuild2/version/init.cxx @@ -37,6 +37,8 @@ namespace build2 tracer trace ("version::boot"); l5 ([&]{trace << "for " << rs;}); + context& ctx (rs.ctx); + // Extract the version from the manifest file. As well as summary and // url while at it. // @@ -67,7 +69,7 @@ namespace build2 { if (nv.name == "name") { - auto& pn (cast (rs.vars[var_project])); + auto& pn (cast (rs.vars[ctx.var_project])); if (nv.value != pn.string ()) { @@ -219,7 +221,7 @@ namespace build2 // Set all the version.* variables. // - auto& vp (rs.ctx.var_pool.rw (rs)); + auto& vp (ctx.var_pool.rw (rs)); auto set = [&vp, &rs] (const char* var, auto val) { @@ -228,8 +230,8 @@ namespace build2 rs.assign (v) = move (val); }; - if (!sum.empty ()) rs.assign (var_project_summary) = move (sum); - if (!url.empty ()) rs.assign (var_project_url) = move (url); + if (!sum.empty ()) rs.assign (ctx.var_project_summary) = move (sum); + if (!url.empty ()) rs.assign (ctx.var_project_url) = move (url); set ("version", v.string ()); // Project version (var_version). @@ -268,7 +270,7 @@ namespace build2 // Create the module. // - mod.reset (new module (cast (rs.vars[var_project]), + mod.reset (new module (cast (rs.vars[ctx.var_project]), move (v), committed, rewritten, @@ -294,6 +296,8 @@ namespace build2 if (!first) fail (l) << "multiple version module initializations"; + context& ctx (rs.ctx); + // Load in.base (in.* variables, in{} target type). // if (!cast_false (rs["in.base.loaded"])) @@ -320,7 +324,7 @@ namespace build2 if (!val) { - string p (cast (rs.vars[var_project]).string ()); + string p (cast (rs.vars[ctx.var_project]).string ()); p += '-'; p += v.string (); val = move (p); -- cgit v1.1