aboutsummaryrefslogtreecommitdiff
path: root/build/config
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-08-24 09:51:15 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-08-24 14:52:43 +0200
commit68f96f9213e849d0d7c4cedf3edeaec99743ee27 (patch)
tree271913d74c906971cac555319f5e14d0c66e0c16 /build/config
parent0d5234f4aefd3cc5b5948cc1b9dd009e50046f5e (diff)
New variable architecture
Diffstat (limited to 'build/config')
-rw-r--r--build/config/operation.cxx57
-rw-r--r--build/config/utility48
-rw-r--r--build/config/utility.cxx45
-rw-r--r--build/config/utility.ixx17
-rw-r--r--build/config/utility.txx64
5 files changed, 90 insertions, 141 deletions
diff --git a/build/config/operation.cxx b/build/config/operation.cxx
index a602325..913ae29 100644
--- a/build/config/operation.cxx
+++ b/build/config/operation.cxx
@@ -81,9 +81,9 @@ namespace build
<< "# feel free to edit." << endl
<< "#" << endl;
- if (auto v = root.vars["amalgamation"])
+ if (auto l = root.vars["amalgamation"])
{
- const dir_path& d (v.as<const dir_path&> ());
+ const dir_path& d (as<dir_path> (*l));
ofs << "# Base configuration inherited from " << d << endl
<< "#" << endl;
@@ -97,27 +97,23 @@ namespace build
++p.first)
{
const variable& var (p.first->first);
- const value_ptr& pval (p.first->second);
+ const value& val (p.first->second);
// Warn the user if the value that we are saving differs
// from the one they specified on the command line.
//
- if (auto gval = (*global_scope)[var])
+ auto l ((*global_scope)[var]);
+ if (l.defined () && *l != val)
{
- if (pval == nullptr || !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";
+ warn << "variable " << var.name << " configured value "
+ << "differs from command line value" <<
+ info << "reconfigure the project to use command line value";
}
- if (pval != nullptr)
+ if (val)
{
- //@@ TODO: assuming list
- //
- const list_value& lv (dynamic_cast<const list_value&> (*pval));
-
- ofs << var.name << " = " << lv << endl;
- //text << var.name << " = " << lv;
+ ofs << var.name << " = " << val.data_ << endl;
+ //text << var.name << " = " << val.data_;
}
else
{
@@ -171,14 +167,12 @@ namespace build
// Configure subprojects that have been loaded.
//
- if (auto v = root.vars["subprojects"])
+ if (auto l = root.vars["subprojects"])
{
- for (const name& n: v.as<const list_value&> ())
+ for (auto p: as<subprojects> (*l))
{
- if (n.pair != '\0')
- continue; // Skip project names.
-
- dir_path out_nroot (out_root / n.dir);
+ const dir_path& pd (p.second);
+ dir_path out_nroot (out_root / pd);
scope& nroot (scopes.find (out_nroot));
// @@ Strictly speaking we need to check whether the config
@@ -271,30 +265,27 @@ namespace build
// Disfigure subprojects. Since we don't load buildfiles during
// disfigure, we do it for all known subprojects.
//
- if (auto v = root.vars["subprojects"])
+ if (auto l = root.vars["subprojects"])
{
- for (const name& n: v.as<const list_value&> ())
+ for (auto p: as<subprojects> (*l))
{
- if (n.pair != '\0')
- continue; // Skip project names.
+ const dir_path& pd (p.second);
// Create and bootstrap subproject's root scope.
//
- dir_path out_nroot (out_root / n.dir);
+ dir_path out_nroot (out_root / pd);
// The same logic for src_root as in create_bootstrap_inner().
//
scope& nroot (create_root (out_nroot, dir_path ()));
bootstrap_out (nroot);
- auto val (nroot.assign ("src_root"));
+ value& val (nroot.assign ("src_root"));
if (!val)
- val = is_src_root (out_nroot)
- ? out_nroot
- : (src_root / n.dir);
+ val = is_src_root (out_nroot) ? out_nroot : (src_root / pd);
- nroot.src_path_ = &val.as<const dir_path&> ();
+ nroot.src_path_ = &as<dir_path> (val);
bootstrap_src (nroot);
@@ -304,9 +295,9 @@ namespace build
// which means there could be empty parent directories left
// behind. Clean them up.
//
- if (!n.dir.simple () && out_root != src_root)
+ if (!pd.simple () && out_root != src_root)
{
- for (dir_path d (n.dir.directory ());
+ for (dir_path d (pd.directory ());
!d.empty ();
d = d.directory ())
{
diff --git a/build/config/utility b/build/config/utility
index ef3ceed..82f71fe 100644
--- a/build/config/utility
+++ b/build/config/utility
@@ -6,15 +6,16 @@
#define BUILD_CONFIG_UTILITY
#include <string>
-#include <utility> // pair
+#include <utility> // pair
+#include <functional> // reference_wrapper
#include <build/types>
+#include <build/variable>
#include <build/diagnostics>
namespace build
{
class scope;
- class list_value;
namespace config
{
@@ -24,35 +25,36 @@ namespace build
// whether the variable has actually been set.
//
template <typename T>
- std::pair<const T&, bool>
- required (scope& root, const char* name, const T& default_value);
+ std::pair<std::reference_wrapper<const value>, bool>
+ required (scope& root, const variable&, const T& default_value);
template <typename T>
- inline std::pair<const T&, bool>
+ inline std::pair<std::reference_wrapper<const value>, bool>
required (scope& root, const std::string& name, const T& default_value)
{
- return required<T> (root, name.c_str (), default_value);
+ return required (root, variable_pool.find (name), default_value);
}
- std::pair<const std::string&, bool>
- required (scope& root, const char* name, const char* default_value);
+ inline std::pair<std::reference_wrapper<const value>, bool>
+ required (scope& root, const std::string& name, const char* default_value)
+ {
+ return required (root, name, std::string (default_value));
+ }
// Set, if necessary, an optional config.* variable. In particular,
// an unspecified variable is set to NULL which is used to distinguish
// between the "configured as unspecified" and "not yet configured"
// cases.
//
- // Return the pointer to the value, which can be NULL.
+ // Return the value, which can be NULL.
//
- template <typename T>
- const T*
- optional (scope& root, const char* name);
+ const value&
+ optional (scope& root, const variable& var);
- template <typename T>
- inline const T*
+ inline const value&
optional (scope& root, const std::string& name)
{
- return optional<T> (root, name.c_str ());
+ return optional (root, variable_pool.find (name));
}
// Check whether there are any variables specified from the
@@ -60,8 +62,8 @@ namespace build
// are any, say, config.install.* values. If there are none,
// then we can assume this functionality is not (yet) used
// and omit writing a whole bunch of NULL config.install.*
- // values to config.build. We call it omitted/delayed
- // configuration.
+ // values to the config.build file . We call it omitted/
+ // delayed configuration.
//
bool
specified (scope& root, const std::string& ns);
@@ -70,19 +72,20 @@ namespace build
//
// Add all the values from a variable to the C-string list. T is
- // either target or scope.
+ // either target or scope. The variable is expected to be of type
+ // strings.
//
template <typename T>
void
append_options (cstrings& args, T& s, const char* var);
- // As above but from the list value directly. Variable name is for
- // diagnostics.
+ // As above but from the strings value directly.
//
void
- append_options (cstrings& args, const list_value&, const char* var);
+ append_options (cstrings& args, const const_strings_value&);
- // Check if a specified option is present. T is either target or scope.
+ // Check if a specified option is present in the variable value.
+ // T is either target or scope.
//
template <typename T>
bool
@@ -91,5 +94,6 @@ namespace build
}
#include <build/config/utility.txx>
+#include <build/config/utility.ixx>
#endif // BUILD_CONFIG_UTILITY
diff --git a/build/config/utility.cxx b/build/config/utility.cxx
index e2afc80..ce723fe 100644
--- a/build/config/utility.cxx
+++ b/build/config/utility.cxx
@@ -10,32 +10,14 @@ namespace build
{
namespace config
{
- // The same as the template except it is a bit more efficient
- // when it comes to not creating the default value string
- // unnecessarily.
- //
- pair<const string&, bool>
- required (scope& root, const char* name, const char* def_value)
+ const value&
+ optional (scope& root, const variable& var)
{
- string r;
- const variable& var (variable_pool.find (name));
+ auto l (root[var]);
- if (auto v = root[var])
- {
- const string& s (v.as<const string&> ());
-
- if (!v.belongs (*global_scope)) // A value from (some) config.build.
- return pair<const string&, bool> (s, false);
-
- r = s;
- }
- else
- r = def_value;
-
- auto v (root.assign (var));
- v = move (r);
-
- return pair<const string&, bool> (v.as<const string&> (), true);
+ return l.defined ()
+ ? l.belongs (*global_scope) ? (root.assign (var) = *l) : *l
+ : root.assign (var); // NULL
}
bool
@@ -54,17 +36,14 @@ namespace build
}
void
- append_options (cstrings& args, const list_value& lv, const char* var)
+ append_options (cstrings& args, const const_strings_value& sv)
{
- for (const name& n: lv)
+ if (!sv.empty ())
{
- if (n.simple ())
- args.push_back (n.value.c_str ());
- else if (n.directory ())
- args.push_back (n.dir.string ().c_str ());
- else
- fail << "expected option instead of " << n <<
- info << "in variable " << var;
+ args.reserve (args.size () + sv.size ());
+
+ for (const string& s: sv)
+ args.push_back (s.c_str ());
}
}
}
diff --git a/build/config/utility.ixx b/build/config/utility.ixx
new file mode 100644
index 0000000..4e32119
--- /dev/null
+++ b/build/config/utility.ixx
@@ -0,0 +1,17 @@
+// file : build/config/utility.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+namespace build
+{
+ namespace config
+ {
+ template <typename T>
+ inline void
+ append_options (cstrings& args, T& s, const char* var)
+ {
+ if (auto l = s[var])
+ append_options (args, as<strings> (*l));
+ }
+ }
+}
diff --git a/build/config/utility.txx b/build/config/utility.txx
index cffdecf..943d308 100644
--- a/build/config/utility.txx
+++ b/build/config/utility.txx
@@ -2,79 +2,37 @@
// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
-#include <utility> // move()
-
#include <build/scope>
-#include <build/variable>
namespace build
{
namespace config
{
template <typename T>
- std::pair<const T&, bool>
- required (scope& root, const char* name, const T& def_value)
- {
- T r;
- const variable& var (variable_pool.find (name));
-
- if (auto v = root[var])
- {
- const T& s (v.as<const T&> ());
-
- if (!v.belongs (*global_scope)) // A value from (some) config.build.
- return std::pair<const T&, bool> (s, false);
-
- r = s;
- }
- else
- r = def_value;
-
- auto v (root.assign (var));
- v = std::move (r);
-
- return std::pair<const T&, bool> (v.as<const T&> (), true);
- }
-
- template <typename T>
- const T*
- optional (scope& root, const char* name)
+ std::pair<std::reference_wrapper<const value>, bool>
+ required (scope& root, const variable& var, const T& def_value)
{
- const T* r (nullptr);
- const variable& var (variable_pool.find (name));
+ using result = std::pair<std::reference_wrapper<const value>, bool>;
- auto v (root[var]);
-
- if (v.defined ())
+ if (auto l = root[var])
{
- if (v.belongs (*global_scope))
- root.assign (var) = v;
-
- r = v.null () ? nullptr : &v.as<const T&> ();
+ return l.belongs (*global_scope)
+ ? result (root.assign (var) = *l, true)
+ : result (*l, false);
}
else
- root.assign (var) = nullptr;
-
- return r;
- }
-
- template <typename T>
- void
- append_options (cstrings& args, T& s, const char* var)
- {
- if (auto val = s[var])
- append_options (args, val.template as<const list_value&> (), var);
+ return result (root.assign (var) = def_value, true);
}
template <typename T>
bool
find_option (const char* option, T& s, const char* var)
{
- if (auto val = s[var])
+ if (auto l = s[var])
{
- for (const name& n: val.template as<const list_value&> ())
+ for (const std::string& s: as<strings> (*l))
{
- if (n.simple () && n.value == option)
+ if (s == option)
return true;
}
}