From d402bc96297c6ed3dd6ee883dcff8cc39bd01030 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 18 Jan 2017 13:50:58 +0200 Subject: Ignore prerequisite mtimes that are not linker inputs This makes sure, for example, that we don't unnecessarily re-link an executable when its testscript prerequisite is changes. --- build2/cc/compile.cxx | 25 ++++++++++++------------- build2/cc/link.cxx | 26 ++++++++++++++++++-------- 2 files changed, 30 insertions(+), 21 deletions(-) (limited to 'build2/cc') diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 6fd64c2..3318f21 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -888,16 +888,7 @@ namespace build2 } } - if (ts != timestamp_unknown) - { - timestamp mt (pt.mtime ()); - - // See execute_prerequisites() for rationale behind the equal part. - // - return ts < mt || (ts == mt && pt.state () != target_state::changed); - } - - return false; + return ts != timestamp_unknown ? pt.newer (ts) : false; }; // Update and add a header file to the list of prerequisite targets. @@ -1394,10 +1385,18 @@ namespace build2 perform_update (action a, target& xt) const { file& t (static_cast (xt)); - file* s (execute_prerequisites (x_src, a, t, t.mtime ())); - if (s == nullptr) - return target_state::unchanged; + // Update prerequisites and determine if any relevant ones render us + // out-of-date. Note that currently we treat all the prerequisites + // as potentially affecting the result (for simplicity/performance). + // + file* s; + { + auto p (execute_prerequisites (x_src, a, t, t.mtime ())); + + if ((s = p.first) == nullptr) + return p.second; + } scope& bs (t.base_scope ()); scope& rs (*bs.root_scope ()); diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index 9dbfa36..a6b67d5 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -890,9 +890,12 @@ namespace build2 otype lt (link_type (t)); lorder lo (link_order (bs, lt)); - // Update prerequisites. + // Update prerequisites. We determine if any relevant ones render us + // out-of-date manually below. // - bool update (execute_prerequisites (a, t, t.mtime ())); + bool update (false); + timestamp mt (t.mtime ()); + target_state ts (execute_prerequisites (a, t)); // If targeting Windows, take care of the manifest. // @@ -913,7 +916,7 @@ namespace build2 t, rpath_timestamp != timestamp_nonexistent)); - timestamp mt (file_mtime (mf)); + timestamp mf_mt (file_mtime (mf)); if (tsys == "mingw32") { @@ -923,7 +926,7 @@ namespace build2 // manifest = mf + ".o"; - if (mt > file_mtime (manifest)) + if (mf_mt > file_mtime (manifest)) { path of (relative (manifest)); @@ -998,7 +1001,7 @@ namespace build2 { manifest = move (mf); // Save for link.exe's /MANIFESTINPUT. - if (mt > t.mtime ()) + if (mf_mt > mt) update = true; // Manifest changed, force update. } } @@ -1204,9 +1207,16 @@ namespace build2 else cs.append (f->path ().string ()); } + else + f = pt->is_a (); // Consider executable mtime (e.g., linker). + + // Check if this input renders us out-of-date. + // + if (f != nullptr) + update = update || f->newer (mt); } - // Treat it as input for both MinGW and VC. + // Treat it as input for both MinGW and VC (mtime checked above). // if (!manifest.empty ()) cs.append (manifest.string ()); @@ -1229,7 +1239,7 @@ namespace build2 // this situation in the "from scratch" flag. // bool scratch (false); - if (dd.writing () || dd.mtime () > t.mtime ()) + if (dd.writing () || dd.mtime () > mt) scratch = update = true; dd.close (); @@ -1237,7 +1247,7 @@ namespace build2 // If nothing changed, then we are done. // if (!update) - return target_state::unchanged; + return ts; // Ok, so we are updating. Finish building the command line. // -- cgit v1.1