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/install/module.cxx | 139 +++++++++++++++++++++++++++-------------------- build/install/rule.cxx | 86 ++++++++++------------------- build/install/utility | 20 ++++--- 3 files changed, 120 insertions(+), 125 deletions(-) (limited to 'build/install') diff --git a/build/install/module.cxx b/build/install/module.cxx index 834b0e8..610154a 100644 --- a/build/install/module.cxx +++ b/build/install/module.cxx @@ -29,54 +29,64 @@ namespace build // to set all the install.* values to defaults, as if we had the // default configuration. // + template static void - set_dir (bool spec, + set_var (bool spec, scope& r, const char* name, - const char* path, - const char* mode = nullptr, - const char* dir_mode = nullptr, - const char* cmd = nullptr, - const char* options = nullptr) + const char* var, + const T* dv) { - auto set = [spec, &r, name] (const char* var, const char* dv) - { - string vn; - const list_value* lv (nullptr); - - if (spec) - { - vn = "config.install."; - vn += name; - vn += var; - - lv = dv != nullptr - ? &config::required (r, vn, list_value (dv)).first - : config::optional (r, vn); - } - - vn = "install."; - vn += name; - vn += var; - auto v (r.assign (vn)); - - if (spec) - { - if (lv != nullptr && !lv->empty ()) - v = *lv; - } - else - { - if (dv != nullptr) - v = dv; - } - }; - - set ("", path); - set (".mode", mode); - set (".dir_mode", dir_mode); - set (".cmd", cmd); - set (".options", options); + string vn; + const value* cv (nullptr); + + if (spec) + { + vn = "config.install."; + vn += name; + vn += var; + const variable& vr ( + variable_pool.find (move (vn), &value_traits::value_type)); + + cv = dv != nullptr + ? &config::required (r, vr, *dv).first.get () + : &config::optional (r, vr); + } + + vn = "install."; + vn += name; + vn += var; + const variable& vr ( + variable_pool.find (move (vn), &value_traits::value_type)); + + value& v (r.assign (vr)); + + if (spec) + { + if (cv != nullptr && *cv && !cv->empty ()) + v = *cv; + } + else + { + if (dv != nullptr) + v = *dv; + } + } + + static void + set_dir (bool s, + scope& r, + const char* name, + const dir_path& path, + const string& fmode = string (), + const string& dmode = string (), + const string& cmd = string ()) + { + set_var (s, r, name, "", path.empty () ? nullptr : &path); + set_var (s, r, name, ".mode", fmode.empty () ? nullptr : &fmode); + set_var (s, r, name, ".dir_mode", dmode.empty () ? nullptr : &dmode); + set_var (s, r, name, ".cmd", cmd.empty () ? nullptr : &cmd); + set_var (s, r, name, ".options", nullptr); } static rule rule_; @@ -120,6 +130,15 @@ namespace build rs.insert (install_id, "install", rule_); } + // Enter module variables. + // + // Note that the set_dir() calls below enter some more. + // + if (first) + { + variable_pool.find ("install", dir_path_type); + } + // Configuration. // // Note that we don't use any defaults for root -- the location @@ -129,31 +148,31 @@ namespace build if (first) { bool s (config::specified (r, "config.install")); - const string& n (r["project"].as ()); + const string& n (as (*r["project"])); - set_dir (s, r, "root", nullptr, nullptr, "755", "install"); - set_dir (s, r, "data_root", "root", "644"); - set_dir (s, r, "exec_root", "root", "755"); + set_dir (s, r, "root", dir_path (), "", "755", "install"); + set_dir (s, r, "data_root", dir_path ("root"), "644"); + set_dir (s, r, "exec_root", dir_path ("root"), "755"); - set_dir (s, r, "sbin", "exec_root/sbin"); - set_dir (s, r, "bin", "exec_root/bin"); - set_dir (s, r, "lib", "exec_root/lib"); - set_dir (s, r, "libexec", ("exec_root/libexec/" + n).c_str ()); + set_dir (s, r, "sbin", dir_path ("exec_root/sbin")); + set_dir (s, r, "bin", dir_path ("exec_root/bin")); + set_dir (s, r, "lib", dir_path ("exec_root/lib")); + set_dir (s, r, "libexec", dir_path ("exec_root/libexec/" + n)); - set_dir (s, r, "data", ("data_root/share/" + n).c_str ()); - set_dir (s, r, "include", "data_root/include"); + set_dir (s, r, "data", dir_path ("data_root/share/" + n)); + set_dir (s, r, "include", dir_path ("data_root/include")); - set_dir (s, r, "doc", ("data_root/share/doc/" + n).c_str ()); - set_dir (s, r, "man", "data_root/share/man"); + set_dir (s, r, "doc", dir_path ("data_root/share/doc/" + n)); + set_dir (s, r, "man", dir_path ("data_root/share/man")); - set_dir (s, r, "man1", "man/man1"); + set_dir (s, r, "man1", dir_path ("man/man1")); } // Configure "installability" for built-in target types. // - path (b, "doc"); // Install into install.doc. - path (b, "man"); // Install into install.man. - path (b, "man1"); // Install into install.man1. + path (b, dir_path ("doc")); // Install into install.doc. + path (b, dir_path ("man")); // Install into install.man. + path (b, dir_path ("man1")); // Install into install.man1. } } } diff --git a/build/install/rule.cxx b/build/install/rule.cxx index f14547c..8f67001 100644 --- a/build/install/rule.cxx +++ b/build/install/rule.cxx @@ -21,48 +21,23 @@ namespace build { namespace install { - // Lookup the install or install.* variable and check that - // the value makes sense. Return NULL if not found or if - // the value is the special 'false' name (which means do - // not install). T is either scope or target. + // Lookup the install or install.* variable. Return NULL if + // not found or if the value is the special 'false' name (which + // means do not install). T is either scope or target. // template - static const name* - lookup (T& t, const char* var) + static const dir_path* + lookup (T& t, const string& var) { - auto v (t[var]); + auto l (t[var]); - const name* r (nullptr); + if (!l) + return nullptr; - if (!v) - return r; - - const list_value& lv (v.template as ()); - - if (lv.empty ()) - return r; - - if (lv.size () == 1) - { - const name& n (lv.front ()); - - if (n.simple () && n.value == "false") - return r; - - if (!n.empty () && (n.simple () || n.directory ())) - return &n; - } - - fail << "expected directory instead of '" << lv << "' in " - << "the " << var << " variable"; - - return r; + const dir_path& r (as (*l)); + return r.simple () && r.string () == "false" ? nullptr : &r; } - template - static inline const name* - lookup (T& t, const string& var) {return lookup (t, var.c_str ());} - match_result rule:: match (action a, target& t, const std::string&) const { @@ -185,8 +160,8 @@ namespace build struct install_dir { dir_path dir; - string cmd; - const list_value* options {nullptr}; + string cmd; //@@ VAR type + const_strings_value options {nullptr}; string mode; string dir_mode; }; @@ -200,8 +175,8 @@ namespace build cstrings args {base.cmd.c_str (), "-d"}; - if (base.options != nullptr) - config::append_options (args, *base.options, "install.*.options"); + if (base.options.d != nullptr) //@@ VAR + config::append_options (args, base.options); args.push_back ("-m"); args.push_back (base.dir_mode.c_str ()); @@ -241,8 +216,8 @@ namespace build cstrings args {base.cmd.c_str ()}; - if (base.options != nullptr) - config::append_options (args, *base.options, "install.*.options"); + if (base.options.d != nullptr) //@@ VAR + config::append_options (args, base.options); args.push_back ("-m"); args.push_back (base.mode.c_str ()); @@ -277,10 +252,9 @@ namespace build // creating leading directories as necessary. // static install_dir - resolve (scope& s, const name& n, const string* var = nullptr) + resolve (scope& s, dir_path d, const string* var = nullptr) { install_dir r; - dir_path d (n.simple () ? dir_path (n.value) : n.dir); if (d.absolute ()) { @@ -298,11 +272,11 @@ namespace build // as the installation directory name, e.g., bin, sbin, lib, // etc. Look it up and recurse. // - const string& dn (*d.begin ()); - const string var ("install." + dn); - if (const name* n = lookup (s, var)) + const string& sn (*d.begin ()); + const string var ("install." + sn); + if (const dir_path* dn = lookup (s, var)) { - r = resolve (s, *n, &var); + r = resolve (s, *dn, &var); d = r.dir / dir_path (++d.begin (), d.end ()); d.normalize (); @@ -310,7 +284,7 @@ namespace build install (r, d); // install -d } else - fail << "unknown installation directory name " << dn << + fail << "unknown installation directory name " << sn << info << "did you forget to specify config." << var << "?"; } @@ -320,12 +294,10 @@ namespace build // if (var != nullptr) { - if (auto v = s[*var + ".cmd"]) r.cmd = v.as (); - if (auto v = s[*var + ".mode"]) r.mode = v.as (); - if (auto v = s[*var + ".dir_mode"]) - r.dir_mode = v.as (); - if (auto v = s[*var + ".options"]) - r.options = &v.as (); + if (auto l = s[*var + ".cmd"]) r.cmd = as (*l); + if (auto l = s[*var + ".mode"]) r.mode = as (*l); + if (auto l = s[*var + ".dir_mode"]) r.dir_mode = as (*l); + if (auto l = s[*var + ".options"]) r.options = as (*l); } // Set defaults for unspecified components. @@ -351,12 +323,12 @@ namespace build // install_dir d ( resolve (t.base_scope (), - t["install"].as ())); // We know it's there. + as (*t["install"]))); // We know it's there. // Override mode if one was specified. // - if (auto v = t["install.mode"]) - d.mode = v.as (); + if (auto l = t["install.mode"]) + d.mode = as (*l); install (d, ft); return (r |= target_state::changed); diff --git a/build/install/utility b/build/install/utility index 5c703fc..9bc41f1 100644 --- a/build/install/utility +++ b/build/install/utility @@ -5,7 +5,11 @@ #ifndef BUILD_INSTALL_UTILITY #define BUILD_INSTALL_UTILITY +#include +#include + #include +#include namespace build { @@ -15,20 +19,20 @@ namespace build // template inline void - path (scope& s, const char* v) + path (scope& s, dir_path d) { - auto p (s.target_vars[T::static_type]["*"].assign ("install")); - if (p.second) // Already set by the user? - p.first = v; + auto r (s.target_vars[T::static_type]["*"].assign ("install")); + if (r.second) // Already set by the user? + r.first.get () = std::move (d); } template inline void - mode (scope& s, const char* v) + mode (scope& s, std::string m) { - auto m (s.target_vars[T::static_type]["*"].assign ("install.mode")); - if (m.second) // Already set by the user? - m.first = v; + auto r (s.target_vars[T::static_type]["*"].assign ("install.mode")); + if (r.second) // Already set by the user? + r.first.get () = std::move (m); } } } -- cgit v1.1