aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/dump.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-04-28 08:48:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 15:47:28 +0200
commitb808c255b6a9ddba085bf5646e7d20ec344f2e2d (patch)
tree32730291f7e6de8ef0a227905520dd66fb4ec0f3 /libbuild2/dump.cxx
parent3552356a87402727e663131994fa87f48b3cd4fb (diff)
Initial support for ad hoc recipes (still work in progress)
Diffstat (limited to 'libbuild2/dump.cxx')
-rw-r--r--libbuild2/dump.cxx199
1 files changed, 137 insertions, 62 deletions
diff --git a/libbuild2/dump.cxx b/libbuild2/dump.cxx
index 8ee68b7..9f60900 100644
--- a/libbuild2/dump.cxx
+++ b/libbuild2/dump.cxx
@@ -3,6 +3,7 @@
#include <libbuild2/dump.hxx>
+#include <libbuild2/rule.hxx>
#include <libbuild2/scope.hxx>
#include <libbuild2/target.hxx>
#include <libbuild2/context.hxx>
@@ -213,7 +214,90 @@ namespace build2
os << ind << t << ':';
- // First print target/rule-specific variables, if any.
+ // First check if this is the simple case where we can print everything
+ // as a single declaration.
+ //
+ const prerequisites& ps (t.prerequisites ());
+ bool simple (true);
+ for (const prerequisite& p: ps)
+ {
+ if (!p.vars.empty ()) // Has prerequisite-specific vars.
+ {
+ simple = false;
+ break;
+ }
+ }
+
+ // If the target has been matched to a rule, we also print resolved
+ // prerequisite targets.
+ //
+ // Note: running serial and task_count is 0 before any operation has
+ // started.
+ //
+ const prerequisite_targets* pts (nullptr);
+ {
+ action inner; // @@ Only for the inner part of the action currently.
+
+ if (size_t c = t[inner].task_count.load (memory_order_relaxed))
+ {
+ if (c == t.ctx.count_applied () || c == t.ctx.count_executed ())
+ {
+ pts = &t.prerequisite_targets[inner];
+
+ bool f (false);
+ for (const target* pt: *pts)
+ {
+ if (pt != nullptr)
+ {
+ f = true;
+ break;
+ }
+ }
+
+ if (!f)
+ pts = nullptr;
+ }
+ }
+ }
+
+ auto print_pts = [&os, &ps, pts] ()
+ {
+ for (const target* pt: *pts)
+ {
+ if (pt != nullptr)
+ os << ' ' << *pt;
+ }
+
+ // Only omit '|' if we have no prerequisites nor targets.
+ //
+ if (!ps.empty ())
+ {
+ os << " |";
+ return true;
+ }
+
+ return false;
+ };
+
+ if (simple)
+ {
+ if (pts != nullptr)
+ print_pts ();
+
+ for (const prerequisite& p: ps)
+ {
+ // Print it as a target if one has been cached.
+ //
+ if (const target* t = p.target.load (memory_order_relaxed)) // Serial.
+ os << ' ' << *t;
+ else
+ os << ' ' << p;
+ }
+ }
+
+ bool used (false); // Target header has been used.
+
+ // Print target/rule-specific variables, if any.
//
{
bool tv (!t.vars.empty ());
@@ -258,87 +342,78 @@ namespace build2
if (rel)
stream_verb (os, nsv);
- os << endl
- << ind << t << ':';
+ used = true;
}
}
- bool used (false); // Target header has been used to display prerequisites.
-
- // If the target has been matched to a rule, first print resolved
- // prerequisite targets.
+ // Then ad hoc recipes, if any.
//
- // Note: running serial and task_count is 0 before any operation has
- // started.
- //
- action inner; // @@ Only for the inner part of the action currently.
-
- if (size_t c = t[inner].task_count.load (memory_order_relaxed))
+ if (!t.adhoc_recipes.empty ())
{
- if (c == t.ctx.count_applied () || c == t.ctx.count_executed ())
+ for (const adhoc_recipe r: t.adhoc_recipes)
{
- bool f (false);
- for (const target* pt: t.prerequisite_targets[inner])
- {
- if (pt == nullptr) // Skipped.
- continue;
-
- os << ' ' << *pt;
- f = true;
- }
-
- // Only omit '|' if we have no prerequisites nor targets.
- //
- if (f || !t.prerequisites ().empty ())
- {
- os << " |";
- used = true;
- }
+ os << endl;
+ r.rule->dump (os, ind); // @@ TODO: pass action(s).
}
+
+ used = true;
}
- // Print prerequisites. Those that have prerequisite-specific variables
- // have to be printed as a separate dependency.
- //
- const prerequisites& ps (t.prerequisites ());
- for (auto i (ps.begin ()), e (ps.end ()); i != e; )
+ if (!simple)
{
- const prerequisite& p (*i++);
- bool ps (!p.vars.empty ()); // Has prerequisite-specific vars.
-
- if (ps && used) // If it has been used, get a new header.
+ if (used)
+ {
os << endl
<< ind << t << ':';
- // Print it as a target if one has been cached.
- //
- if (const target* t = p.target.load (memory_order_relaxed)) // Serial.
- os << ' ' << *t;
- else
- os << ' ' << p;
+ used = false;
+ }
+
+ if (pts != nullptr)
+ used = print_pts () || used;
- if (ps)
+ // Print prerequisites. Those that have prerequisite-specific variables
+ // have to be printed as a separate dependency.
+ //
+ for (auto i (ps.begin ()), e (ps.end ()); i != e; )
{
- if (rel)
- stream_verb (os, osv); // We want variable values in full.
+ const prerequisite& p (*i++);
+ bool ps (!p.vars.empty ()); // Has prerequisite-specific vars.
- os << ':' << endl
- << ind << '{';
- ind += " ";
- dump_variables (os, ind, p.vars, s, variable_kind::prerequisite);
- ind.resize (ind.size () - 2);
- os << endl
- << ind << '}';
+ if (ps && used) // If it has been used, get a new header.
+ os << endl
+ << ind << t << ':';
- if (rel)
- stream_verb (os, nsv);
+ // Print it as a target if one has been cached.
+ //
+ if (const target* t = p.target.load (memory_order_relaxed)) // Serial.
+ os << ' ' << *t;
+ else
+ os << ' ' << p;
- if (i != e) // If we have another, get a new header.
+ if (ps)
+ {
+ if (rel)
+ stream_verb (os, osv); // We want variable values in full.
+
+ os << ':' << endl
+ << ind << '{';
+ ind += " ";
+ dump_variables (os, ind, p.vars, s, variable_kind::prerequisite);
+ ind.resize (ind.size () - 2);
os << endl
- << ind << t << ':';
- }
+ << ind << '}';
+
+ if (rel)
+ stream_verb (os, nsv);
- used = !ps;
+ if (i != e) // If we have another, get a new header.
+ os << endl
+ << ind << t << ':';
+ }
+
+ used = !ps;
+ }
}
if (rel)