diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-04-01 12:18:40 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-04-01 12:18:40 +0200 |
commit | e0de4f26fcf598b4f6beaa2847c4d43a4c761f5b (patch) | |
tree | 42e79e141d5b3488cb98843589a68001c875ed01 | |
parent | 0dee00f28e623830e816c4002c8004c86055df85 (diff) |
Warn about configured/command line value mismatch
Also store configured but unspecified values
-rw-r--r-- | build/config/operation.cxx | 37 | ||||
-rw-r--r-- | build/cxx/module.cxx | 12 | ||||
-rw-r--r-- | build/name | 9 | ||||
-rw-r--r-- | build/variable | 63 | ||||
-rw-r--r-- | build/variable.ixx | 46 |
5 files changed, 117 insertions, 50 deletions
diff --git a/build/config/operation.cxx b/build/config/operation.cxx index c6a9444..5b9cc5c 100644 --- a/build/config/operation.cxx +++ b/build/config/operation.cxx @@ -82,30 +82,43 @@ namespace build ofs.exceptions (ofstream::failbit | ofstream::badbit); - // Save all the variables in the config. namespace that are set + // Save all the variables in the config namespace that are set // on the project's root scope. // scope& r (scopes.find (out_root)); - /* - r.variables["config"] = "default interactive"; - r.variables["config.cxx"] = "g++-4.9"; - r.variables["config.cxx.options"] = "-O3 -g"; - */ - for (auto p (r.variables.find_namespace ("config")); p.first != p.second; ++p.first) { const variable& var (p.first->first); - const value& val (*p.first->second); + const value_ptr& pval (p.first->second); - //@@ TODO: assuming list + // Warn the user if the value that we are saving differs + // from the one they specified on the command line. // - const list_value& lv (dynamic_cast<const list_value&> (val)); + if (auto gval = (*global_scope)[var]) + { + if (!pval || !pval->compare (gval.as<const value&> ())) + warn << "variable " << var.name << " configured value " + << "differs from command line value" << + info << "reconfigure the project to use command line value"; + } - ofs << var.name << " = " << lv.data << endl; - text << var.name << " = " << lv.data; + if (pval) + { + //@@ TODO: assuming list + // + const list_value& lv (dynamic_cast<const list_value&> (*pval)); + + ofs << var.name << " = " << lv.data << endl; + text << var.name << " = " << lv.data; + } + else + { + ofs << var.name << " =" << endl; // @@ TODO: [undefined] + text << var.name << " = [undefined]"; + } } } catch (const ios_base::failure&) diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx index eb7ca40..1179ce3 100644 --- a/build/cxx/module.cxx +++ b/build/cxx/module.cxx @@ -104,31 +104,41 @@ namespace build // // These are optional so all we need to do is "import" them // into the root scope if they were specified on the command - // line. + // line and set them to empty if unspecified (the last part + // is important for the "configured as undefined" vs + // "unconfigured" logic). // if (auto val = root["config.cxx.poptions"]) { if (&val.scope () == global_scope) root.variables["config.cxx.poptions"] = val; } + else + root.variables["config.cxx.poptions"]; // Undefined. if (auto val = root["config.cxx.coptions"]) { if (&val.scope () == global_scope) root.variables["config.cxx.coptions"] = val; } + else + root.variables["config.cxx.coptions"]; // Undefined. if (auto val = root["config.cxx.loptions"]) { if (&val.scope () == global_scope) root.variables["config.cxx.loptions"] = val; } + else + root.variables["config.cxx.loptions"]; // Undefined. if (auto val = root["config.cxx.libs"]) { if (&val.scope () == global_scope) root.variables["config.cxx.libs"] = val; } + else + root.variables["config.cxx.libs"]; // Undefined. } } } @@ -39,6 +39,15 @@ namespace build bool pair {false}; }; + inline bool + operator== (const name& x, const name& y) + { + return x.type == y.type && x.dir == y.dir && x.value == y.value; + } + + inline bool + operator!= (const name& x, const name& y) {return !(x == y);} + typedef std::vector<name> names; std::ostream& diff --git a/build/variable b/build/variable index 0688a3e..500cc00 100644 --- a/build/variable +++ b/build/variable @@ -63,6 +63,9 @@ namespace build virtual value_ptr clone (scope_type& s) const = 0; + virtual bool + compare (const value&) const = 0; + virtual ~value () = default; }; @@ -88,8 +91,15 @@ namespace build data.emplace_back (std::move (d)); } - value_ptr + virtual value_ptr clone (scope_type& s) const {return value_ptr (new list_value (s, data));} + + virtual bool + compare (const value& v) const + { + const list_value* lv (dynamic_cast<const list_value*> (&v)); + return lv != nullptr && data == lv->data; + } }; typedef std::unique_ptr<list_value> list_value_ptr; @@ -114,49 +124,18 @@ namespace build // Set interface. // const value_proxy& - operator= (value_ptr v) const - { - assert (v == nullptr || &v->scope == s); - *p = std::move (v); - return *this; - } + operator= (value_ptr) const; const value_proxy& - operator= (const value_proxy& v) const - { - if (this != &v) - { - if (v) - { - const value_ptr& vp (v); - *p = vp->clone (*s); - } - else - p->reset (); - } - - return *this; - } + operator= (const value_proxy&) const; const value_proxy& - operator= (std::string v) const - { - // In most cases this is used to initialize a new variable, so - // don't bother trying to optimize for the case where p is not - // NULL. - // - p->reset (new list_value (*s, std::move (v))); - return *this; - } + operator= (std::string) const; // Note: stored in name as a directory. // const value_proxy& - operator= (path v) const - { - p->reset (new list_value (*s, std::move (v))); - return *this; - } + operator= (path) const; // Implementation details. // @@ -169,6 +148,14 @@ namespace build }; template <> + inline value& value_proxy:: + as<value&> () const {return **p;} + + template <> + inline const value& value_proxy:: + as<const value&> () const {return **p;} + + template <> list_value& value_proxy:: as<list_value&> () const; @@ -180,7 +167,7 @@ namespace build const std::string& value_proxy:: as<const std::string&> () const; - // Note: get the name's directory. + // Note: get the name's dir. // template <> const path& value_proxy:: @@ -273,4 +260,6 @@ namespace build }; } +#include <build/variable.ixx> + #endif // BUILD_VARIABLE diff --git a/build/variable.ixx b/build/variable.ixx new file mode 100644 index 0000000..85fdd50 --- /dev/null +++ b/build/variable.ixx @@ -0,0 +1,46 @@ +// file : build/variable.ixx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace build +{ + inline const value_proxy& value_proxy:: + operator= (value_ptr v) const + { + assert (v == nullptr || &v->scope == s); + *p = std::move (v); + return *this; + } + + inline const value_proxy& value_proxy:: + operator= (const value_proxy& v) const + { + if (this != &v) + { + if (v) + *p = v.as<const value&> ().clone (*s); + else + p->reset (); + } + + return *this; + } + + inline const value_proxy& value_proxy:: + operator= (std::string v) const + { + // In most cases this is used to initialize a new variable, so + // don't bother trying to optimize for the case where p is not + // NULL. + // + p->reset (new list_value (*s, std::move (v))); + return *this; + } + + inline const value_proxy& value_proxy:: + operator= (path v) const + { + p->reset (new list_value (*s, std::move (v))); + return *this; + } +} |