aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-05-08 13:10:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 08:35:29 +0200
commit66b6e20659a0d611e89adde85cd7bcb34a92a2c7 (patch)
tree9b78f9ad9f45011be4b5d04574fe8bb76d5cc867
parenta5bf818ebb55e4e27eb0f067664fd4db70284267 (diff)
Use recipe data in ad hoc rule
-rw-r--r--libbuild2/dump.cxx2
-rw-r--r--libbuild2/recipe.hxx6
-rw-r--r--libbuild2/rule.cxx172
-rw-r--r--libbuild2/rule.hxx7
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<string> 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<string> 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 <libbuild2/rule.hxx>
+#include <libbuild2/depdb.hxx>
#include <libbuild2/scope.hxx>
#include <libbuild2/target.hxx>
#include <libbuild2/context.hxx>
@@ -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<file> ())
{
- 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<cli_cxx> ());
- const path& tp (t.h->path ());
+ const file& t (xt.as<file> ());
+ 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<cli> (a, t, mt));
-
- bool update (!pr.first);
- target_state ts (update ? target_state::changed : *pr.first);
+ timestamp mt (t.load_mtime ());
+ optional<target_state> 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;