diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2019-08-22 14:38:57 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2019-08-23 18:14:07 +0200 |
commit | 5035f4ef68922ac758b1e4734e67d73c9228010b (patch) | |
tree | 271fdd5b1d6e995a058d97aacb3ac90a538d9ff1 /libbuild2/config/operation.cxx | |
parent | 8793941652d6aa1c3d02b2f87f691e6d06254b7d (diff) |
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.
Diffstat (limited to 'libbuild2/config/operation.cxx')
-rw-r--r-- | libbuild2/config/operation.cxx | 202 |
1 files changed, 107 insertions, 95 deletions
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<const scope*>; // 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<const module> (module::name)); + const module& mod (*rs.lookup_module<const 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<dir_path> (l)); @@ -130,10 +132,10 @@ namespace build2 { const variable& var (sv.var); - pair<lookup, size_t> org (root.find_original (var)); + pair<lookup, size_t> org (rs.find_original (var)); pair<lookup, size_t> 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<subprojects> (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<subprojects> (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<const scope*> (at.target)); - configure_forward (root, projects); + const scope& rs (*static_cast<const scope*> (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<subprojects> (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<subprojects> (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<const scope*> (at.target)); + const scope& rs (*static_cast<const scope*> (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> (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<opspec>& 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); } } |