From 66b6e20659a0d611e89adde85cd7bcb34a92a2c7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 8 May 2020 13:10:29 +0200 Subject: Use recipe data in ad hoc rule --- libbuild2/dump.cxx | 2 +- libbuild2/recipe.hxx | 6 +- libbuild2/rule.cxx | 172 +++++++++++++++++++++++++-------------------------- libbuild2/rule.hxx | 7 ++- 4 files changed, 95 insertions(+), 92 deletions(-) diff --git a/libbuild2/dump.cxx b/libbuild2/dump.cxx index 919b921..6eb8018 100644 --- a/libbuild2/dump.cxx +++ b/libbuild2/dump.cxx @@ -373,7 +373,7 @@ namespace build2 } os << ind << string (r.braces, '{') << endl - << ind << r.recipe + << ind << r.script << ind << string (r.braces, '}'); } diff --git a/libbuild2/recipe.hxx b/libbuild2/recipe.hxx index e73a8ea..4c903b5 100644 --- a/libbuild2/recipe.hxx +++ b/libbuild2/recipe.hxx @@ -57,7 +57,7 @@ namespace build2 using location_type = build2::location; action_type action; - string recipe; + string script; optional diag; // Command name for low-verbosity diagnostics. // Diagnostics-related information. @@ -67,11 +67,11 @@ namespace build2 size_t braces; // Number of braces in multi-brace tokens. adhoc_recipe (action_type a, - string r, + string s, optional d, const location_type& l, size_t b) : action (a), - recipe (move (r)), + script (move (s)), diag (move (d)), file (l.file), location (file, l.line, l.column), braces (b) {} }; diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx index d89cf39..f3b9253 100644 --- a/libbuild2/rule.cxx +++ b/libbuild2/rule.cxx @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -365,7 +366,7 @@ namespace build2 // match_prerequisite_members (a, t); - // For update inject dependency on the tool target. + // For update inject dependency on the tool target(s). // // @@ We could see that it's a target and do it but not sure if we should // bother. We dropped this idea of implicit targets in tests. Maybe we @@ -375,22 +376,20 @@ namespace build2 // if (a == perform_update_id) // inject (a, t, tgt); - if (const adhoc_recipe* r = find_recipe (a, t)) + if (const adhoc_recipe* ar = find_recipe (a, t)) { - // @@ Perhaps we should have different implementations for file-based - // targets (depdb, timestamp, etc) and non. - - switch (a) + if (a == perform_update_id && t.is_a ()) { - case perform_update_id: return [r] (action a, const target& t) + return [ar] (action a, const target& t) { - return perform_update (a, t, *r); + return perform_update_file (a, t, *ar); }; - default: return [r] (action a, const target& t) + } + else + { + return [ar] (action a, const target& t) { - // @@ TODO - text << t << ' ' << a << ' ' << r; - return target_state::unchanged; + return default_action (a, t, *ar); }; } } @@ -403,58 +402,51 @@ namespace build2 } target_state adhoc_rule:: - perform_update (action, const target&, const adhoc_recipe&) + perform_update_file (action a, const target& xt, const adhoc_recipe& ar) { - tracer trace ("adhoc_rule::perform_update"); + tracer trace ("adhoc_rule::perform_update_file"); -#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 ()); + const file& t (xt.as ()); + const path& tp (t.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). + // Update prerequisites and determine if any of them render this target + // out-of-date. // - 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); + timestamp mt (t.load_mtime ()); + optional ps (execute_prerequisites (a, t, mt)); - const cli& s (pr.second); + bool update (!ps); - // We use depdb to track changes to the .cli file name, options, - // compiler, etc. + // We use depdb to track changes to the script itself, input file names, + // tools, etc. // depdb dd (tp + ".d"); { // First should come the rule name/version. // - if (dd.expect ("cli.compile 1") != nullptr) + if (dd.expect ("adhoc 1") != nullptr) l4 ([&]{trace << "rule mismatch forcing update of " << t;}); - // Then the compiler checksum. + // Then the tool checksums. // - if (dd.expect (csum) != nullptr) - l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); - - // Then the options checksum. + // @@ TODO: obtain checksums of all the targets used as commands in + // the script. // - sha256 cs; - append_options (cs, t, "cli.options"); + //if (dd.expect (csum) != nullptr) + // l4 ([&]{trace << "compiler mismatch forcing update of " << t;}); - if (dd.expect (cs.string ()) != nullptr) - l4 ([&]{trace << "options mismatch forcing update of " << t;}); - - // Finally the .cli input file. + // Then the script checksum. + // + // @@ TODO: for now we hash the unexpanded text but it should be + // expanded. This will take care of all the relevant input + // file name changes as well as any other variables the + // script may reference. + // + // It feels like we need a special execute mode that instead + // of executing hashes the commands. // - if (dd.expect (s.path ()) != nullptr) - l4 ([&]{trace << "input file mismatch forcing update of " << t;}); + if (dd.expect (sha256 (ar.script).string ()) != nullptr) + l4 ([&]{trace << "recipe change forcing update of " << t;}); } // Update if depdb mismatch. @@ -467,65 +459,73 @@ namespace build2 // 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 ())); + return *ps; - const process_path& pp (ctgt.process_path ()); - cstrings args {pp.recall_string ()}; + if (verb >= 2) + { + //@@ TODO - // See if we need to pass --output-{prefix,suffix} - // - string prefix, suffix; - match_stem (t.name, s.name, &prefix, &suffix); + //print_process (args); - if (!prefix.empty ()) + text << trim (string (ar.script)); + } + else if (verb) { - args.push_back ("--output-prefix"); - args.push_back (prefix.c_str ()); + // @@ TODO: + // + // - derive diag if absent (should probably do in match?) + // + // - we are printing target, not source (like in most other places) + // + // - printing of ad hoc target group (the {hxx cxx}{foo} idea) + // + // - if we are printing prerequisites, should we print all of them + // (including tools)? + // + + text << (ar.diag ? ar.diag->c_str () : "adhoc") << ' ' << t; } - if (!suffix.empty ()) + if (!t.ctx.dry_run) { - args.push_back ("--output-suffix"); - args.push_back (suffix.c_str ()); + // @@ TODO + // + touch (t.ctx, tp, true, verb_never); + dd.check_mtime (tp); } - // 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"); + t.mtime (system_clock::now ()); + return target_state::changed; + } + + target_state adhoc_rule:: + default_action (action a, const target& t, const adhoc_recipe& ar) + { + tracer trace ("adhoc_rule::default_action"); - append_options (args, t, "cli.options"); + execute_prerequisites (a, t); - if (!relo.empty ()) + if (verb >= 2) { - args.push_back ("-o"); - args.push_back (relo.string ().c_str ()); - } + //@@ TODO - args.push_back (rels.string ().c_str ()); - args.push_back (nullptr); + //print_process (args); - if (verb >= 2) - print_process (args); + text << trim (string (ar.script)); + } else if (verb) - text << "cli " << s; + { + // @@ TODO: as above + + text << (ar.diag ? ar.diag->c_str () : "adhoc") << ' ' << t; + } if (!t.ctx.dry_run) { - run (pp, args); - dd.check_mtime (tp); + // @@ TODO + // } - t.mtime (system_clock::now ()); -#endif return target_state::changed; } diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx index d712957..669f7db 100644 --- a/libbuild2/rule.hxx +++ b/libbuild2/rule.hxx @@ -111,7 +111,7 @@ namespace build2 // Ad hoc recipe rule. // - // Note: should not be used directly (e.g., registered, etc). + // Note: should not be used directly (i.e., registered). // class LIBBUILD2_SYMEXPORT adhoc_rule: public rule { @@ -123,7 +123,10 @@ namespace build2 apply (action, target&) const override; static target_state - perform_update (action, const target&, const adhoc_recipe&); + perform_update_file (action, const target&, const adhoc_recipe&); + + static target_state + default_action (action, const target&, const adhoc_recipe&); adhoc_rule () {} static const adhoc_rule instance; -- cgit v1.1