aboutsummaryrefslogtreecommitdiff
path: root/build/install
diff options
context:
space:
mode:
Diffstat (limited to 'build/install')
-rw-r--r--build/install/module26
-rw-r--r--build/install/module.cxx188
-rw-r--r--build/install/operation18
-rw-r--r--build/install/operation.cxx32
-rw-r--r--build/install/rule49
-rw-r--r--build/install/rule.cxx410
-rw-r--r--build/install/utility40
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