From 398134d2b4d362f857de5d2c94942e919d0bc534 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 4 Dec 2017 12:41:32 +0200 Subject: Implement better cross-hinting between c-family modules --- build2/b.cxx | 1 + build2/c/init.cxx | 4 ++ build2/cc/common.hxx | 5 ++ build2/cc/init.cxx | 52 +++++++++++++++------ build2/cc/init.hxx | 9 ++++ build2/cc/module.cxx | 127 ++++++++++++++++++++++++++++++++------------------- build2/cxx/init.cxx | 4 ++ 7 files changed, 141 insertions(+), 61 deletions(-) diff --git a/build2/b.cxx b/build2/b.cxx index 9ad21bc..a88d1c0 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -324,6 +324,7 @@ main (int argc, char* argv[]) bm["bin.rc"] = mf {nullptr, &bin::rc_init}; bm["cc.core.vars"] = mf {nullptr, &cc::core_vars_init}; + bm["cc.core.guess"] = mf {nullptr, &cc::core_guess_init}; bm["cc.core.config"] = mf {nullptr, &cc::core_config_init}; bm["cc.core"] = mf {nullptr, &cc::core_init}; bm["cc.config"] = mf {nullptr, &cc::config_init}; diff --git a/build2/c/init.cxx b/build2/c/init.cxx index 59c6a40..3ab91d4 100644 --- a/build2/c/init.cxx +++ b/build2/c/init.cxx @@ -105,6 +105,8 @@ namespace build2 return r; } + static const char* const hinters[] = {"cxx", nullptr}; + // See cc::module for details on guess_init vs config_init. // bool @@ -141,6 +143,8 @@ namespace build2 "gcc", ".i", + hinters, + // Note: some overridable, some not. // v.insert ("config.c", true), diff --git a/build2/cc/common.hxx b/build2/cc/common.hxx index ba14471..ad550e1 100644 --- a/build2/cc/common.hxx +++ b/build2/cc/common.hxx @@ -34,6 +34,11 @@ namespace build2 const char* x_default; // Compiler default ("gcc", "g++"). const char* x_pext; // Preprocessed source extension (".i", ".ii"). + // Array of modules that can hint us the toolchain, terminate with + // NULL. + // + const char* const* x_hinters; + const variable& config_x; const variable& config_x_poptions; const variable& config_x_coptions; diff --git a/build2/cc/init.cxx b/build2/cc/init.cxx index 3108d6d..90821ae 100644 --- a/build2/cc/init.cxx +++ b/build2/cc/init.cxx @@ -138,15 +138,15 @@ namespace build2 } bool - core_config_init (scope& rs, - scope&, - const location& loc, - unique_ptr&, - bool first, - bool, - const variable_map& hints) + core_guess_init (scope& rs, + scope&, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) { - tracer trace ("cc::core_config_init"); + tracer trace ("cc::core_guess_init"); l5 ([&]{trace << "for " << rs.out_path ();}); assert (first); @@ -156,13 +156,6 @@ namespace build2 if (!cast_false (rs["cc.core.vars.loaded"])) load_module (rs, rs, "cc.core.vars", loc); - // Configure. - // - - // Adjust module priority (compiler). - // - config::save_module (rs, "cc", 250); - // config.cc.id // { @@ -199,6 +192,35 @@ namespace build2 rs.assign ("cc.pattern") = cast (l); } + return true; + } + + bool + core_config_init (scope& rs, + scope&, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("cc::core_config_init"); + l5 ([&]{trace << "for " << rs.out_path ();}); + + assert (first); + + // Load cc.core.guess. + // + if (!cast_false (rs["cc.core.guess.loaded"])) + load_module (rs, rs, "cc.core.guess", loc); + + // Configure. + // + + // Adjust module priority (compiler). + // + config::save_module (rs, "cc", 250); + // Note that we are not having a config report since it will just // duplicate what has already been printed by the hinting module. diff --git a/build2/cc/init.hxx b/build2/cc/init.hxx index 9eab424..38d8753 100644 --- a/build2/cc/init.hxx +++ b/build2/cc/init.hxx @@ -24,6 +24,15 @@ namespace build2 const variable_map&); bool + core_guess_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool core_config_init (scope&, scope&, const location&, diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 92a04a7..74238c3 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -27,11 +27,11 @@ namespace build2 namespace cc { void config_module:: - guess (scope& rs, const location&, const variable_map&) + guess (scope& rs, const location& loc, const variable_map&) { tracer trace (x, "guess_init"); - bool cc_loaded (cast_false (rs["cc.core.config.loaded"])); + bool cc_loaded (cast_false (rs["cc.core.guess.loaded"])); // Adjust module priority (compiler). Also order cc module before us // (we don't want to use priorities for that in case someone manages @@ -55,9 +55,35 @@ namespace build2 if (!p.first) { - // If someone already loaded cc.core.config then use its toolchain - // id and (optional) pattern to guess an appropriate default (e.g., - // for {gcc, *-4.9} we will get g++-4.9). + // If there is a config.x value for one of the modules that can hint + // us the toolchain, load it's .guess module. This makes sure that the + // order in which we load the modules is unimportant and that the user + // can specify the toolchain using any of the config.x values. + // + if (!cc_loaded) + { + auto& vp (var_pool.rw (rs)); + + for (const char* const* pm (x_hinters); *pm != nullptr; ++pm) + { + string m (*pm); + + // Must be the same as in module's init(). + // + const variable& v (vp.insert ("config." + m, true)); + + if (rs[v].defined ()) + { + load_module (rs, rs, m + ".guess", loc); + cc_loaded = true; + break; + } + } + } + + // If cc.core.config is already loaded then use its toolchain id and + // (optional) pattern to guess an appropriate default (e.g., for {gcc, + // *-4.9} we will get g++-4.9). // path d (cc_loaded ? guess_default (x_lang, @@ -116,7 +142,7 @@ namespace build2 } } - // Assign value to variables that describe the compile. + // Assign value to variables that describe the compiler. // rs.assign (x_id) = ci.id.string (); rs.assign (x_id_type) = ci.id.type; @@ -142,6 +168,55 @@ namespace build2 rs.assign (x_target) = move (tt); new_ = p.second; + + // Load cc.core.guess. + // + if (!cc_loaded) + { + // Prepare configuration hints. + // + variable_map h; + + // Note that all these variables have already been registered. + // + h.assign ("config.cc.id") = cast (rs[x_id]); + h.assign ("config.cc.target") = cast (rs[x_target]); + + if (!ci.cc_pattern.empty ()) + h.assign ("config.cc.pattern") = ci.cc_pattern; + + load_module (rs, rs, "cc.core.guess", loc, false, h); + } + else + { + // If cc.core.guess is already loaded, verify its configuration + // matched ours since it could have been loaded by another c-family + // module. + // + // Note that we don't require that patterns match. Presumably, if the + // toolchain id and target are the same, then where exactly the tools + // come from doesn't really matter. + // + { + const auto& cv (cast (rs["cc.id"])); + const auto& xv (cast (rs[x_id])); + + if (cv != xv) + fail (loc) << "cc and " << x << " module toolchain mismatch" << + info << "cc.id is " << cv << + info << x_id.name << " is " << xv; + } + + { + const auto& cv (cast (rs["cc.target"])); + const auto& xv (cast (rs[x_target])); + + if (cv != xv) + fail (loc) << "cc and " << x << " module target mismatch" << + info << "cc.target is " << cv << + info << x_target.name << " is " << xv; + } + } } void config_module:: @@ -318,53 +393,13 @@ namespace build2 // if (!cast_false (rs["cc.core.config.loaded"])) { - // Prepare configuration hints. - // variable_map h; - // Note that all these variables have already been registered. - // - h.assign ("config.cc.id") = cast (rs[x_id]); - h.assign ("config.cc.target") = cast (rs[x_target]); - - if (!ci.cc_pattern.empty ()) - h.assign ("config.cc.pattern") = move (ci.cc_pattern); - if (!ci.bin_pattern.empty ()) h.assign ("config.bin.pattern") = move (ci.bin_pattern); load_module (rs, rs, "cc.core.config", loc, false, h); } - else - { - // If cc.core.config is already loaded, verify its configuration - // matched ours since it could have been loaded by another c-family - // module. - // - // Note that we don't require that patterns match. Presumably, if the - // toolchain id and target are the same, then where exactly the tools - // come from doesn't really matter. - // - { - const auto& cv (cast (rs["cc.id"])); - const auto& xv (cast (rs[x_id])); - - if (cv != xv) - fail (loc) << "cc and " << x << " module toolchain mismatch" << - info << "cc.id is " << cv << - info << x_id.name << " is " << xv; - } - - { - const auto& cv (cast (rs["cc.target"])); - const auto& xv (cast (rs[x_target])); - - if (cv != xv) - fail (loc) << "cc and " << x << " module target mismatch" << - info << "cc.target is " << cv << - info << x_target.name << " is " << xv; - } - } } void module:: diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx index 9f2d912..ea3bf79 100644 --- a/build2/cxx/init.cxx +++ b/build2/cxx/init.cxx @@ -290,6 +290,8 @@ namespace build2 return r; } + static const char* const hinters[] = {"c", nullptr}; + // See cc::module for details on guess_init vs config_init. // bool @@ -326,6 +328,8 @@ namespace build2 "g++", ".ii", + hinters, + // Note: some overridable, some not. // v.insert ("config.cxx", true), -- cgit v1.1