diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-23 15:56:03 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-23 15:56:03 +0200 |
commit | fefe0657f29b8db782f7a722dd46b074b991cf08 (patch) | |
tree | 62008e350c4f6048a68444fe50c47281643d276a /build/target.cxx | |
parent | 962cb1040670977085f0a187ecc6730608578151 (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.cxx | 162 |
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 + }; } |