diff options
Diffstat (limited to 'build/install')
-rw-r--r-- | build/install/module | 26 | ||||
-rw-r--r-- | build/install/module.cxx | 188 | ||||
-rw-r--r-- | build/install/operation | 18 | ||||
-rw-r--r-- | build/install/operation.cxx | 32 | ||||
-rw-r--r-- | build/install/rule | 49 | ||||
-rw-r--r-- | build/install/rule.cxx | 410 | ||||
-rw-r--r-- | build/install/utility | 40 |
7 files changed, 0 insertions, 763 deletions
diff --git a/build/install/module b/build/install/module deleted file mode 100644 index 7a814c8..0000000 --- a/build/install/module +++ /dev/null @@ -1,26 +0,0 @@ -// file : build/install/module -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_INSTALL_MODULE -#define BUILD_INSTALL_MODULE - -#include <build/types> -#include <build/utility> - -#include <build/module> - -namespace build -{ - namespace install - { - extern "C" void - install_boot (scope&, const location&, unique_ptr<module>&); - - extern "C" bool - install_init ( - scope&, scope&, const location&, unique_ptr<module>&, bool, bool); - } -} - -#endif // BUILD_INSTALL_MODULE diff --git a/build/install/module.cxx b/build/install/module.cxx deleted file mode 100644 index 706f367..0000000 --- a/build/install/module.cxx +++ /dev/null @@ -1,188 +0,0 @@ -// file : build/install/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/install/module> - -#include <build/scope> -#include <build/target> -#include <build/rule> -#include <build/operation> -#include <build/diagnostics> - -#include <build/config/utility> - -#include <build/install/rule> -#include <build/install/utility> -#include <build/install/operation> - -using namespace std; -using namespace butl; - -namespace build -{ - namespace install - { - // Set install.<name>.* values based on config.install.<name>.* ones - // or the defaults. If none of config.install.* values were specified, - // then we do omitted/delayed configuration. Note that we still need - // to set all the install.* values to defaults, as if we had the - // default configuration. - // - // If override is true, then override values that came from outer - // configurations. We have to do this for paths that contain the - // package name. - // - template <typename T> - static void - set_var (bool spec, - scope& r, - const char* name, - const char* var, - const T* dv, - bool override = false) - { - string vn; - const value* cv (nullptr); - - if (spec) - { - vn = "config.install."; - vn += name; - vn += var; - const variable& vr ( - var_pool.find (move (vn), &value_traits<T>::value_type)); - - cv = dv != nullptr - ? &config::required (r, vr, *dv, override).first.get () - : &config::optional (r, vr); - } - - vn = "install."; - vn += name; - vn += var; - const variable& vr ( - var_pool.find (move (vn), &value_traits<T>::value_type)); - - value& v (r.assign (vr)); - - if (spec) - { - if (*cv && !cv->empty ()) - v = *cv; - } - else - { - if (dv != nullptr) - v = *dv; - } - } - - static void - set_dir (bool s, // specified - scope& r, // root scope - const char* n, // var name - const string& ps, // path (as string) - const string& fm = string (), // file mode - const string& dm = string (), // dir mode - const string& c = string (), // command - bool o = false) // override - { - dir_path p (ps); - set_var (s, r, n, "", p.empty () ? nullptr : &p, o); - set_var (s, r, n, ".mode", fm.empty () ? nullptr : &fm); - set_var (s, r, n, ".dir_mode", dm.empty () ? nullptr : &dm); - set_var<string> (s, r, n, ".sudo", nullptr); - set_var (s, r, n, ".cmd", c.empty () ? nullptr : &c); - set_var<strings> (s, r, n, ".options", nullptr); - } - - static alias_rule alias_; - static file_rule file_; - - extern "C" void - install_boot (scope& r, const location&, unique_ptr<module>&) - { - tracer trace ("install::boot"); - - level5 ([&]{trace << "for " << r.out_path ();}); - - // Register the install operation. - // - r.operations.insert (install_id, install); - } - - extern "C" bool - install_init (scope& r, - scope& b, - const location& l, - unique_ptr<module>&, - bool first, - bool) - { - tracer trace ("install::init"); - - if (!first) - { - warn (l) << "multiple install module initializations"; - return true; - } - - const dir_path& out_root (r.out_path ()); - level5 ([&]{trace << "for " << out_root;}); - - // Enter module variables. - // - // Note that the set_dir() calls below enter some more. - // - if (first) - { - auto& v (var_pool); - - v.find ("install", dir_path_type); - } - - // Register our alias and file installer rule. - // - b.rules.insert<alias> (perform_install_id, "install.alias", alias_); - b.rules.insert<file> (perform_install_id, "install.file", file_); - - // Configuration. - // - // Note that we don't use any defaults for root -- the location - // must be explicitly specified or the installer will complain - // if and when we try to install. - // - if (first) - { - bool s (config::specified (r, "config.install")); - const string& n (as<string> (*r["project"])); - - set_dir (s, r, "root", "", "", "755", "install"); - set_dir (s, r, "data_root", "root", "644"); - set_dir (s, r, "exec_root", "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, "", "", "", true); - - set_dir (s, r, "data", "data_root/share/" + n, "", "", "", true); - set_dir (s, r, "include", "data_root/include"); - - set_dir (s, r, "doc", "data_root/share/doc/" + n, "", "", "", true); - set_dir (s, r, "man", "data_root/share/man"); - - set_dir (s, r, "man1", "man/man1"); - } - - // Configure "installability" for built-in target types. - // - path<doc> (b, dir_path ("doc")); // Install into install.doc. - path<man> (b, dir_path ("man")); // Install into install.man. - path<man1> (b, dir_path ("man1")); // Install into install.man1. - - return true; - } - } -} diff --git a/build/install/operation b/build/install/operation deleted file mode 100644 index 2763d10..0000000 --- a/build/install/operation +++ /dev/null @@ -1,18 +0,0 @@ -// file : build/install/operation -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_INSTALL_OPERATION -#define BUILD_INSTALL_OPERATION - -#include <build/operation> - -namespace build -{ - namespace install - { - extern operation_info install; - } -} - -#endif // BUILD_INSTALL_OPERATION diff --git a/build/install/operation.cxx b/build/install/operation.cxx deleted file mode 100644 index 1246671..0000000 --- a/build/install/operation.cxx +++ /dev/null @@ -1,32 +0,0 @@ -// file : build/install/operation.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/install/operation> - -using namespace std; -using namespace butl; - -namespace build -{ - namespace install - { - static operation_id - install_pre (meta_operation_id mo) - { - // Run update as a pre-operation, unless we are disfiguring. - // - return mo != disfigure_id ? update_id : 0; - } - - operation_info install { - "install", - "install", - "installing", - "has nothing to install", // We cannot "be installed". - execution_mode::first, - &install_pre, - nullptr - }; - } -} diff --git a/build/install/rule b/build/install/rule deleted file mode 100644 index 54014e1..0000000 --- a/build/install/rule +++ /dev/null @@ -1,49 +0,0 @@ -// file : build/install/rule -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_INSTALL_RULE -#define BUILD_INSTALL_RULE - -#include <build/rule> -#include <build/types> -#include <build/target> -#include <build/operation> - -namespace build -{ - namespace install - { - class alias_rule: public rule - { - public: - virtual match_result - match (action, target&, const std::string&) const; - - virtual recipe - apply (action, target&, const match_result&) const; - }; - - class file_rule: public rule - { - public: - virtual match_result - match (action, target&, const std::string&) const; - - // Return NULL if this prerequisite should be ignored and pointer to its - // target otherwise. The default implementation ignores prerequsites that - // are outside of this target's project. - // - virtual target* - filter (action, target&, prerequisite_member) const; - - virtual recipe - apply (action, target&, const match_result&) const; - - static target_state - perform_install (action, target&); - }; - } -} - -#endif // BUILD_INSTALL_RULE diff --git a/build/install/rule.cxx b/build/install/rule.cxx deleted file mode 100644 index fa648b5..0000000 --- a/build/install/rule.cxx +++ /dev/null @@ -1,410 +0,0 @@ -// file : build/install/rule.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/install/rule> - -#include <butl/process> -#include <butl/filesystem> - -#include <build/scope> -#include <build/target> -#include <build/algorithm> -#include <build/diagnostics> - -#include <build/config/utility> - -using namespace std; -using namespace butl; - -namespace build -{ - namespace install - { - // 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 <typename T> - static const dir_path* - lookup (T& t, const string& var) - { - auto l (t[var]); - - if (!l) - return nullptr; - - const dir_path& r (as<dir_path> (*l)); - return r.simple () && r.string () == "false" ? nullptr : &r; - } - - // alias_rule - // - match_result alias_rule:: - match (action, target& t, const std::string&) const - { - return t; - } - - recipe alias_rule:: - apply (action a, target& t, const match_result&) const - { - tracer trace ("install::alias_rule::apply"); - - for (prerequisite p: group_prerequisites (t)) - { - target& pt (search (p)); - - // Check if this prerequisite is explicitly "not installable", - // that is, there is the 'install' variable and its value is - // false. - // - // At first, this might seem redundand since we could have let - // the file_rule below take care of it. The nuance is this: this - // prerequsite can be in a different subproject that hasn't loaded - // the install module (and therefore has no file_rule registered). - // The typical example would be the 'tests' subproject. - // - auto l (pt["install"]); - - if (l && as<dir_path> (*l).string () == "false") - { - level5 ([&]{trace << "ignoring " << pt;}); - continue; - } - - build::match (a, pt); - t.prerequisite_targets.push_back (&pt); - } - - return default_recipe; - } - - // file_rule - // - - match_result file_rule:: - match (action a, target& t, const std::string&) const - { - // First determine if this target should be installed (called - // "installable" for short). - // - if (lookup (t, "install") == nullptr) - // If this is the update pre-operation, signal that we don't match so - // that some other rule can take care of it. - // - return a.operation () == update_id ? nullptr : match_result (t, false); - - match_result mr (t, true); - - // If this is the update pre-operation, change the recipe action - // to (update, 0) (i.e., "unconditional update"). - // - if (a.operation () == update_id) - mr.recipe_action = action (a.meta_operation (), update_id); - - return mr; - } - - target* file_rule:: - filter (action, target& t, prerequisite_member p) const - { - target& pt (p.search ()); - return pt.in (t.root_scope ()) ? &pt : nullptr; - } - - recipe file_rule:: - apply (action a, target& t, const match_result& mr) const - { - if (!mr.bvalue) // Not installable. - return noop_recipe; - - // Ok, if we are here, then this means: - // - // 1. This target is installable. - // 2. The action is either - // a. (perform, install, 0) or - // b. (*, update, install) - // - // In both cases, the next step is to search, match, and collect - // all the installable prerequisites. - // - // @@ Perhaps if [noinstall] will be handled by the - // group_prerequisite_members machinery, then we can just - // run standard search_and_match()? Will need an indicator - // that it was forced (e.g., [install]) for filter() below. - // - for (prerequisite_member p: group_prerequisite_members (a, t)) - { - // Ignore unresolved targets that are imported from other projects. - // We are definitely not installing those. - // - if (p.proj () != nullptr) - continue; - - // Let a customized rule have its say. - // - target* pt (filter (a, t, p)); - if (pt == nullptr) - continue; - - // See if the user instructed us not to install it. - // - auto l ((*pt)["install"]); - if (l && as<dir_path> (*l).string () == "false") - continue; - - build::match (a, *pt); - - // If the matched rule returned noop_recipe, then the target - // state will be set to unchanged as an optimization. Use this - // knowledge to optimize things on our side as well since this - // will help a lot in case of any static installable content - // (headers, documentation, etc). - // - if (pt->state () != target_state::unchanged) - t.prerequisite_targets.push_back (pt); - else - unmatch (a, *pt); // No intent to execute. - } - - // This is where we diverge depending on the operation. In the - // update pre-operation, we need to make sure that this target - // as well as all its installable prerequisites are up to date. - // - if (a.operation () == update_id) - { - // Save the prerequisite targets that we found since the - // call to match_delegate() below will wipe them out. - // - target::prerequisite_targets_type p; - - if (!t.prerequisite_targets.empty ()) - p.swap (t.prerequisite_targets); - - // Find the "real" update rule, that is, the rule that would - // have been found if we signalled that we do not match from - // match() above. - // - recipe d (match_delegate (a, t).first); - - // If we have no installable prerequisites, then simply redirect - // to it. - // - if (p.empty ()) - return d; - - // Ok, the worst case scenario: we need to cause update of - // prerequisite targets and also delegate to the real update. - // - return [pt = move (p), dr = move (d)] - (action a, target& t) mutable -> target_state - { - // Do the target update first. - // - target_state r (execute_delegate (dr, a, t)); - - // Swap our prerequisite targets back in and execute. - // - t.prerequisite_targets.swap (pt); - r |= execute_prerequisites (a, t); - pt.swap (t.prerequisite_targets); // In case we get re-executed. - - return r; - }; - } - else - return &perform_install; - } - - struct install_dir - { - dir_path dir; - string sudo; - string cmd; //@@ VAR type - const_strings_value options {nullptr}; - string mode; - string dir_mode; - }; - - // install -d <dir> - // - static void - install (const install_dir& base, const dir_path& d) - { - path reld (relative (d)); - - cstrings args; - - if (!base.sudo.empty ()) - args.push_back (base.sudo.c_str ()); - - args.push_back (base.cmd.c_str ()); - args.push_back ("-d"); - - if (base.options.d != nullptr) //@@ VAR - config::append_options (args, base.options); - - args.push_back ("-m"); - args.push_back (base.dir_mode.c_str ()); - args.push_back (reld.string ().c_str ()); - args.push_back (nullptr); - - if (verb >= 2) - print_process (args); - else if (verb) - text << "install " << d; - - try - { - process pr (args.data ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e.what (); - - if (e.child ()) - exit (1); - - throw failed (); - } - } - - // install <file> <dir> - // - static void - install (const install_dir& base, file& t) - { - path reld (relative (base.dir)); - path relf (relative (t.path ())); - - cstrings args; - - if (!base.sudo.empty ()) - args.push_back (base.sudo.c_str ()); - - args.push_back (base.cmd.c_str ()); - - if (base.options.d != nullptr) //@@ VAR - config::append_options (args, base.options); - - args.push_back ("-m"); - args.push_back (base.mode.c_str ()); - args.push_back (relf.string ().c_str ()); - args.push_back (reld.string ().c_str ()); - args.push_back (nullptr); - - if (verb >= 2) - print_process (args); - else if (verb) - text << "install " << t; - - try - { - process pr (args.data ()); - - if (!pr.wait ()) - throw failed (); - } - catch (const process_error& e) - { - error << "unable to execute " << args[0] << ": " << e.what (); - - if (e.child ()) - exit (1); - - throw failed (); - } - } - - // Resolve installation directory name to absolute directory path, - // creating leading directories as necessary. - // - static install_dir - resolve (scope& s, dir_path d, const string* var = nullptr) - { - install_dir r; - - if (d.absolute ()) - { - d.normalize (); - - // Make sure it already exists (this will normally be - // install.root with everything else defined in term of it). - // - if (!dir_exists (d)) - fail << "installation directory " << d << " does not exist"; - } - else - { - // If it is relative, then the first component is treated - // as the installation directory name, e.g., bin, sbin, lib, - // etc. Look it up and recurse. - // - const string& sn (*d.begin ()); - const string var ("install." + sn); - if (const dir_path* dn = lookup (s, var)) - { - r = resolve (s, *dn, &var); - d = r.dir / dir_path (++d.begin (), d.end ()); - d.normalize (); - - if (!dir_exists (d)) - install (r, d); // install -d - } - else - fail << "unknown installation directory name " << sn << - info << "did you forget to specify config." << var << "?"; - } - - r.dir = move (d); - - // Override components in install_dir if we have our own. - // - if (var != nullptr) - { - if (auto l = s[*var + ".sudo"]) r.sudo = as<string> (*l); - if (auto l = s[*var + ".cmd"]) r.cmd = as<string> (*l); - if (auto l = s[*var + ".mode"]) r.mode = as<string> (*l); - if (auto l = s[*var + ".dir_mode"]) r.dir_mode = as<string> (*l); - if (auto l = s[*var + ".options"]) r.options = as<strings> (*l); - } - - // Set defaults for unspecified components. - // - if (r.cmd.empty ()) r.cmd = "install"; - if (r.mode.empty ()) r.mode = "644"; - if (r.dir_mode.empty ()) r.dir_mode = "755"; - - return r; - } - - target_state file_rule:: - perform_install (action a, target& t) - { - file& ft (static_cast<file&> (t)); - assert (!ft.path ().empty ()); // Should have been assigned by update. - - // First handle installable prerequisites. - // - target_state r (execute_prerequisites (a, t)); - - // Resolve and, if necessary, create target directory. - // - install_dir d ( - resolve (t.base_scope (), - as<dir_path> (*t["install"]))); // We know it's there. - - // Override mode if one was specified. - // - if (auto l = t["install.mode"]) - d.mode = as<string> (*l); - - install (d, ft); - return (r |= target_state::changed); - } - } -} diff --git a/build/install/utility b/build/install/utility deleted file mode 100644 index 9bc41f1..0000000 --- a/build/install/utility +++ /dev/null @@ -1,40 +0,0 @@ -// file : build/install/utility -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_INSTALL_UTILITY -#define BUILD_INSTALL_UTILITY - -#include <string> -#include <utility> - -#include <build/scope> -#include <build/types> - -namespace build -{ - namespace install - { - // Set install path, mode for a target type. - // - template <typename T> - inline void - path (scope& s, dir_path d) - { - 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 <typename T> - inline void - mode (scope& s, std::string m) - { - 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); - } - } -} - -#endif // BUILD_INSTALL_UTILITY |