From 5035f4ef68922ac758b1e4734e67d73c9228010b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 22 Aug 2019 14:38:57 +0200 Subject: Introduce notion of build context All non-const global state is now in class context and we can now have multiple independent builds going on at the same time. --- libbuild2/config/init.cxx | 10 +- libbuild2/config/operation.cxx | 202 ++++++++++++++++++++++------------------- libbuild2/config/operation.hxx | 2 +- libbuild2/config/utility.cxx | 18 ++-- libbuild2/config/utility.hxx | 6 +- libbuild2/config/utility.txx | 2 +- 6 files changed, 126 insertions(+), 114 deletions(-) (limited to 'libbuild2/config') diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index b790569..6998017 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -29,8 +29,8 @@ namespace build2 l5 ([&]{trace << "for " << rs;}); - const string& mname (current_mname); - const string& oname (current_oname); + const string& mname (rs.ctx.current_mname); + const string& oname (rs.ctx.current_oname); // Only create the module if we are configuring or creating. This is a // bit tricky since the build2 core may not yet know if this is the @@ -80,7 +80,7 @@ namespace build2 assert (config_hints.empty ()); // We don't known any hints. - auto& vp (var_pool.rw (rs)); + auto& vp (rs.ctx.var_pool.rw (rs)); // Load config.build if one exists (we don't need to worry about // disfigure since we will never be init'ed). @@ -103,7 +103,7 @@ namespace build2 { // Assume missing version is 0. // - auto p (extract_variable (f, c_v)); + auto p (extract_variable (rs.ctx, f, c_v)); uint64_t v (p.second ? cast (p.first) : 0); if (v != module::version) @@ -126,7 +126,7 @@ namespace build2 // global scope similar to builtin rules. // { - auto& r (rs.global ().rules); + auto& r (rs.global_scope ().rules); r.insert ( configure_id, 0, "config.file", file_rule::instance); } diff --git a/libbuild2/config/operation.cxx b/libbuild2/config/operation.cxx index c3ce4b7..264eb93 100644 --- a/libbuild2/config/operation.cxx +++ b/libbuild2/config/operation.cxx @@ -28,12 +28,12 @@ namespace build2 // configure // static void - save_src_root (const scope& root) + save_src_root (const scope& rs) { - const dir_path& out_root (root.out_path ()); - const dir_path& src_root (root.src_path ()); + const dir_path& out_root (rs.out_path ()); + const dir_path& src_root (rs.src_path ()); - path f (out_root / root.root_extra->src_root_file); + path f (out_root / rs.root_extra->src_root_file); if (verb >= 2) text << "cat >" << f; @@ -57,12 +57,12 @@ namespace build2 } static void - save_out_root (const scope& root) + save_out_root (const scope& rs) { - const dir_path& out_root (root.out_path ()); - const dir_path& src_root (root.src_path ()); + const dir_path& out_root (rs.out_path ()); + const dir_path& src_root (rs.src_path ()); - path f (src_root / root.root_extra->out_root_file); + path f (src_root / rs.root_extra->out_root_file); if (verb) text << (verb >= 2 ? "cat >" : "save ") << f; @@ -88,14 +88,16 @@ namespace build2 using project_set = set; // Use pointers to get comparison. static void - save_config (const scope& root, const project_set& projects) + save_config (const scope& rs, const project_set& projects) { - path f (config_file (root)); + context& ctx (rs.ctx); + + path f (config_file (rs)); if (verb) text << (verb >= 2 ? "cat >" : "save ") << f; - const module& mod (*root.lookup_module (module::name)); + const module& mod (*rs.lookup_module (module::name)); try { @@ -107,7 +109,7 @@ namespace build2 ofs << "config.version = " << module::version << endl; - if (auto l = root.vars[var_amalgamation]) + if (auto l = rs.vars[ctx.var_amalgamation]) { const dir_path& d (cast (l)); @@ -130,10 +132,10 @@ namespace build2 { const variable& var (sv.var); - pair org (root.find_original (var)); + pair org (rs.find_original (var)); pair ovr (var.overrides == nullptr ? org - : root.find_override (var, org)); + : rs.find_override (var, org)); const lookup& l (ovr.first); // We definitely write values that are set on our root scope or @@ -144,7 +146,7 @@ namespace build2 if (!l.defined ()) continue; - if (!(l.belongs (root) || l.belongs (*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 @@ -162,7 +164,7 @@ namespace build2 // root. // bool found (false); - const scope* r (&root); + const scope* r (&rs); while ((r = r->parent_scope ()->root_scope ()) != nullptr) { if (l.belongs (*r)) @@ -307,14 +309,16 @@ namespace build2 } static void - configure_project (action a, const scope& root, project_set& projects) + configure_project (action a, const scope& rs, project_set& projects) { tracer trace ("configure_project"); - const dir_path& out_root (root.out_path ()); - const dir_path& src_root (root.src_path ()); + context& ctx (rs.ctx); + + const dir_path& out_root (rs.out_path ()); + const dir_path& src_root (rs.src_path ()); - if (!projects.insert (&root).second) + if (!projects.insert (&rs).second) { l5 ([&]{trace << "skipping already configured " << out_root;}); return; @@ -324,8 +328,8 @@ namespace build2 // if (out_root != src_root) { - mkdir_p (out_root / root.root_extra->build_dir); - mkdir (out_root / root.root_extra->bootstrap_dir, 2); + mkdir_p (out_root / rs.root_extra->build_dir); + mkdir (out_root / rs.root_extra->bootstrap_dir, 2); } // We distinguish between a complete configure and operation- @@ -338,11 +342,11 @@ namespace build2 // Save src-root.build unless out_root is the same as src. // if (out_root != src_root) - save_src_root (root); + save_src_root (rs); // Save config.build. // - save_config (root, projects); + save_config (rs, projects); } else { @@ -350,54 +354,56 @@ namespace build2 // Configure subprojects that have been loaded. // - if (auto l = root.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& nroot (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. // - if (nroot.out_path () != out_nroot) // This subproject not loaded. + if (nrs.out_path () != out_nroot) // This subproject not loaded. continue; - configure_project (a, nroot, projects); + configure_project (a, nrs, projects); } } } static void - configure_forward (const scope& root, project_set& projects) + configure_forward (const scope& rs, project_set& projects) { tracer trace ("configure_forward"); - const dir_path& out_root (root.out_path ()); - const dir_path& src_root (root.src_path ()); + context& ctx (rs.ctx); - if (!projects.insert (&root).second) + const dir_path& out_root (rs.out_path ()); + const dir_path& src_root (rs.src_path ()); + + if (!projects.insert (&rs).second) { l5 ([&]{trace << "skipping already configured " << src_root;}); return; } - mkdir (src_root / root.root_extra->bootstrap_dir, 2); // Make sure exists. - save_out_root (root); + mkdir (src_root / rs.root_extra->bootstrap_dir, 2); // Make sure exists. + save_out_root (rs); // Configure subprojects. Since we don't load buildfiles if configuring // a forward, we do it for all known subprojects. // - if (auto l = root.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& nroot (scopes.find (out_nroot)); - assert (nroot.out_path () == out_nroot); + const scope& nrs (ctx.scopes.find (out_nroot)); + assert (nrs.out_path () == out_nroot); - configure_forward (nroot, projects); + configure_forward (nrs, projects); } } } @@ -451,7 +457,7 @@ namespace build2 static void configure_load (const values& params, - scope& root, + scope& rs, const path& buildfile, const dir_path& out_base, const dir_path& src_base, @@ -463,19 +469,19 @@ namespace build2 // forwarding but in order to configure subprojects we have to // bootstrap them (similar to disfigure). // - create_bootstrap_inner (root); + create_bootstrap_inner (rs); - if (root.out_path () == root.src_path ()) - fail (l) << "forwarding to source directory " << root.src_path (); + if (rs.out_path () == rs.src_path ()) + fail (l) << "forwarding to source directory " << rs.src_path (); } else - load (params, root, buildfile, out_base, src_base, l); // Normal load. + load (params, rs, buildfile, out_base, src_base, l); // Normal load. } static void configure_search (const values& params, - const scope& root, - const scope& base, + const scope& rs, + const scope& bs, const path& bf, const target_key& tk, const location& l, @@ -486,10 +492,10 @@ namespace build2 // For forwarding we only collect the projects (again, similar to // disfigure). // - ts.push_back (&root); + ts.push_back (&rs); } else - search (params, root, base, bf, tk, l, ts); // Normal search. + search (params, rs, bs, bf, tk, l, ts); // Normal search. } static void @@ -515,8 +521,8 @@ namespace build2 { // Forward configuration. // - const scope& root (*static_cast (at.target)); - configure_forward (root, projects); + const scope& rs (*static_cast (at.target)); + configure_forward (rs, projects); continue; } @@ -539,6 +545,8 @@ namespace build2 if (rs == nullptr) fail << "out of project target " << t; + context& ctx (t.ctx); + const operations& ops (rs->root_extra->operations); for (operation_id id (default_id + 1); // Skip default_id. @@ -552,9 +560,9 @@ namespace build2 if (oif->id != id) continue; - set_current_oif (*oif); + ctx.current_operation (*oif); - phase_lock pl (run_phase::match); + phase_lock pl (ctx, run_phase::match); match (action (configure_id, id), t); } } @@ -586,14 +594,16 @@ namespace build2 // static bool - disfigure_project (action a, const scope& root, project_set& projects) + disfigure_project (action a, const scope& rs, project_set& projects) { tracer trace ("disfigure_project"); - const dir_path& out_root (root.out_path ()); - const dir_path& src_root (root.src_path ()); + context& ctx (rs.ctx); + + const dir_path& out_root (rs.out_path ()); + const dir_path& src_root (rs.src_path ()); - if (!projects.insert (&root).second) + if (!projects.insert (&rs).second) { l5 ([&]{trace << "skipping already disfigured " << out_root;}); return false; @@ -604,16 +614,16 @@ namespace build2 // Disfigure subprojects. Since we don't load buildfiles during // disfigure, we do it for all known subprojects. // - if (auto l = root.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& nroot (scopes.find (out_nroot)); - assert (nroot.out_path () == out_nroot); // See disfigure_load(). + const scope& nrs (ctx.scopes.find (out_nroot)); + assert (nrs.out_path () == out_nroot); // See disfigure_load(). - r = disfigure_project (a, nroot, projects) || r; + r = disfigure_project (a, nrs, projects) || r; // We use mkdir_p() to create the out_root of a subproject // which means there could be empty parent directories left @@ -625,7 +635,7 @@ namespace build2 !d.empty (); d = d.directory ()) { - rmdir_status s (rmdir (out_root / d, 2)); + rmdir_status s (rmdir (ctx, out_root / d, 2)); if (s == rmdir_status::not_empty) break; // No use trying do remove parent ones. @@ -643,21 +653,21 @@ namespace build2 { l5 ([&]{trace << "completely disfiguring " << out_root;}); - r = rmfile (config_file (root)) || r; + r = rmfile (ctx, config_file (rs)) || r; if (out_root != src_root) { - r = rmfile (out_root / root.root_extra->src_root_file, 2) || r; + r = rmfile (ctx, out_root / rs.root_extra->src_root_file, 2) || r; // Clean up the directories. // // Note: try to remove the root/ hooks directory if it is empty. // - r = rmdir (out_root / root.root_extra->root_dir, 2) || r; - r = rmdir (out_root / root.root_extra->bootstrap_dir, 2) || r; - r = rmdir (out_root / root.root_extra->build_dir, 2) || r; + r = rmdir (ctx, out_root / rs.root_extra->root_dir, 2) || r; + r = rmdir (ctx, out_root / rs.root_extra->bootstrap_dir, 2) || r; + r = rmdir (ctx, out_root / rs.root_extra->build_dir, 2) || r; - switch (rmdir (out_root)) + switch (rmdir (ctx, out_root)) { case rmdir_status::not_empty: { @@ -687,16 +697,18 @@ namespace build2 } static bool - disfigure_forward (const scope& root, project_set& projects) + disfigure_forward (const scope& rs, project_set& projects) { // Pretty similar logic to disfigure_project(). // tracer trace ("disfigure_forward"); - const dir_path& out_root (root.out_path ()); - const dir_path& src_root (root.src_path ()); + context& ctx (rs.ctx); + + const dir_path& out_root (rs.out_path ()); + const dir_path& src_root (rs.src_path ()); - if (!projects.insert (&root).second) + if (!projects.insert (&rs).second) { l5 ([&]{trace << "skipping already disfigured " << src_root;}); return false; @@ -704,23 +716,23 @@ namespace build2 bool r (false); - if (auto l = root.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& nroot (scopes.find (out_nroot)); - assert (nroot.out_path () == out_nroot); + const scope& nrs (ctx.scopes.find (out_nroot)); + assert (nrs.out_path () == out_nroot); - r = disfigure_forward (nroot, projects) || r; + r = disfigure_forward (nrs, projects) || r; } } // Remove the out-root.build file and try to remove the bootstrap/ // directory if it is empty. // - r = rmfile (src_root / root.root_extra->out_root_file) || r; - r = rmdir (src_root / root.root_extra->bootstrap_dir, 2) || r; + r = rmfile (ctx, src_root / rs.root_extra->out_root_file) || r; + r = rmdir (ctx, src_root / rs.root_extra->bootstrap_dir, 2) || r; return r; } @@ -757,14 +769,14 @@ namespace build2 static void disfigure_search (const values&, - const scope& root, + const scope& rs, const scope&, const path&, const target_key&, const location&, action_targets& ts) { - ts.push_back (&root); + ts.push_back (&rs); } static void @@ -790,23 +802,23 @@ namespace build2 // for (const action_target& at: ts) { - const scope& root (*static_cast (at.target)); + const scope& rs (*static_cast (at.target)); if (!(fwd - ? disfigure_forward ( root, projects) - : disfigure_project (a, root, projects))) + ? disfigure_forward ( rs, projects) + : disfigure_project (a, rs, projects))) { // Create a dir{$out_root/} target to signify the project's root in // diagnostics. Not very clean but seems harmless. // target& t ( - targets.insert (dir::static_type, - fwd ? root.src_path () : root.out_path (), - dir_path (), // Out tree. - "", - nullopt, - true, // Implied. - trace).first); + rs.ctx.targets.insert (dir::static_type, + fwd ? rs.src_path () : rs.out_path (), + dir_path (), // Out tree. + "", + nullopt, + true, // Implied. + trace).first); if (verb != 0 && diag >= 2) info << diag_done (a, t); @@ -836,7 +848,7 @@ namespace build2 // create // static void - save_config (const dir_path& d, const variable_overrides& var_ovs) + save_config (context& ctx, const dir_path& d) { // Since there aren't any sub-projects yet, any config.import.* values // that the user may want to specify won't be saved in config.build. So @@ -846,13 +858,13 @@ namespace build2 // going to do is bootstrap the newly created project, similar to the // way main() does it. // - scope& gs (*scope::global_); + scope& gs (ctx.global_scope.rw ()); scope& rs (load_project (gs, d, d, false /* fwd */, false /* load */)); module& m (*rs.lookup_module (module::name)); // Save all the global config.import.* variables. // - variable_pool& vp (var_pool.rw (rs)); + variable_pool& vp (ctx.var_pool.rw (rs)); for (auto p (gs.vars.find_namespace (vp.insert ("config.import"))); p.first != p.second; ++p.first) @@ -869,7 +881,7 @@ namespace build2 // Now project-specific. For now we just save all of them and let // save_config() above weed out the ones that don't apply. // - for (const variable_override& vo: var_ovs) + for (const variable_override& vo: ctx.var_overrides) { const variable& var (vo.var); @@ -879,7 +891,7 @@ namespace build2 } const string& - preprocess_create (const variable_overrides& var_ovs, + preprocess_create (context& ctx, values& params, vector_view& spec, bool lifted, @@ -916,7 +928,7 @@ namespace build2 fail (l) << "invalid module name: " << e.what (); } - current_oname = empty_string; // Make sure valid. + ctx.current_oname = empty_string; // Make sure valid. // Now handle each target in each operation spec. // @@ -986,7 +998,7 @@ namespace build2 true, /* buildfile */ "the create meta-operation"); - save_config (d, var_ovs); + save_config (ctx, d); } } diff --git a/libbuild2/config/operation.hxx b/libbuild2/config/operation.hxx index 0a88f96..8b2a29d 100644 --- a/libbuild2/config/operation.hxx +++ b/libbuild2/config/operation.hxx @@ -18,7 +18,7 @@ namespace build2 extern const meta_operation_info mo_disfigure; const string& - preprocess_create (const variable_overrides&, + preprocess_create (context&, values&, vector_view&, bool, diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx index 746639d..355e896 100644 --- a/libbuild2/config/utility.cxx +++ b/libbuild2/config/utility.cxx @@ -46,7 +46,7 @@ namespace build2 } } - if (l.defined () && current_mif->id == configure_id) + if (l.defined () && r.ctx.current_mif->id == configure_id) save_variable (r, var); return pair (l, n); @@ -55,7 +55,7 @@ namespace build2 lookup optional (scope& r, const variable& var) { - if (current_mif->id == configure_id) + if (r.ctx.current_mif->id == configure_id) save_variable (r, var); auto l (r[var]); @@ -75,7 +75,7 @@ namespace build2 // any original values, they will be "visible"; see find_override() for // details. // - const variable& vns (var_pool.rw (r).insert ("config." + n)); + const variable& vns (r.ctx.var_pool.rw (r).insert ("config." + n)); for (scope* s (&r); s != nullptr; s = s->parent_scope ()) { for (auto p (s->vars.find_namespace (vns)); @@ -101,9 +101,9 @@ namespace build2 // Pattern-typed in boot() as bool. // const variable& var ( - var_pool.rw (rs).insert ("config." + n + ".configured")); + rs.ctx.var_pool.rw (rs).insert ("config." + n + ".configured")); - if (current_mif->id == configure_id) + if (rs.ctx.current_mif->id == configure_id) save_variable (rs, var); auto l (rs[var]); // Include inherited values. @@ -116,9 +116,9 @@ namespace build2 // Pattern-typed in boot() as bool. // const variable& var ( - var_pool.rw (rs).insert ("config." + n + ".configured")); + rs.ctx.var_pool.rw (rs).insert ("config." + n + ".configured")); - if (current_mif->id == configure_id) + if (rs.ctx.current_mif->id == configure_id) save_variable (rs, var); value& x (rs.assign (var)); @@ -135,7 +135,7 @@ namespace build2 void save_variable (scope& r, const variable& var, uint64_t flags) { - if (current_mif->id != configure_id) + if (r.ctx.current_mif->id != configure_id) return; // The project might not be using the config module. But then how @@ -148,7 +148,7 @@ namespace build2 void save_module (scope& r, const char* name, int prio) { - if (current_mif->id != configure_id) + if (r.ctx.current_mif->id != configure_id) return; if (module* m = r.lookup_module (module::name)) diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx index a063693..b1995b6 100644 --- a/libbuild2/config/utility.hxx +++ b/libbuild2/config/utility.hxx @@ -58,7 +58,7 @@ namespace build2 uint64_t save_flags = 0) { return required ( - root, var_pool[name], default_value, override, save_flags); + root, root.ctx.var_pool[name], default_value, override, save_flags); } inline pair @@ -86,7 +86,7 @@ namespace build2 inline pair omitted (scope& root, const string& name) { - return omitted (root, var_pool[name]); + return omitted (root, root.ctx.var_pool[name]); } // Set, if necessary, an optional config.* variable. In particular, an @@ -105,7 +105,7 @@ namespace build2 inline lookup optional (scope& root, const string& name) { - return optional (root, var_pool[name]); + return optional (root, root.ctx.var_pool[name]); } // Check whether there are any variables specified from the config diff --git a/libbuild2/config/utility.txx b/libbuild2/config/utility.txx index 841c408..9c1455f 100644 --- a/libbuild2/config/utility.txx +++ b/libbuild2/config/utility.txx @@ -19,7 +19,7 @@ namespace build2 { // Note: see also omitted() if changing anything here. - if (current_mif->id == configure_id) + if (root.ctx.current_mif->id == configure_id) save_variable (root, var, save_flags); pair org (root.find_original (var)); -- cgit v1.1