From bbd0f3bb21442a2833916110cbe8e9a07e9f4c1f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 31 Jul 2015 12:52:20 +0200 Subject: Essential install module functionality --- build/cxx/compile | 2 ++ build/cxx/compile.cxx | 12 ++++--- build/cxx/install | 29 +++++++++++++++++ build/cxx/install.cxx | 48 ++++++++++++++++++++++++++++ build/cxx/link | 2 ++ build/cxx/link.cxx | 2 ++ build/cxx/module.cxx | 86 ++++++++++++++++++++++++++++++--------------------- 7 files changed, 141 insertions(+), 40 deletions(-) create mode 100644 build/cxx/install create mode 100644 build/cxx/install.cxx (limited to 'build/cxx') diff --git a/build/cxx/compile b/build/cxx/compile index 1cc91ab..cb44829 100644 --- a/build/cxx/compile +++ b/build/cxx/compile @@ -23,6 +23,8 @@ namespace build static target_state perform_update (action, target&); + + static compile instance; }; } } diff --git a/build/cxx/compile.cxx b/build/cxx/compile.cxx index ae1ebe2..d89aaac 100644 --- a/build/cxx/compile.cxx +++ b/build/cxx/compile.cxx @@ -649,12 +649,14 @@ namespace build // There would normally be a lot of headers for every source // file (think all the system headers) and this can get // expensive. At the same time, most of these headers are - // existing files that we will never be updating (again, + // existing files that we will never be updated (again, // system headers, for example) and the rule that will match - // them is fallback file_rule. So we are going to do a little - // fast-path optimization by detecting this common case. + // them is fallback file_rule. That rule has an optimization + // in that it returns noop_recipe (which causes the target + // state to be automatically set to unchanged) if the file + // is known to be up to date. // - if (!file_rule::uptodate (a, pt)) + if (pt.state () != target_state::unchanged) { // We only want to restart if our call to execute() actually // caused an update. In particular, the target could already @@ -787,5 +789,7 @@ namespace build throw failed (); } } + + compile compile::instance; } } diff --git a/build/cxx/install b/build/cxx/install new file mode 100644 index 0000000..3a6f463 --- /dev/null +++ b/build/cxx/install @@ -0,0 +1,29 @@ +// file : build/cxx/install -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD_CXX_INSTALL +#define BUILD_CXX_INSTALL + +#include +#include + +namespace build +{ + namespace cxx + { + class install: public build::install::rule + { + public: + virtual bool + filter (action, target&, prerequisite_member) const; + + virtual match_result + match (action, target&, const std::string&) const; + + static install instance; + }; + } +} + +#endif // BUILD_CXX_INSTALL diff --git a/build/cxx/install.cxx b/build/cxx/install.cxx new file mode 100644 index 0000000..b623349 --- /dev/null +++ b/build/cxx/install.cxx @@ -0,0 +1,48 @@ +// file : build/cxx/install.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +#include +#include + +using namespace std; + +namespace build +{ + namespace cxx + { + using namespace bin; + + bool install:: + filter (action, target& t, prerequisite_member p) const + { + // Don't install executable's prerequisite headers. + // + if (t.is_a () && + (p.is_a () || p.is_a () || p.is_a () || p.is_a ())) + return false; + + return true; + } + + match_result install:: + match (action a, target& t, const std::string& hint) const + { + // @@ How do we split the hint between the two? + // + + // We only want to handle installation if we are also the + // ones building this target. So first run link's match(). + // + match_result r (link::instance.match (a, t, hint)); + + return r ? install::rule::match (a, t, "") : r; + } + + install install::instance; + } +} diff --git a/build/cxx/link b/build/cxx/link index 75223fc..5d3d29e 100644 --- a/build/cxx/link +++ b/build/cxx/link @@ -28,6 +28,8 @@ namespace build static target_state perform_update (action, target&); + static link instance; + private: friend class compile; diff --git a/build/cxx/link.cxx b/build/cxx/link.cxx index 145a085..5c3a515 100644 --- a/build/cxx/link.cxx +++ b/build/cxx/link.cxx @@ -835,5 +835,7 @@ namespace build throw failed (); } } + + link link::instance; } } diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx index 882d4b0..1e6ed8a 100644 --- a/build/cxx/module.cxx +++ b/build/cxx/module.cxx @@ -11,12 +11,14 @@ #include #include +#include #include #include #include #include +#include using namespace std; using namespace butl; @@ -25,29 +27,26 @@ namespace build { namespace cxx { - compile compile_; - link link_; - extern "C" void - cxx_init (scope& root, - scope& base, + cxx_init (scope& r, + scope& b, const location& l, std::unique_ptr&, bool first) { tracer trace ("cxx::init"); - level4 ([&]{trace << "for " << base.path ();}); + level4 ([&]{trace << "for " << b.path ();}); // Initialize the bin module. Only do this if it hasn't already // been loaded so that we don't overwrite user's bin.* settings. // - if (base.find_target_type ("obj") == nullptr) - load_module ("bin", root, base, l); + if (b.find_target_type ("obj") == nullptr) + load_module ("bin", r, b, l); // Register target types. // { - auto& tts (base.target_types); + auto& tts (b.target_types); tts.insert (); tts.insert (); @@ -63,27 +62,31 @@ namespace build { using namespace bin; - auto& rs (base.rules); + auto& rs (b.rules); + + rs.insert (default_id, "cxx.compile", compile::instance); + rs.insert (update_id, "cxx.compile", compile::instance); + rs.insert (clean_id, "cxx.compile", compile::instance); - rs.insert (default_id, "cxx.compile", compile_); - rs.insert (update_id, "cxx.compile", compile_); - rs.insert (clean_id, "cxx.compile", compile_); + rs.insert (default_id, "cxx.compile", compile::instance); + rs.insert (update_id, "cxx.compile", compile::instance); + rs.insert (clean_id, "cxx.compile", compile::instance); - rs.insert (default_id, "cxx.compile", compile_); - rs.insert (update_id, "cxx.compile", compile_); - rs.insert (clean_id, "cxx.compile", compile_); + rs.insert (default_id, "cxx.link", link::instance); + rs.insert (update_id, "cxx.link", link::instance); + rs.insert (clean_id, "cxx.link", link::instance); - rs.insert (default_id, "cxx.link", link_); - rs.insert (update_id, "cxx.link", link_); - rs.insert (clean_id, "cxx.link", link_); + rs.insert (default_id, "cxx.link", link::instance); + rs.insert (update_id, "cxx.link", link::instance); + rs.insert (clean_id, "cxx.link", link::instance); - rs.insert (default_id, "cxx.link", link_); - rs.insert (update_id, "cxx.link", link_); - rs.insert (clean_id, "cxx.link", link_); + rs.insert (default_id, "cxx.link", link::instance); + rs.insert (update_id, "cxx.link", link::instance); + rs.insert (clean_id, "cxx.link", link::instance); - rs.insert (default_id, "cxx.link", link_); - rs.insert (update_id, "cxx.link", link_); - rs.insert (clean_id, "cxx.link", link_); + rs.insert (install_id, "cxx.install", install::instance); + rs.insert (install_id, "cxx.install", install::instance); + rs.insert (install_id, "cxx.install", install::instance); } // Configure. @@ -93,13 +96,13 @@ namespace build // if (first) { - auto r (config::required (root, "config.cxx", "g++")); + auto p (config::required (r, "config.cxx", "g++")); // If we actually set a new value, test it by trying to execute. // - if (r.second) + if (p.second) { - const string& cxx (r.first); + const string& cxx (p.first); const char* args[] = {cxx.c_str (), "-dumpversion", nullptr}; if (verb) @@ -152,17 +155,28 @@ namespace build // using cxx // cxx.coptions += # Note: '+='. // - if (auto* v = config::optional (root, "config.cxx.poptions")) - base.assign ("cxx.poptions") += *v; + if (auto* v = config::optional (r, "config.cxx.poptions")) + b.assign ("cxx.poptions") += *v; - if (auto* v = config::optional (root, "config.cxx.coptions")) - base.assign ("cxx.coptions") += *v; + if (auto* v = config::optional (r, "config.cxx.coptions")) + b.assign ("cxx.coptions") += *v; - if (auto* v = config::optional (root, "config.cxx.loptions")) - base.assign ("cxx.loptions") += *v; + if (auto* v = config::optional (r, "config.cxx.loptions")) + b.assign ("cxx.loptions") += *v; - if (auto* v = config::optional (root, "config.cxx.libs")) - base.assign ("cxx.libs") += *v; + if (auto* v = config::optional (r, "config.cxx.libs")) + b.assign ("cxx.libs") += *v; + + // Configure "installability" of our target types. + // + { + using build::install::path; + + path (b, "include"); // Install into install.include. + path (b, "include"); + path (b, "include"); + path (b, "include"); + } } } } -- cgit v1.1