aboutsummaryrefslogtreecommitdiff
path: root/build/target.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-02-23 15:56:03 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-02-23 15:56:03 +0200
commitfefe0657f29b8db782f7a722dd46b074b991cf08 (patch)
tree62008e350c4f6048a68444fe50c47281643d276a /build/target.cxx
parent962cb1040670977085f0a187ecc6730608578151 (diff)
Redo rule match/build logic
Now the rule is fully responsible for searching, matching, and building of prerequisites.
Diffstat (limited to 'build/target.cxx')
-rw-r--r--build/target.cxx162
1 files changed, 122 insertions, 40 deletions
diff --git a/build/target.cxx b/build/target.cxx
index 582ae4a..197770c 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -4,6 +4,8 @@
#include <build/target>
+#include <build/scope>
+#include <build/search>
#include <build/context>
#include <build/diagnostics>
@@ -25,7 +27,7 @@ namespace build
if (!t.dir.empty ())
{
- string s (diagnostic_string (t.dir));
+ string s (diag_relative_work (t.dir));
if (!s.empty ())
{
@@ -46,46 +48,68 @@ namespace build
return os;
}
+ static target*
+ search_target (prerequisite& p)
+ {
+ // The default behavior is to look for an existing target in the
+ // prerequisite's directory scope.
+ //
+ return search_existing_target (p);
+ }
+
// target_set
//
auto target_set::
+ find (const key& k, tracer& trace) const -> iterator
+ {
+ iterator i (map_.find (k));
+
+ if (i != end ())
+ {
+ target& t (**i);
+
+ // Update the extension if the existing target has it unspecified.
+ //
+ const string* ext (*k.ext);
+ if (t.ext != ext)
+ {
+ level4 ([&]{
+ diag_record r (trace);
+ r << "assuming target " << t << " is the same as the one with ";
+ if (ext == nullptr)
+ r << "unspecified extension";
+ else if (ext->empty ())
+ r << "no extension";
+ else
+ r << "extension " << *ext;
+ });
+
+ if (ext != nullptr)
+ t.ext = ext;
+ }
+ }
+
+ return i;
+ }
+
+ pair<target&, bool> target_set::
insert (const target_type& tt,
path dir,
std::string name,
const std::string* ext,
- tracer& trace) -> pair<target&, bool>
+ tracer& trace)
{
- //@@ OPT: would be nice to somehow first check if this target is
- // already in the set before allocating a new instance.
+ iterator i (find (key {&tt.id, &dir, &name, &ext}, trace));
- // Find or insert.
- //
- auto r (
- emplace (
- unique_ptr<target> (tt.factory (move (dir), move (name), ext))));
+ if (i != end ())
+ return pair<target&, bool> (**i, false);
- target& t (**r.first);
+ unique_ptr<target> t (tt.factory (move (dir), move (name), ext));
+ i = map_.emplace (
+ make_pair (key {&tt.id, &t->dir, &t->name, &t->ext},
+ move (t))).first;
- // Update the extension if the existing target has it unspecified.
- //
- if (t.ext != ext)
- {
- level4 ([&]{
- diag_record r (trace);
- r << "assuming target " << t << " is the same as the one with ";
- if (ext == nullptr)
- r << "unspecified extension";
- else if (ext->empty ())
- r << "no extension";
- else
- r << "extension " << *ext;
- });
-
- if (ext != nullptr)
- t.ext = ext;
- }
-
- return pair<target&, bool> (t, r.second);
+ return pair<target&, bool> (**i, true);
}
target_set targets;
@@ -101,18 +125,76 @@ namespace build
return path_mtime (path_);
}
- const target_type target::static_type {
- typeid (target), "target", nullptr, nullptr};
+ // file target
+ //
+
+ static target*
+ search_file (prerequisite& p)
+ {
+ // First see if there is an existing target.
+ //
+ if (target* t = search_existing_target (p))
+ return t;
- const target_type mtime_target::static_type {
- typeid (mtime_target), "mtime_target", &target::static_type, nullptr};
+ // Then look for an existing file in this target-type-specific
+ // list of paths (@@ TODO: comes from the variable).
+ //
+ if (p.dir.relative ())
+ {
+ paths sp;
+ sp.push_back (src_out (p.scope.path ())); // src_base
- const target_type path_target::static_type {
- typeid (path_target), "path_target", &mtime_target::static_type, nullptr};
+ return search_existing_file (p, sp);
+ }
+ else
+ return nullptr;
+ }
- const target_type file::static_type {
- typeid (file), "file", &path_target::static_type, &target_factory<file>};
+ // type info
+ //
- const target_type dir::static_type {
- typeid (dir), "dir", &target::static_type, &target_factory<dir>};
+ const target_type target::static_type
+ {
+ typeid (target),
+ "target",
+ nullptr,
+ nullptr,
+ &search_target
+ };
+
+ const target_type mtime_target::static_type
+ {
+ typeid (mtime_target),
+ "mtime_target",
+ &target::static_type,
+ nullptr,
+ target::static_type.search
+ };
+
+ const target_type path_target::static_type
+ {
+ typeid (path_target),
+ "path_target",
+ &mtime_target::static_type,
+ nullptr,
+ mtime_target::static_type.search
+ };
+
+ const target_type file::static_type
+ {
+ typeid (file),
+ "file",
+ &path_target::static_type,
+ &target_factory<file>,
+ &search_file
+ };
+
+ const target_type dir::static_type
+ {
+ typeid (dir),
+ "dir",
+ &target::static_type,
+ &target_factory<dir>,
+ target::static_type.search
+ };
}