aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-12-04 12:41:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-12-04 12:41:32 +0200
commit398134d2b4d362f857de5d2c94942e919d0bc534 (patch)
tree03c5e1ce206a477fe41d344dae51b48aee73666b
parent2c8294b069f5df30d281e0f4f580f6f313a50eb2 (diff)
Implement better cross-hinting between c-family modules
-rw-r--r--build2/b.cxx1
-rw-r--r--build2/c/init.cxx4
-rw-r--r--build2/cc/common.hxx5
-rw-r--r--build2/cc/init.cxx52
-rw-r--r--build2/cc/init.hxx9
-rw-r--r--build2/cc/module.cxx127
-rw-r--r--build2/cxx/init.cxx4
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<path> ("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<module_base>&,
- bool first,
- bool,
- const variable_map& hints)
+ core_guess_init (scope& rs,
+ scope&,
+ const location& loc,
+ unique_ptr<module_base>&,
+ 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<bool> (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<string> ("cc.pattern") = cast<string> (l);
}
+ return true;
+ }
+
+ bool
+ core_config_init (scope& rs,
+ scope&,
+ const location& loc,
+ unique_ptr<module_base>&,
+ 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<bool> (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<module_base>&,
+ 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<bool> (rs["cc.core.config.loaded"]));
+ bool cc_loaded (cast_false<bool> (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<path> ("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<string> (rs[x_id]);
+ h.assign ("config.cc.target") = cast<target_triplet> (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<string> (rs["cc.id"]));
+ const auto& xv (cast<string> (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<target_triplet> (rs["cc.target"]));
+ const auto& xv (cast<target_triplet> (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<bool> (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<string> (rs[x_id]);
- h.assign ("config.cc.target") = cast<target_triplet> (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<string> (rs["cc.id"]));
- const auto& xv (cast<string> (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<target_triplet> (rs["cc.target"]));
- const auto& xv (cast<target_triplet> (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<path> ("config.cxx", true),