aboutsummaryrefslogtreecommitdiff
path: root/build2/cc/module.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-08-12 12:46:21 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-08-12 17:04:22 +0200
commit0fd7815cbc6557811df4f1b6ffb40461474b8534 (patch)
treef67b2d8a94f85027b3f1c98c4bf9acadd4b27d56 /build2/cc/module.cxx
parent9fa5f73d00905568e8979d0c93ec4a8f645c81d5 (diff)
Implement c/cxx toolchain cross-hinting
Diffstat (limited to 'build2/cc/module.cxx')
-rw-r--r--build2/cc/module.cxx96
1 files changed, 68 insertions, 28 deletions
diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx
index 3a7dad2..4b51905 100644
--- a/build2/cc/module.cxx
+++ b/build2/cc/module.cxx
@@ -35,9 +35,11 @@ namespace build2
{
tracer trace (x, "config_init");
+ bool cc_loaded (cast_false<bool> (b["cc.config.loaded"]));
+
// Configure.
//
- string pattern; // Toolchain pattern.
+ compiler_info ci; // For program patterns.
if (first)
{
@@ -45,33 +47,69 @@ namespace build2
// config.x
//
- auto p (config::required (r, config_x, path (x_default)));
+
+ // Normally we will have a persistent configuration and computing the
+ // default value every time will be a waste. So try without a default
+ // first.
+ //
+ auto p (config::required (r, config_x));
+
+ if (p.first == nullptr)
+ {
+ // If someone already loaded cc.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).
+ //
+ path d (cc_loaded
+ ? guess_default (x_lang,
+ cast<string> (r["cc.id"]),
+ cast_null<string> (r["cc.pattern"]))
+ : path (x_default));
+
+ auto p1 (config::required (r, config_x, d));
+ p.first = &p1.first.get ();
+ p.second = p1.second;
+ }
// Figure out which compiler we are dealing with, its target, etc.
//
- const path& xc (cast<path> (p.first));
- compiler_info ci (
- guess (x_lang,
- xc,
- cast_null<strings> (r[config_c_coptions]),
- cast_null<strings> (r[config_x_coptions])));
+ const path& xc (cast<path> (*p.first));
+ ci = guess (x_lang,
+ xc,
+ cast_null<strings> (r[config_c_coptions]),
+ cast_null<strings> (r[config_x_coptions]));
// If this is a new value (e.g., we are configuring), then print the
// report at verbosity level 2 and up (-v).
//
if (verb >= (p.second ? 2 : 3))
{
- text << x << ' ' << project (r) << '@' << r.out_path () << '\n'
+ diag_record dr (text);
+
+ {
+ dr << x << ' ' << project (r) << '@' << r.out_path () << '\n'
<< " " << left << setw (11) << x << xc << '\n'
<< " id " << ci.id << '\n'
<< " version " << ci.version.string << '\n'
<< " major " << ci.version.major << '\n'
<< " minor " << ci.version.minor << '\n'
- << " patch " << ci.version.patch << '\n'
- << " build " << ci.version.build << '\n'
- << " signature " << ci.signature << '\n'
- << " checksum " << ci.checksum << '\n'
- << " target " << ci.target;
+ << " patch " << ci.version.patch << '\n';
+ }
+
+ if (!ci.version.build.empty ())
+ dr << " build " << ci.version.build << '\n';
+
+ {
+ dr << " signature " << ci.signature << '\n'
+ << " target " << ci.target << '\n';
+ }
+
+ if (!ci.cc_pattern.empty ()) // bin_pattern printed by bin
+ dr << " pattern " << ci.cc_pattern << '\n';
+
+ {
+ dr << " checksum " << ci.checksum;
+ }
}
r.assign (x_id) = ci.id.string ();
@@ -87,8 +125,6 @@ namespace build2
r.assign (x_signature) = move (ci.signature);
r.assign (x_checksum) = move (ci.checksum);
- pattern = move (ci.pattern);
-
// Split/canonicalize the target. First see if the user asked us to
// use config.sub.
//
@@ -158,7 +194,7 @@ namespace build2
// Load cc.config.
//
- if (!cast_false<bool> (b["cc.config.loaded"]))
+ if (!cc_loaded)
{
// Prepare configuration hints. They are only used on the first load
// of cc.config so we only populate them on our first load.
@@ -168,8 +204,12 @@ namespace build2
{
h.assign ("config.cc.id") = cast<string> (r[x_id]);
h.assign ("config.cc.target") = cast<string> (r[x_target]);
- if (!pattern.empty ())
- h.assign ("config.cc.pattern") = move (pattern);
+
+ 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 ("cc.config", r, b, loc, false, h);
@@ -179,24 +219,24 @@ namespace build2
// If cc.config is already loaded, verify its configuration matched
// ours since it could have been loaded by another c-family module.
//
- auto check = [&r, &loc, this](const char* cv,
- const variable& xv,
+ auto check = [&r, &loc, this](const char* cvar,
+ const variable& xvar,
const char* w)
{
- const string& c (cast<string> (r[cv]));
- const string& x (cast<string> (r[xv]));
+ const string& cv (cast<string> (r[cvar]));
+ const string& xv (cast<string> (r[xvar]));
- if (c != x)
+ if (cv != xv)
fail (loc) << "cc and " << x << " module " << w << " mismatch" <<
- info << cv << " is " << c <<
- info << xv.name << " is " << x;
+ info << cvar << " is " << cv <<
+ info << xvar.name << " is " << xv;
};
// Note that we don't require that patterns match. Presumably, if the
// toolchain id and target are the same, then where exactly the tools
- // (e.g., ar) come from doesn't really matter.
+ // come from doesn't really matter.
//
- check ("cc.id", x_id, "toolchain id");
+ check ("cc.id", x_id, "toolchain");
check ("cc.target", x_target, "target");
}
}