From 83b5af87efef571b707fc1f409f22571a9f5054c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 12 Aug 2016 16:23:37 +0200 Subject: Add support for ordering modules in config.build --- build2/bin/module.cxx | 4 ++++ build2/cc/init.cxx | 4 ++++ build2/cc/module.cxx | 19 ++++++++++++++++++- build2/cli/module.cxx | 4 ++++ build2/config/module | 18 +++++++++++++++--- build2/config/module.cxx | 22 ++++++++++++++-------- build2/config/operation.cxx | 7 +++---- build2/config/utility | 5 +++++ build2/config/utility.cxx | 10 ++++++++++ build2/dist/module.cxx | 6 ++++++ build2/install/module.cxx | 9 +++++++-- build2/test/module.cxx | 6 ++++++ build2/types | 2 +- 13 files changed, 97 insertions(+), 19 deletions(-) diff --git a/build2/bin/module.cxx b/build2/bin/module.cxx index 3a3f612..89f20af 100644 --- a/build2/bin/module.cxx +++ b/build2/bin/module.cxx @@ -74,6 +74,10 @@ namespace build2 using config::required; using config::optional; + // Adjust module priority (binutils). + // + config::save_module (r, "bin", 350); + // The idea here is as follows: if we already have one of // the bin.* variables set, then we assume this is static // project configuration and don't bother setting the diff --git a/build2/cc/init.cxx b/build2/cc/init.cxx index 80e5027..5f8e2fb 100644 --- a/build2/cc/init.cxx +++ b/build2/cc/init.cxx @@ -87,6 +87,10 @@ namespace build2 // if (first) { + // Adjust module priority (compiler). + // + config::save_module (r, "cc", 250); + // config.cc.id // { diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 4b51905..74c07e2 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -43,6 +43,15 @@ namespace build2 if (first) { + // Adjust module priority (compiler). Also order cc module before us + // (we don't want to use priorities for that in case someone manages + // to slot in-between). + // + if (!cc_loaded) + config::save_module (r, "cc", 250); + + config::save_module (r, x, 250); + const variable& config_c_coptions (var_pool["config.cc.coptions"]); // config.x @@ -66,7 +75,15 @@ namespace build2 cast_null (r["cc.pattern"])) : path (x_default)); - auto p1 (config::required (r, config_x, d)); + // If this value was hinted, save it as commented out so that if the + // user changes the source of the pattern, this one will get updated + // as well. + // + auto p1 (config::required (r, + config_x, + d, + false, + cc_loaded ? config::save_commented : 0)); p.first = &p1.first.get (); p.second = p1.second; } diff --git a/build2/cli/module.cxx b/build2/cli/module.cxx index a9bed86..ef9c2f8 100644 --- a/build2/cli/module.cxx +++ b/build2/cli/module.cxx @@ -157,6 +157,10 @@ namespace build2 return string (); // Not found. }; + // Adjust module priority (code generator). + // + config::save_module (rs, "cli", 150); + string ver; // Empty means unconfigured. path cli ("cli"); // Default. bool nv (false); // New value. diff --git a/build2/config/module b/build2/config/module index 7360cf6..21a7e28 100644 --- a/build2/config/module +++ b/build2/config/module @@ -5,6 +5,7 @@ #ifndef BUILD2_CONFIG_MODULE #define BUILD2_CONFIG_MODULE +#include #include // find_if() #include @@ -49,15 +50,26 @@ namespace build2 struct saved_modules: butl::prefix_map { - vector sequence; + // Priority order with INT32_MIN being the highest. Modules with the + // same priority are saved in the order inserted. + // + // Generally, the idea is that we want higher-level modules at the top + // of the file since that's the configuration that we usualy want to + // change. So we have the following priority bands/defaults: + // + // 101-200/150 - code generators (e.g., yacc, bison) + // 201-300/250 - compilers (e.g., C, C++), + // 301-400/350 - binutils (ar, ld) + // + std::multimap order; iterator - insert (string name) + insert (string name, int prio = 0) { auto p (emplace (move (name), saved_variables ())); if (p.second) - sequence.push_back (p.first); + order.emplace (prio, p.first); return p.first; } diff --git a/build2/config/module.cxx b/build2/config/module.cxx index d4b9b49..de106b7 100644 --- a/build2/config/module.cxx +++ b/build2/config/module.cxx @@ -11,6 +11,7 @@ #include // file_exists() #include +#include #include using namespace std; @@ -23,17 +24,17 @@ namespace build2 const string module::name ("config"); void - boot (scope& root, const location&, unique_ptr&) + boot (scope& rs, const location&, unique_ptr&) { tracer trace ("config::boot"); - const dir_path& out_root (root.out_path ()); + const dir_path& out_root (rs.out_path ()); l5 ([&]{trace << "for " << out_root;}); // Register meta-operations. // - root.meta_operations.insert (configure_id, configure); - root.meta_operations.insert (disfigure_id, disfigure); + rs.meta_operations.insert (configure_id, configure); + rs.meta_operations.insert (disfigure_id, disfigure); // Load config.build if one exists. // @@ -45,11 +46,11 @@ namespace build2 path f (out_root / config_file); if (file_exists (f)) - source (f, root, root); + source (f, rs, rs); } bool - init (scope& root, + init (scope& rs, scope&, const location& l, unique_ptr& mod, @@ -65,7 +66,7 @@ namespace build2 return true; } - l5 ([&]{trace << "for " << root.out_path ();}); + l5 ([&]{trace << "for " << rs.out_path ();}); assert (config_hints.empty ()); // We don't known any hints. @@ -74,6 +75,11 @@ namespace build2 if (current_mif->id == configure_id) mod.reset (new module); + // Adjust priority for the import pseudo-module so that config.import.* + // values come first in config.build. + // + config::save_module (rs, "import", INT32_MIN); + // Register alias and fallback rule for the configure meta-operation. // { @@ -83,7 +89,7 @@ namespace build2 global_scope->rules.insert ( configure_id, 0, "config.file", file_rule::instance); - auto& r (root.rules); + auto& r (rs.rules); r.insert (configure_id, 0, "config", fallback_rule::instance); r.insert (configure_id, 0, "config.file", fallback_rule::instance); diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx index 89ddcfb..ca2d559 100644 --- a/build2/config/operation.cxx +++ b/build2/config/operation.cxx @@ -93,11 +93,10 @@ namespace build2 // names storage; - for (const saved_modules::const_iterator& i: - mod.saved_modules.sequence) + for (auto p: mod.saved_modules.order) { - const string& sname (i->first); - const saved_variables& svars (i->second); + const string& sname (p.second->first); + const saved_variables& svars (p.second->second); bool first (true); // Separate modules with a blank line. for (const saved_variable& sv: svars) diff --git a/build2/config/utility b/build2/config/utility index 2be2842..d11a38b 100644 --- a/build2/config/utility +++ b/build2/config/utility @@ -132,6 +132,11 @@ namespace build2 void save_variable (scope& root, const variable&, uint64_t flags = 0); + + // Establish module order/priority. See config::module for details. + // + void + save_module (scope& root, const char* name, int prio = 0); } } diff --git a/build2/config/utility.cxx b/build2/config/utility.cxx index b73e852..45417f1 100644 --- a/build2/config/utility.cxx +++ b/build2/config/utility.cxx @@ -170,5 +170,15 @@ namespace build2 assert (j->flags == flags); } } + + void + save_module (scope& r, const char* name, int prio) + { + if (current_mif->id != configure_id) + return; + + if (module* m = r.modules.lookup (module::name)) + m->saved_modules.insert (string ("config.") += name, prio); + } } } diff --git a/build2/dist/module.cxx b/build2/dist/module.cxx index eed9562..2da75c4 100644 --- a/build2/dist/module.cxx +++ b/build2/dist/module.cxx @@ -91,6 +91,12 @@ namespace build2 // bool s (config::specified (r, "config.dist")); + // Adjust module priority so that the config.dist.* values are saved at + // the end of config.build. + // + if (s) + config::save_module (r, "dist", INT32_MAX); + // dist.root // { diff --git a/build2/install/module.cxx b/build2/install/module.cxx index ad2af6c..18ce2ad 100644 --- a/build2/install/module.cxx +++ b/build2/install/module.cxx @@ -156,7 +156,6 @@ namespace build2 // // Note that the set_dir() calls below enter some more. // - if (first) { auto& v (var_pool); @@ -177,11 +176,17 @@ namespace build2 // must be explicitly specified or the installer will complain // if and when we try to install. // - if (first) { using build2::path; bool s (config::specified (r, "config.install")); + + // Adjust module priority so that the (numerous) config.install.* + // values are saved at the end of config.build. + // + if (s) + config::save_module (r, "install", INT32_MAX); + const string& n (cast (r["project"])); set_dir (s, r, "root", abs_dir_path (), false, "", "755", path ("install")); diff --git a/build2/test/module.cxx b/build2/test/module.cxx index 3b5cf7b..83ccf3c 100644 --- a/build2/test/module.cxx +++ b/build2/test/module.cxx @@ -74,6 +74,12 @@ namespace build2 //@@ TODO: Need ability to specify extra diff options (e.g., // --strip-trailing-cr, now hardcoded). + // Adjust module priority so that the config.test.* values are saved at + // the end of config.build. + // + // if (s) + // config::save_module (r, "test", INT32_MAX); + // Register rules. // { diff --git a/build2/types b/build2/types index 8ccbd13..e3aa1b1 100644 --- a/build2/types +++ b/build2/types @@ -11,7 +11,7 @@ #include // unique_ptr, shared_ptr #include // pair, move() #include // size_t, nullptr_t -#include // uint{8,16,32,64}_t +#include // uint{8,16,32,64}_t, *_MIN, *_MAX #include #include #include // function, reference_wrapper -- cgit v1.1