aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-09-07 18:09:44 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-09-07 18:09:44 +0200
commite2ba7fa123213fcc5673119b8d993d7967a1fb24 (patch)
tree22b545150af90ec2831a2665afbac9b19828e65f
parentd01c30fa81a849ea7545b8235656eb1dcbba877b (diff)
Implement {c,cxx}.guess modules
These can be loaded before {c,cxx} to guess the compiler. Based on this information we can then choose the standard, experimental features, etc. For example: using cxx.guess if ($cxx.id == 'clang') cxx.features.modules = false cxx.std = experimental using cxx
-rw-r--r--build2/b.cxx2
-rw-r--r--build2/c/init.cxx62
-rw-r--r--build2/c/init.hxx9
-rw-r--r--build2/cc/module.cxx75
-rw-r--r--build2/cc/module.hxx15
-rw-r--r--build2/cxx/init.cxx61
-rw-r--r--build2/cxx/init.hxx9
7 files changed, 165 insertions, 68 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index 95bf876..0520bd8 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -333,9 +333,11 @@ main (int argc, char* argv[])
bm["cc.config"] = mf {nullptr, &cc::config_init};
bm["cc"] = mf {nullptr, &cc::init};
+ bm["c.guess"] = mf {nullptr, &c::guess_init};
bm["c.config"] = mf {nullptr, &c::config_init};
bm["c"] = mf {nullptr, &c::init};
+ bm["cxx.guess"] = mf {nullptr, &cxx::guess_init};
bm["cxx.config"] = mf {nullptr, &cxx::config_init};
bm["cxx"] = mf {nullptr, &cxx::init};
diff --git a/build2/c/init.cxx b/build2/c/init.cxx
index 79cfec7..1190eae 100644
--- a/build2/c/init.cxx
+++ b/build2/c/init.cxx
@@ -30,7 +30,7 @@ namespace build2
config_module (config_data&& d)
: config_data (move (d)), cc::config_module (move (d)) {}
- strings
+ virtual strings
translate_std (const compiler_info&,
scope&,
const string*) const override;
@@ -106,22 +106,24 @@ namespace build2
return r;
}
+ // See cc::module for details on guess_init vs config_init.
+ //
bool
- config_init (scope& rs,
- scope& bs,
- const location& loc,
- unique_ptr<module_base>& mod,
- bool,
- bool,
- const variable_map& hints)
+ guess_init (scope& rs,
+ scope& bs,
+ const location& loc,
+ unique_ptr<module_base>& mod,
+ bool,
+ bool,
+ const variable_map& hints)
{
- tracer trace ("c::config_init");
+ tracer trace ("c::guess_init");
l5 ([&]{trace << "for " << bs.out_path ();});
// We only support root loading (which means there can only be one).
//
if (&rs != &bs)
- fail (loc) << "c.config module must be loaded in project root";
+ fail (loc) << "c.guess module must be loaded in project root";
// Load cc.core.vars so that we can cache all the cc.* variables.
//
@@ -207,10 +209,38 @@ namespace build2
assert (mod == nullptr);
config_module* m (new config_module (move (d)));
mod.reset (m);
- m->init (rs, loc, hints);
+ m->guess (rs, loc, hints);
return true;
}
+ bool
+ config_init (scope& rs,
+ scope& bs,
+ const location& loc,
+ unique_ptr<module_base>&,
+ bool,
+ bool,
+ const variable_map& hints)
+ {
+ tracer trace ("c::config_init");
+ l5 ([&]{trace << "for " << bs.out_path ();});
+
+ // We only support root loading (which means there can only be one).
+ //
+ if (&rs != &bs)
+ fail (loc) << "c.config module must be loaded in project root";
+
+ // Load c.guess.
+ //
+ if (!cast_false<bool> (rs["c.guess.loaded"]))
+ load_module (rs, rs, "c.guess", loc, false, hints);
+
+ config_module& cm (*rs.modules.lookup<config_module> ("c.guess"));
+ cm.init (rs, loc, hints);
+ return true;
+ }
+
+
static const target_type* const hdr[] =
{
&h::static_type,
@@ -246,7 +276,7 @@ namespace build2
if (!cast_false<bool> (rs["c.config.loaded"]))
load_module (rs, rs, "c.config", loc, false, hints);
- config_module& cm (*rs.modules.lookup<config_module> ("c.config"));
+ config_module& cm (*rs.modules.lookup<config_module> ("c.guess"));
cc::data d {
cm,
@@ -256,10 +286,10 @@ namespace build2
"c.install",
"c.uninstall",
- cm.cid,
- cast<string> (rs[cm.x_id_variant]),
- cast<uint64_t> (rs[cm.x_version_major]),
- cast<uint64_t> (rs[cm.x_version_minor]),
+ cm.ci.id.value (),
+ cm.ci.id.variant,
+ cm.ci.version.major,
+ cm.ci.version.minor,
cast<process_path> (rs[cm.x_path]),
cast<target_triplet> (rs[cm.x_target]),
diff --git a/build2/c/init.hxx b/build2/c/init.hxx
index e18a5df..5fd7c84 100644
--- a/build2/c/init.hxx
+++ b/build2/c/init.hxx
@@ -15,6 +15,15 @@ namespace build2
namespace c
{
bool
+ guess_init (scope&,
+ scope&,
+ const location&,
+ unique_ptr<module_base>&,
+ bool,
+ bool,
+ const variable_map&);
+
+ bool
config_init (scope&,
scope&,
const location&,
diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx
index 56b74e9..a18271c 100644
--- a/build2/cc/module.cxx
+++ b/build2/cc/module.cxx
@@ -25,16 +25,12 @@ namespace build2
namespace cc
{
void config_module::
- init (scope& rs, const location& loc, const variable_map&)
+ guess (scope& rs, const location&, const variable_map&)
{
- tracer trace (x, "config_init");
+ tracer trace (x, "guess_init");
bool cc_loaded (cast_false<bool> (rs["cc.core.config.loaded"]));
- // Configure.
- //
- compiler_info ci; // For program patterns.
-
// 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).
@@ -81,10 +77,10 @@ namespace build2
// Figure out which compiler we are dealing with, its target, etc.
//
const path& xc (cast<path> (*p.first));
- ci = guess (x_lang,
- xc,
- cast_null<strings> (rs[config_c_coptions]),
- cast_null<strings> (rs[config_x_coptions]));
+ ci = cc::guess (x_lang,
+ xc,
+ cast_null<strings> (rs[config_c_coptions]),
+ cast_null<strings> (rs[config_x_coptions]));
// Split/canonicalize the target. First see if the user asked us to
// use config.sub.
@@ -118,6 +114,39 @@ namespace build2
}
}
+ // Assign value to variables that describe the compile.
+ //
+ rs.assign (x_id) = ci.id.string ();
+ rs.assign (x_id_type) = ci.id.type;
+ rs.assign (x_id_variant) = ci.id.variant;
+
+ rs.assign (x_version) = ci.version.string;
+ rs.assign (x_version_major) = ci.version.major;
+ rs.assign (x_version_minor) = ci.version.minor;
+ rs.assign (x_version_patch) = ci.version.patch;
+ rs.assign (x_version_build) = ci.version.build;
+
+ // Also enter as x.target.{cpu,vendor,system,version,class} for
+ // convenience of access.
+ //
+ rs.assign (x_target_cpu) = tt.cpu;
+ rs.assign (x_target_vendor) = tt.vendor;
+ rs.assign (x_target_system) = tt.system;
+ rs.assign (x_target_version) = tt.version;
+ rs.assign (x_target_class) = tt.class_;
+
+ rs.assign (x_target) = move (tt);
+
+ new_ = p.second;
+ }
+
+ void config_module::
+ init (scope& rs, const location& loc, const variable_map&)
+ {
+ tracer trace (x, "config_init");
+
+ const target_triplet& tt (cast<target_triplet> (rs[x_target]));
+
// Translate x_std value (if any) to the compiler option(s) (if any).
//
tstd = translate_std (ci, rs, cast_null<string> (rs[x_std]));
@@ -154,7 +183,7 @@ namespace build2
// 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))
+ if (verb >= (new_ ? 2 : 3))
{
diag_record dr (text);
@@ -220,31 +249,9 @@ namespace build2
rs.assign (x_sys_lib_dirs) = move (lib_dirs);
rs.assign (x_sys_inc_dirs) = move (inc_dirs);
- cid = ci.id.value ();
- rs.assign (x_id) = ci.id.string ();
- rs.assign (x_id_type) = move (ci.id.type);
- rs.assign (x_id_variant) = move (ci.id.variant);
-
- rs.assign (x_version) = move (ci.version.string);
- rs.assign (x_version_major) = ci.version.major;
- rs.assign (x_version_minor) = ci.version.minor;
- rs.assign (x_version_patch) = ci.version.patch;
- rs.assign (x_version_build) = move (ci.version.build);
-
rs.assign (x_signature) = move (ci.signature);
rs.assign (x_checksum) = move (ci.checksum);
- // Also enter as x.target.{cpu,vendor,system,version,class} for
- // convenience of access.
- //
- rs.assign (x_target_cpu) = tt.cpu;
- rs.assign (x_target_vendor) = tt.vendor;
- rs.assign (x_target_system) = tt.system;
- rs.assign (x_target_version) = tt.version;
- rs.assign (x_target_class) = tt.class_;
-
- rs.assign (x_target) = move (tt);
-
// config.x.{p,c,l}options
// config.x.libs
//
@@ -275,7 +282,7 @@ namespace build2
// Load cc.core.config.
//
- if (!cc_loaded)
+ if (!cast_false<bool> (rs["cc.core.config.loaded"]))
{
// Prepare configuration hints.
//
diff --git a/build2/cc/module.hxx b/build2/cc/module.hxx
index c34b0e5..08f573b 100644
--- a/build2/cc/module.hxx
+++ b/build2/cc/module.hxx
@@ -29,6 +29,15 @@ namespace build2
explicit
config_module (config_data&& d) : config_data (move (d)) {}
+ // We split the configuration process into into two parts: guessing the
+ // compiler information and the actual configuration. This allows one to
+ // adjust configuration (say the standard or enabled experimental
+ // features) base on the compiler information by first loading the
+ // guess module.
+ //
+ void
+ guess (scope&, const location&, const variable_map&);
+
void
init (scope&, const location&, const variable_map&);
@@ -40,8 +49,7 @@ namespace build2
translate_std (const compiler_info&, scope&, const string*) const = 0;
strings tstd;
-
- compiler_id::value_type cid;
+ compiler_info ci; // Note: some members are moved from.
private:
dir_paths
@@ -49,6 +57,9 @@ namespace build2
dir_paths
msvc_library_search_paths (process_path&, scope&) const; // msvc.cxx
+
+ private:
+ bool new_; // See guess() and init() for details.
};
class module: public module_base, public virtual common,
diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx
index 5bd14ee..4a72c90 100644
--- a/build2/cxx/init.cxx
+++ b/build2/cxx/init.cxx
@@ -30,7 +30,7 @@ namespace build2
config_module (config_data&& d)
: config_data (move (d)), cc::config_module (move (d)) {}
- strings
+ virtual strings
translate_std (const compiler_info&,
scope&,
const string*) const override;
@@ -285,22 +285,24 @@ namespace build2
return r;
}
+ // See cc::module for details on guess_init vs config_init.
+ //
bool
- config_init (scope& rs,
- scope& bs,
- const location& loc,
- unique_ptr<module_base>& mod,
- bool,
- bool,
- const variable_map& hints)
+ guess_init (scope& rs,
+ scope& bs,
+ const location& loc,
+ unique_ptr<module_base>& mod,
+ bool,
+ bool,
+ const variable_map& hints)
{
- tracer trace ("cxx::config_init");
+ tracer trace ("cxx::guess_init");
l5 ([&]{trace << "for " << bs.out_path ();});
// We only support root loading (which means there can only be one).
//
if (&rs != &bs)
- fail (loc) << "cxx.config module must be loaded in project root";
+ fail (loc) << "cxx.guess module must be loaded in project root";
// Load cc.core.vars so that we can cache all the cc.* variables.
//
@@ -396,7 +398,34 @@ namespace build2
assert (mod == nullptr);
config_module* m (new config_module (move (d)));
mod.reset (m);
- m->init (rs, loc, hints);
+ m->guess (rs, loc, hints);
+ return true;
+ }
+
+ bool
+ config_init (scope& rs,
+ scope& bs,
+ const location& loc,
+ unique_ptr<module_base>&,
+ bool,
+ bool,
+ const variable_map& hints)
+ {
+ tracer trace ("cxx::config_init");
+ l5 ([&]{trace << "for " << bs.out_path ();});
+
+ // We only support root loading (which means there can only be one).
+ //
+ if (&rs != &bs)
+ fail (loc) << "cxx.config module must be loaded in project root";
+
+ // Load cxx.guess.
+ //
+ if (!cast_false<bool> (rs["cxx.guess.loaded"]))
+ load_module (rs, rs, "cxx.guess", loc, false, hints);
+
+ config_module& cm (*rs.modules.lookup<config_module> ("cxx.guess"));
+ cm.init (rs, loc, hints);
return true;
}
@@ -444,7 +473,7 @@ namespace build2
if (!cast_false<bool> (rs["cxx.config.loaded"]))
load_module (rs, rs, "cxx.config", loc, false, hints);
- config_module& cm (*rs.modules.lookup<config_module> ("cxx.config"));
+ config_module& cm (*rs.modules.lookup<config_module> ("cxx.guess"));
auto& vp (var_pool.rw (rs));
@@ -467,10 +496,10 @@ namespace build2
"cxx.install",
"cxx.uninstall",
- cm.cid,
- cast<string> (rs[cm.x_id_variant]),
- cast<uint64_t> (rs[cm.x_version_major]),
- cast<uint64_t> (rs[cm.x_version_minor]),
+ cm.ci.id.value (),
+ cm.ci.id.variant,
+ cm.ci.version.major,
+ cm.ci.version.minor,
cast<process_path> (rs[cm.x_path]),
cast<target_triplet> (rs[cm.x_target]),
diff --git a/build2/cxx/init.hxx b/build2/cxx/init.hxx
index 5ba4041..a952bf8 100644
--- a/build2/cxx/init.hxx
+++ b/build2/cxx/init.hxx
@@ -15,6 +15,15 @@ namespace build2
namespace cxx
{
bool
+ guess_init (scope&,
+ scope&,
+ const location&,
+ unique_ptr<module_base>&,
+ bool,
+ bool,
+ const variable_map&);
+
+ bool
config_init (scope&,
scope&,
const location&,