From 68f96f9213e849d0d7c4cedf3edeaec99743ee27 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 24 Aug 2015 09:51:15 +0200 Subject: New variable architecture --- build/config/operation.cxx | 57 +++++++++++++++++------------------------ build/config/utility | 48 ++++++++++++++++++---------------- build/config/utility.cxx | 45 +++++++++----------------------- build/config/utility.ixx | 17 ++++++++++++ build/config/utility.txx | 64 ++++++++-------------------------------------- 5 files changed, 90 insertions(+), 141 deletions(-) create mode 100644 build/config/utility.ixx (limited to 'build/config') 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& d (as (*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 ())) - 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 (*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 ()) + for (auto p: as (*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 ()) + for (auto p: as (*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 (); + nroot.src_path_ = &as (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 -#include // pair +#include // pair +#include // reference_wrapper #include +#include #include namespace build { class scope; - class list_value; namespace config { @@ -24,35 +25,36 @@ namespace build // whether the variable has actually been set. // template - std::pair - required (scope& root, const char* name, const T& default_value); + std::pair, bool> + required (scope& root, const variable&, const T& default_value); template - inline std::pair + inline std::pair, bool> required (scope& root, const std::string& name, const T& default_value) { - return required (root, name.c_str (), default_value); + return required (root, variable_pool.find (name), default_value); } - std::pair - required (scope& root, const char* name, const char* default_value); + inline std::pair, 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 - const T* - optional (scope& root, const char* name); + const value& + optional (scope& root, const variable& var); - template - inline const T* + inline const value& optional (scope& root, const std::string& name) { - return optional (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 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 bool @@ -91,5 +94,6 @@ namespace build } #include +#include #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 - 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 ()); - - if (!v.belongs (*global_scope)) // A value from (some) config.build. - return pair (s, false); - - r = s; - } - else - r = def_value; - - auto v (root.assign (var)); - v = move (r); - - return pair (v.as (), 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 + inline void + append_options (cstrings& args, T& s, const char* var) + { + if (auto l = s[var]) + append_options (args, as (*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 // move() - #include -#include namespace build { namespace config { template - std::pair - 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 ()); - - if (!v.belongs (*global_scope)) // A value from (some) config.build. - return std::pair (s, false); - - r = s; - } - else - r = def_value; - - auto v (root.assign (var)); - v = std::move (r); - - return std::pair (v.as (), true); - } - - template - const T* - optional (scope& root, const char* name) + std::pair, 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, 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 (); + return l.belongs (*global_scope) + ? result (root.assign (var) = *l, true) + : result (*l, false); } else - root.assign (var) = nullptr; - - return r; - } - - template - void - append_options (cstrings& args, T& s, const char* var) - { - if (auto val = s[var]) - append_options (args, val.template as (), var); + return result (root.assign (var) = def_value, true); } template 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 ()) + for (const std::string& s: as (*l)) { - if (n.simple () && n.value == option) + if (s == option) return true; } } -- cgit v1.1