aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/cc/module.hxx6
-rw-r--r--libbuild2/cxx/init.cxx71
2 files changed, 64 insertions, 13 deletions
diff --git a/libbuild2/cc/module.hxx b/libbuild2/cc/module.hxx
index ac170da..f9d435d 100644
--- a/libbuild2/cc/module.hxx
+++ b/libbuild2/cc/module.hxx
@@ -45,8 +45,10 @@ namespace build2
// Translate the x.std value (if any) to the standard-selecting
// option(s) (if any) and fold them (normally by pre-pending) into the
- // compiler mode options. This function may also check/set x.features.*
- // variables on the root scope.
+ // compiler mode options.
+ //
+ // This function may also check/set [config.]x.features.* variables on
+ // the root scope.
//
virtual void
translate_std (const compiler_info&,
diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx
index 876f5d8..adc5bf4 100644
--- a/libbuild2/cxx/init.cxx
+++ b/libbuild2/cxx/init.cxx
@@ -6,6 +6,8 @@
#include <libbuild2/scope.hxx>
#include <libbuild2/diagnostics.hxx>
+#include <libbuild2/config/utility.hxx>
+
#include <libbuild2/cc/guess.hxx>
#include <libbuild2/cc/module.hxx>
@@ -93,11 +95,57 @@ namespace build2
//
auto& vp (rs.var_pool ());
- //bool concepts (false);
- //auto& v_c (vp.insert<bool> ("cxx.features.concepts"));
+ // Similar to config.cxx.std, config.cxx.features.* override
+ // cxx.features.*.
+ //
+ struct feature
+ {
+ optional<bool> value; // cxx.features.* value.
+ optional<bool> c_value; // config.cxx.features.* value.
+ bool result; // Calculated result value.
+
+ feature& operator= (bool r) {result = r; return *this;}
+
+ build2::value& value_; // cxx.features.* variable value.
+ const char* name_; // Feature name.
+ };
+
+ auto get_feature = [&rs, &vp] (const char* name) -> feature
+ {
+ auto& var (vp.insert<bool> (string ("cxx.features.") + name));
+ auto& c_var (vp.insert<bool> (string ("config.cxx.features.") + name));
+
+ pair<value&, bool> val (rs.vars.insert (var));
+ lookup l (config::lookup_config (rs, c_var));
+
+ optional<bool> v, c_v;
+ if (l.defined ())
+ v = c_v = cast_false<bool> (*l);
+ else if (!val.second)
+ v = cast_false<bool> (val.first);
- bool modules (false);
- auto& v_m (vp.insert<bool> ("cxx.features.modules"));
+ return feature {v, c_v, false, val.first, name};
+ };
+
+ auto set_feature = [&rs, &ci, v] (const feature& f)
+ {
+ if (f.c_value && *f.c_value != f.result)
+ {
+ fail << f.name_ << " cannot be "
+ << (*f.c_value ? "enabled" : "disabled") << " for "
+ << project (rs) << '@' << rs <<
+ info << "C++ language standard is "
+ << (v != nullptr ? v->c_str () : "compiler-default") <<
+ info << "C++ compiler is " << ci.signature <<
+ info << f.name_ << " state requested with config.cxx.features."
+ << f.name_;
+ }
+
+ f.value_ = f.result;
+ };
+
+ feature modules (get_feature ("modules"));
+ //feature concepts (get_feature ("concepts"));
// NOTE: see also module sidebuild subproject if changing anything about
// modules here.
@@ -301,8 +349,7 @@ namespace build2
// Unless disabled by the user, try to enable C++ modules.
//
- lookup l;
- if (!(l = rs[v_m]) || cast<bool> (l))
+ if (!modules.value || *modules.value)
{
switch (ct)
{
@@ -315,7 +362,7 @@ namespace build2
// M;` syntax. And 16.4 (19.24) supports the global module
// fragment.
//
- if (mj > 19 || (mj == 19 && mi >= (l ? 10 : 12)))
+ if (mj > 19 || (mj == 19 && mi >= (modules.value ? 10 : 12)))
{
prepend (
mj > 19 || mi >= 24 ?
@@ -336,13 +383,14 @@ namespace build2
// generated headers via the mapper, we require the user to
// explicitly request modules.
//
- if (mj >= 11 && l)
+ if (mj >= 11 && modules.value)
{
// Defines __cpp_modules=201907. @@ TMP: confirm.
//
prepend ("-fmodules-ts");
modules = true;
}
+
break;
}
case compiler_type::clang:
@@ -360,12 +408,13 @@ namespace build2
//
// Also see Clang modules support hack in cc::compile.
//
- if (l)
+ if (modules.value)
{
prepend ("-D__cpp_modules=201704"); // p0629r0
mode.push_back ("-fmodules-ts"); // For the hack to work.
modules = true;
}
+
break;
}
case compiler_type::icc:
@@ -374,8 +423,8 @@ namespace build2
}
}
- rs.assign (v_m) = modules;
- //rs.assign (v_c) = concepts;
+ set_feature (modules);
+ //set_feature (concepts);
}
static const char* const hinters[] = {"c", nullptr};