aboutsummaryrefslogtreecommitdiff
path: root/build
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-04-01 12:18:40 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-04-01 12:18:40 +0200
commite0de4f26fcf598b4f6beaa2847c4d43a4c761f5b (patch)
tree42e79e141d5b3488cb98843589a68001c875ed01 /build
parent0dee00f28e623830e816c4002c8004c86055df85 (diff)
Warn about configured/command line value mismatch
Also store configured but unspecified values
Diffstat (limited to 'build')
-rw-r--r--build/config/operation.cxx37
-rw-r--r--build/cxx/module.cxx12
-rw-r--r--build/name9
-rw-r--r--build/variable63
-rw-r--r--build/variable.ixx46
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.
}
}
}
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<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;
+ }
+}