From 50e1ffc8f9c48e3e81bd5fa38381193942182df3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 29 Jun 2018 10:39:26 +0200 Subject: Use depdb to track changes to cli compiler, options, etc --- build2/cli/init.cxx | 33 ++++++++++++++++++----- build2/cli/rule.cxx | 77 ++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 22 deletions(-) (limited to 'build2/cli') diff --git a/build2/cli/init.cxx b/build2/cli/init.cxx index 88a8d69..8e0abdb 100644 --- a/build2/cli/init.cxx +++ b/build2/cli/init.cxx @@ -53,7 +53,11 @@ namespace build2 v.insert ("config.cli", true); v.insert ("config.cli.options", true); + //@@ TODO: split version into componets (it is stdver). + // v.insert ("cli.path"); + v.insert ("cli.version"); + v.insert ("cli.checksum"); v.insert ("cli.options"); } @@ -214,11 +218,23 @@ namespace build2 nv = p.second; } - // Note that we are unconfigured so that we don't keep re-testing this - // on each run. - // - if (!conf) + string checksum; + if (conf) + { + // Hash the compiler path and version. + // + sha256 cs; + cs.append (pp.effect_string ()); + cs.append (ver); + checksum = cs.string (); + } + else + { + // Note that we are unconfigured so that we don't keep re-testing + // this on each run. + // nv = config::unconfigured (rs, "cli", true) || nv; + } // If this is a new value (e.g., we are configuring), then print the // report at verbosity level 2 and up (-v). @@ -230,13 +246,18 @@ namespace build2 if (conf) dr << " cli " << pp << '\n' - << " version " << ver; + << " version " << ver << '\n' + << " checksum " << checksum; else dr << " cli " << "not found, leaving unconfigured"; } if (conf) - rs.assign ("cli.path") = move (pp); + { + rs.assign ("cli.path") = move (pp); + rs.assign ("cli.version") = move (ver); + rs.assign ("cli.checksum") = move (checksum); + } } if (conf) diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx index 45b8185..27668c1 100644 --- a/build2/cli/rule.cxx +++ b/build2/cli/rule.cxx @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -166,10 +167,12 @@ namespace build2 // match_prerequisite_members (a, t); + //@@ TODO: inject dependency on exe{cli}. + switch (a) { case perform_update_id: return &perform_update; - case perform_clean_id: return &perform_clean_group; // Standard impl. + case perform_clean_id: return &perform_clean_group_depdb; default: return noop_recipe; // Configure/dist update. } } @@ -206,34 +209,76 @@ namespace build2 target_state compile_rule:: perform_update (action a, const target& xt) { + tracer trace ("cli::compile_rule::perform_update"); + + // The rule has been matched which means the members should be resolved + // and paths assigned. We use the header file as our "target path" for + // timestamp, depdb, etc. + // const cli_cxx& t (xt.as ()); + const scope& rs (t.root_scope ()); + const path& tp (t.h->path ()); // 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 (think prologues/epilogues, - // etc). + // out-of-date. Note that currently we treat all the prerequisites as + // potentially affecting the result (think prologues/epilogues, etc). // + timestamp mt (t.load_mtime (tp)); + auto pr (execute_prerequisites (a, t, mt)); - // The rule has been matched which means the members should be resolved - // and paths assigned. + bool update (!pr.first); + target_state ts (update ? target_state::changed : *pr.first); + + const cli& s (pr.second); + + // We use depdb to track changes to the .cli file name, options, + // compiler, etc. // - auto pr ( - execute_prerequisites ( - a, t, t.load_mtime (t.h->path ()))); + { + depdb dd (tp + ".d"); - if (pr.first) - return *pr.first; + // First should come the rule name/version. + // + if (dd.expect ("cli.compile 1") != nullptr) + l4 ([&]{trace << "rule mismatch forcing update of " << t;}); - const cli& s (pr.second); + // Then the compiler checksum. + // + if (dd.expect (cast (rs["cli.checksum"])) != nullptr) + l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); - // Translate paths to relative (to working directory). This - // results in easier to read diagnostics. + // Then the options checksum. + // + sha256 cs; + hash_options (cs, t, "cli.options"); + + if (dd.expect (cs.string ()) != nullptr) + l4 ([&]{trace << "options mismatch forcing update of " << t;}); + + // Finally the .cli input file. + // + if (dd.expect (s.path ()) != nullptr) + l4 ([&]{trace << "input file mismatch forcing update of " << t;}); + + // Update if depdb mismatch. + // + if (dd.writing () || dd.mtime () > mt) + update = true; + + dd.close (); + } + + // If nothing changed, then we are done. + // + if (!update) + return ts; + + // Translate paths to relative (to working directory). This results in + // easier to read diagnostics. // path relo (relative (t.dir)); path rels (relative (s.path ())); - const scope& rs (t.root_scope ()); - const process_path& cli (cast (rs["cli.path"])); cstrings args {cli.recall_string ()}; -- cgit v1.1