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/rule.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/rule.cxx')
-rw-r--r-- | build/rule.cxx | 70 |
1 files changed, 32 insertions, 38 deletions
diff --git a/build/rule.cxx b/build/rule.cxx index b00901e..2373033 100644 --- a/build/rule.cxx +++ b/build/rule.cxx @@ -6,6 +6,7 @@ #include <utility> // move() +#include <build/algorithm> #include <build/diagnostics> using namespace std; @@ -21,21 +22,16 @@ namespace build { // @@ TODO: // - // - need to assign path somehow. Get (potentially several) - // extensions from target type? Maybe target type should - // generate a list of potential paths that we can try here. - // What if none of them exist, which one do we use? Should - // there be a default extension, perhaps configurable via - // a variable? + // - need to try all the target-type-specific extensions, just + // like search_existing_file(). // - path_target& pt (dynamic_cast<path_target&> (t)); if (pt.path ().empty ()) { path p (t.dir / path (pt.name)); - // @@ TMP: derive file name by appending target name as an extension? + // @@ TMP: target name as an extension. // const string& e (pt.ext != nullptr ? *pt.ext : pt.type ().name); @@ -45,6 +41,10 @@ namespace build p += e; } + // While strictly speaking we shouldn't do this in match(), + // no other rule should ever be ambiguous with this fallback + // one. + // pt.path (move (p)); } @@ -52,8 +52,12 @@ namespace build } recipe path_rule:: - select (target&, void*) const + select (target& t, void*) const { + // Search and match all the prerequisites. + // + search_and_match (t); + return &update; } @@ -62,38 +66,32 @@ namespace build { // Make sure the target is not older than any of its prerequisites. // - path_target& pt (dynamic_cast<path_target&> (t)); - timestamp mt (pt.mtime ()); + timestamp mt (dynamic_cast<path_target&> (t).mtime ()); for (const prerequisite& p: t.prerequisites) { - const target& pt (*p.target); // Should be resolved at this stage. + target& pt (*p.target); + target_state ts (update (pt)); - // If this is an mtime-based target, then simply compare timestamps. + // If this is an mtime-based target, then compare timestamps. // - if (auto mtp = dynamic_cast<const mtime_target*> (&pt)) + if (auto mpt = dynamic_cast<const mtime_target*> (&pt)) { - if (mt < mtp->mtime ()) - { - error << "no rule to update target " << t << - info << "prerequisite " << pt << " is ahead of " << t - << " by " << (mtp->mtime () - mt); + timestamp mp (mpt->mtime ()); - return target_state::failed; - } + if (mt < mp) + fail << "no recipe to update target " << t << + info << "prerequisite " << pt << " is ahead of " << t + << " by " << (mp - mt); } else { // Otherwise we assume the prerequisite is newer if it was updated. // - if (pt.state () == target_state::updated) - { - error << "no rule to update target " << t << + if (ts == target_state::updated) + fail << "no recipe to update target " << t << info << "prerequisite " << pt << " is ahead of " << t - << " because it was updated"; - - return target_state::failed; - } + << " because it was updated"; } } @@ -109,22 +107,18 @@ namespace build } recipe dir_rule:: - select (target&, void*) const + select (target& t, void*) const { + search_and_match (t); return &update; } target_state dir_rule:: update (target& t) { - for (const prerequisite& p: t.prerequisites) - { - auto ts (p.target->state ()); - - if (ts != target_state::uptodate) - return ts; // updated or failed - } - - return target_state::uptodate; + // Return updated if any of our prerequsites were updated and + // uptodate otherwise. + // + return update_prerequisites (t); } } |