From e0de4f26fcf598b4f6beaa2847c4d43a4c761f5b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 1 Apr 2015 12:18:40 +0200 Subject: Warn about configured/command line value mismatch Also store configured but unspecified values --- build/config/operation.cxx | 37 ++++++++++++++++++--------- build/cxx/module.cxx | 12 ++++++++- build/name | 9 +++++++ build/variable | 63 +++++++++++++++++++--------------------------- build/variable.ixx | 46 +++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 50 deletions(-) create mode 100644 build/variable.ixx (limited to 'build') 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 (val)); + if (auto gval = (*global_scope)[var]) + { + if (!pval || !pval->compare (gval.as ())) + 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 (*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. } } } diff --git a/build/name b/build/name index fc89f44..f45930e 100644 --- a/build/name +++ b/build/name @@ -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 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 (&v)); + return lv != nullptr && data == lv->data; + } }; typedef std::unique_ptr 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 () const {return **p;} + + template <> + inline const value& value_proxy:: + as () const {return **p;} + + template <> list_value& value_proxy:: as () const; @@ -180,7 +167,7 @@ namespace build const std::string& value_proxy:: as () 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 + #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 ().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; + } +} -- cgit v1.1