aboutsummaryrefslogtreecommitdiff
path: root/build/cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-31 12:52:20 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-31 12:52:20 +0200
commitbbd0f3bb21442a2833916110cbe8e9a07e9f4c1f (patch)
treed25de6f2bcfa4b6cabe1fd55a1b8f508005de4c1 /build/cxx
parent729b56300c441a0d63c7d2013eb5a881211d352b (diff)
Essential install module functionality
Diffstat (limited to 'build/cxx')
-rw-r--r--build/cxx/compile2
-rw-r--r--build/cxx/compile.cxx12
-rw-r--r--build/cxx/install29
-rw-r--r--build/cxx/install.cxx48
-rw-r--r--build/cxx/link2
-rw-r--r--build/cxx/link.cxx2
-rw-r--r--build/cxx/module.cxx86
7 files changed, 141 insertions, 40 deletions
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 <build/types>
+#include <build/install/rule>
+
+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 <build/cxx/install>
+
+#include <build/bin/target>
+
+#include <build/cxx/target>
+#include <build/cxx/link>
+
+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<exe> () &&
+ (p.is_a<hxx> () || p.is_a<ixx> () || p.is_a<txx> () || p.is_a<h> ()))
+ 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 <build/diagnostics>
#include <build/config/utility>
+#include <build/install/utility>
#include <build/bin/target>
#include <build/cxx/target>
#include <build/cxx/compile>
#include <build/cxx/link>
+#include <build/cxx/install>
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<module>&,
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<h> ();
tts.insert<c> ();
@@ -63,27 +62,31 @@ namespace build
{
using namespace bin;
- auto& rs (base.rules);
+ auto& rs (b.rules);
+
+ rs.insert<obja> (default_id, "cxx.compile", compile::instance);
+ rs.insert<obja> (update_id, "cxx.compile", compile::instance);
+ rs.insert<obja> (clean_id, "cxx.compile", compile::instance);
- rs.insert<obja> (default_id, "cxx.compile", compile_);
- rs.insert<obja> (update_id, "cxx.compile", compile_);
- rs.insert<obja> (clean_id, "cxx.compile", compile_);
+ rs.insert<objso> (default_id, "cxx.compile", compile::instance);
+ rs.insert<objso> (update_id, "cxx.compile", compile::instance);
+ rs.insert<objso> (clean_id, "cxx.compile", compile::instance);
- rs.insert<objso> (default_id, "cxx.compile", compile_);
- rs.insert<objso> (update_id, "cxx.compile", compile_);
- rs.insert<objso> (clean_id, "cxx.compile", compile_);
+ rs.insert<exe> (default_id, "cxx.link", link::instance);
+ rs.insert<exe> (update_id, "cxx.link", link::instance);
+ rs.insert<exe> (clean_id, "cxx.link", link::instance);
- rs.insert<exe> (default_id, "cxx.link", link_);
- rs.insert<exe> (update_id, "cxx.link", link_);
- rs.insert<exe> (clean_id, "cxx.link", link_);
+ rs.insert<liba> (default_id, "cxx.link", link::instance);
+ rs.insert<liba> (update_id, "cxx.link", link::instance);
+ rs.insert<liba> (clean_id, "cxx.link", link::instance);
- rs.insert<liba> (default_id, "cxx.link", link_);
- rs.insert<liba> (update_id, "cxx.link", link_);
- rs.insert<liba> (clean_id, "cxx.link", link_);
+ rs.insert<libso> (default_id, "cxx.link", link::instance);
+ rs.insert<libso> (update_id, "cxx.link", link::instance);
+ rs.insert<libso> (clean_id, "cxx.link", link::instance);
- rs.insert<libso> (default_id, "cxx.link", link_);
- rs.insert<libso> (update_id, "cxx.link", link_);
- rs.insert<libso> (clean_id, "cxx.link", link_);
+ rs.insert<exe> (install_id, "cxx.install", install::instance);
+ rs.insert<liba> (install_id, "cxx.install", install::instance);
+ rs.insert<libso> (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 += <overriding options> # Note: '+='.
//
- if (auto* v = config::optional<list_value> (root, "config.cxx.poptions"))
- base.assign ("cxx.poptions") += *v;
+ if (auto* v = config::optional<list_value> (r, "config.cxx.poptions"))
+ b.assign ("cxx.poptions") += *v;
- if (auto* v = config::optional<list_value> (root, "config.cxx.coptions"))
- base.assign ("cxx.coptions") += *v;
+ if (auto* v = config::optional<list_value> (r, "config.cxx.coptions"))
+ b.assign ("cxx.coptions") += *v;
- if (auto* v = config::optional<list_value> (root, "config.cxx.loptions"))
- base.assign ("cxx.loptions") += *v;
+ if (auto* v = config::optional<list_value> (r, "config.cxx.loptions"))
+ b.assign ("cxx.loptions") += *v;
- if (auto* v = config::optional<list_value> (root, "config.cxx.libs"))
- base.assign ("cxx.libs") += *v;
+ if (auto* v = config::optional<list_value> (r, "config.cxx.libs"))
+ b.assign ("cxx.libs") += *v;
+
+ // Configure "installability" of our target types.
+ //
+ {
+ using build::install::path;
+
+ path<hxx> (b, "include"); // Install into install.include.
+ path<ixx> (b, "include");
+ path<txx> (b, "include");
+ path<h> (b, "include");
+ }
}
}
}