From ca7db0a1b856909efe127d3b47b50a0144e5c2c9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 4 May 2020 11:05:23 +0200 Subject: WIP --- libbuild2/rule.cxx | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++--- libbuild2/rule.hxx | 3 ++ 2 files changed, 147 insertions(+), 8 deletions(-) diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx index bbb854c..d89cf39 100644 --- a/libbuild2/rule.cxx +++ b/libbuild2/rule.cxx @@ -379,18 +379,154 @@ namespace build2 { // @@ Perhaps we should have different implementations for file-based // targets (depdb, timestamp, etc) and non. - // - return [r] (action a, const target& t) + + switch (a) { - // @@ TODO - text << t << ' ' << a << ' ' << r; - return target_state::unchanged; - }; + case perform_update_id: return [r] (action a, const target& t) + { + return perform_update (a, t, *r); + }; + default: return [r] (action a, const target& t) + { + // @@ TODO + text << t << ' ' << a << ' ' << r; + return target_state::unchanged; + }; + } + } + else + { + // Otherwise this should be the standard clean. + // + return &perform_clean_depdb; } + } + + target_state adhoc_rule:: + perform_update (action, const target&, const adhoc_recipe&) + { + tracer trace ("adhoc_rule::perform_update"); + +#if 0 + // 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 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, CLI + // compiler target itself, etc). + // + timestamp mt (t.load_mtime (tp)); + auto pr (execute_prerequisites (a, t, mt)); + + bool update (!pr.first); + target_state ts (update ? target_state::changed : *pr.first); - // Otherwise this should be the standard clean. + const cli& s (pr.second); + + // We use depdb to track changes to the .cli file name, options, + // compiler, etc. // - return &perform_clean_depdb; + depdb dd (tp + ".d"); + { + // First should come the rule name/version. + // + if (dd.expect ("cli.compile 1") != nullptr) + l4 ([&]{trace << "rule mismatch forcing update of " << t;}); + + // Then the compiler checksum. + // + if (dd.expect (csum) != nullptr) + l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); + + // Then the options checksum. + // + sha256 cs; + append_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 process_path& pp (ctgt.process_path ()); + cstrings args {pp.recall_string ()}; + + // See if we need to pass --output-{prefix,suffix} + // + string prefix, suffix; + match_stem (t.name, s.name, &prefix, &suffix); + + if (!prefix.empty ()) + { + args.push_back ("--output-prefix"); + args.push_back (prefix.c_str ()); + } + + if (!suffix.empty ()) + { + args.push_back ("--output-suffix"); + args.push_back (suffix.c_str ()); + } + + // See if we need to pass any --?xx-suffix options. + // + append_extension (args, *t.h, "--hxx-suffix", "hxx"); + append_extension (args, *t.c, "--cxx-suffix", "cxx"); + if (t.i != nullptr) + append_extension (args, *t.i, "--ixx-suffix", "ixx"); + + append_options (args, t, "cli.options"); + + if (!relo.empty ()) + { + args.push_back ("-o"); + args.push_back (relo.string ().c_str ()); + } + + args.push_back (rels.string ().c_str ()); + args.push_back (nullptr); + + if (verb >= 2) + print_process (args); + else if (verb) + text << "cli " << s; + + if (!t.ctx.dry_run) + { + run (pp, args); + dd.check_mtime (tp); + } + + t.mtime (system_clock::now ()); +#endif + return target_state::changed; } const adhoc_rule adhoc_rule::instance; diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx index c15064e..d712957 100644 --- a/libbuild2/rule.hxx +++ b/libbuild2/rule.hxx @@ -122,6 +122,9 @@ namespace build2 virtual recipe apply (action, target&) const override; + static target_state + perform_update (action, const target&, const adhoc_recipe&); + adhoc_rule () {} static const adhoc_rule instance; static const rule_match match_instance; -- cgit v1.1