aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/diagnostics.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-11-29 08:02:51 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-11-29 08:02:51 +0200
commit05afdd8ca16c7066d12510a27e2fc08743bb2e95 (patch)
tree90c7a43a08c47786df3869d68d7b625bf93174d3 /libbuild2/diagnostics.cxx
parent472d6d0e49c0114f46ff31267d09acdbf9fba421 (diff)
Fix backlink logic for target groups
We used to backlink ad hoc group members both via the group and as individual members. And for explicit groups it was done only via individual members, which means it only works correctly if every member is individually updated. Now both types of groups are backlinked from the group target.
Diffstat (limited to 'libbuild2/diagnostics.cxx')
-rw-r--r--libbuild2/diagnostics.cxx195
1 files changed, 141 insertions, 54 deletions
diff --git a/libbuild2/diagnostics.cxx b/libbuild2/diagnostics.cxx
index bc74db3..d91150b 100644
--- a/libbuild2/diagnostics.cxx
+++ b/libbuild2/diagnostics.cxx
@@ -82,39 +82,26 @@ namespace build2
dr << r;
}
- template <typename L> // L can be target_key, path, or string.
- static void
- print_diag_impl (const char* p,
- const L* l, bool lempty,
- vector<target_key>&& rs,
- const char* c)
- {
- assert (rs.size () > 1);
- // The overall plan is as follows:
- //
- // 1. Collect the printed names for all the group members.
- //
- // Note if the printed representation is irregular (see
- // to_stream(target_key) for details). We will print such members each
- // on a separate line.
- //
- // 2. Move the names so that we end up with contiguous partitions of
- // targets with the same name.
- //
- // 3. Print the partitions, one per line.
- //
- vector<pair<optional<string>, const target_key*>> ns;
- ns.reserve (rs.size ());
+ static inline bool
+ print_diag_cmp (const pair<optional<string>, const target_key*>& x,
+ const pair<optional<string>, const target_key*>& y)
+ {
+ return (x.second->dir->compare (*y.second->dir) == 0 &&
+ x.first->compare (*y.first) == 0);
+ }
- // Use the diag_record's ostringstream so that we get the appropriate
- // stream verbosity, etc.
- //
- diag_record dr (text);
- ostringstream& os (dr.os);
- stream_verbosity sv (stream_verb (os));
+ // Return true if we have multiple partitions (see below for details).
+ //
+ static bool
+ print_diag_collect (const vector<target_key>& tks,
+ ostringstream& os,
+ stream_verbosity sv,
+ vector<pair<optional<string>, const target_key*>>& ns)
+ {
+ ns.reserve (tks.size ());
- for (const target_key& k: rs)
+ for (const target_key& k: tks)
{
bool r;
if (auto p = k.type->print)
@@ -130,16 +117,9 @@ namespace build2
// Partition.
//
- auto cmp = [] (const pair<optional<string>, const target_key*>& x,
- const pair<optional<string>, const target_key*>& y)
- {
- return (x.second->dir->compare (*y.second->dir) == 0 &&
- x.first->compare (*y.first) == 0);
- };
-
// While at it also determine whether we have multiple partitions.
//
- optional<string> ml;
+ bool ml (false);
for (auto b (ns.begin ()), e (ns.end ()); b != e; )
{
const pair<optional<string>, const target_key*>& x (*b++);
@@ -149,25 +129,24 @@ namespace build2
//
b = stable_partition (
b, e,
- [&cmp, &x] (const pair<optional<string>, const target_key*>& y)
+ [&x] (const pair<optional<string>, const target_key*>& y)
{
- return (x.first && y.first && cmp (x, y));
+ return (x.first && y.first && print_diag_cmp (x, y));
});
if (!ml && b != e)
- ml = string ();
+ ml = true;
}
- // Print.
- //
- os << p << ' ';
-
- if (l != nullptr)
- os << *l << (lempty ? "" : " ") << (c == nullptr ? "->" : c) << ' ';
-
- if (ml)
- ml = string (os.str ().size (), ' '); // Indentation.
+ return ml;
+ }
+ static void
+ print_diag_print (const vector<pair<optional<string>, const target_key*>>& ns,
+ ostringstream& os,
+ stream_verbosity sv,
+ const optional<string>& ml)
+ {
for (auto b (ns.begin ()), i (b), e (ns.end ()); i != e; )
{
if (i != b)
@@ -185,7 +164,7 @@ namespace build2
// Calculate the number of members in this partition.
//
size_t n (1);
- for (auto j (i + 1); j != e && j->first && cmp (*i, *j); ++j)
+ for (auto j (i + 1); j != e && j->first && print_diag_cmp (*i, *j); ++j)
++n;
// Similar code to to_stream(target_key).
@@ -232,6 +211,95 @@ namespace build2
}
}
+ template <typename L> // L can be target_key, path, or string.
+ static void
+ print_diag_impl (const char* p,
+ const L* l, bool lempty,
+ vector<target_key>&& rs,
+ const char* c)
+ {
+ assert (rs.size () > 1);
+
+ // The overall plan is as follows:
+ //
+ // 1. Collect the printed names for all the group members.
+ //
+ // Note if the printed representation is irregular (see
+ // to_stream(target_key) for details). We will print such members each
+ // on a separate line.
+ //
+ // 2. Move the names around so that we end up with contiguous partitions
+ // of targets with the same name.
+ //
+ // 3. Print the partitions, one per line.
+ //
+ // The steps 1-2 are performed by print_diag_impl_common() above.
+ //
+ vector<pair<optional<string>, const target_key*>> ns;
+
+ // Use the diag_record's ostringstream so that we get the appropriate
+ // stream verbosity, etc.
+ //
+ diag_record dr (text);
+ ostringstream& os (dr.os);
+ stream_verbosity sv (stream_verb (os));
+
+ optional<string> ml;
+ if (print_diag_collect (rs, os, sv, ns))
+ ml = string ();
+
+ // Print.
+ //
+ os << p << ' ';
+
+ if (l != nullptr)
+ os << *l << (lempty ? "" : " ") << (c == nullptr ? "->" : c) << ' ';
+
+ if (ml)
+ ml = string (os.str ().size (), ' '); // Indentation.
+
+ print_diag_print (ns, os, sv, ml);
+ }
+
+ template <typename R> // R can be target_key, path, or string.
+ static void
+ print_diag_impl (const char* p,
+ vector<target_key>&& ls, const R& r,
+ const char* c)
+ {
+ assert (ls.size () > 1);
+
+ // As above but for the group on the LHS.
+ //
+ vector<pair<optional<string>, const target_key*>> ns;
+
+ diag_record dr (text);
+ ostringstream& os (dr.os);
+ stream_verbosity sv (stream_verb (os));
+
+ optional<string> ml;
+ if (print_diag_collect (ls, os, sv, ns))
+ ml = string ();
+
+ // Print.
+ //
+ os << p << ' ';
+
+ if (ml)
+ ml = string (os.str ().size (), ' '); // Indentation.
+
+ print_diag_print (ns, os, sv, ml);
+
+ // @@ TODO: make sure `->` is aligned with longest line printed by
+ // print_diag_print(). Currently it can look like this:
+ //
+ // ln /tmp/hello-gcc/hello/hello/{hxx cxx}{hello-types}
+ // /tmp/hello-gcc/hello/hello/{hxx cxx}{hello-stubs}
+ // /tmp/hello-gcc/hello/hello/cxx{hello-ext} -> ./
+ //
+ os << ' ' << (c == nullptr ? "->" : c) << ' ' << r;
+ }
+
void
print_diag_impl (const char* p,
target_key* l, vector<target_key>&& rs,
@@ -361,7 +429,9 @@ namespace build2
}
void
- print_diag (const char* p, const target& l, const dir_path& r, const char* c)
+ print_diag (const char* p,
+ const target& l, const path_name_view& r,
+ const char* c)
{
// @@ TODO: out qualification stripping: only do if p.out is subdir of t
// (also below)?
@@ -370,11 +440,28 @@ namespace build2
}
void
+ print_diag (const char* p, const target& l, const dir_path& r, const char* c)
+ {
+ print_diag (p, l.key (), r, c);
+ }
+
+ void
+ print_diag (const char* p, target_key&& l, const dir_path& r, const char* c)
+ {
+ text << p << ' ' << l << ' ' << (c == nullptr ? "->" : c) << ' ' << r;
+ }
+
+ void
print_diag (const char* p,
- const target& l, const path_name_view& r,
+ vector<target_key>&& ls, const dir_path& r,
const char* c)
{
- text << p << ' ' << l << ' ' << (c == nullptr ? "->" : c) << ' ' << r;
+ assert (!ls.empty ());
+
+ if (ls.size () == 1)
+ print_diag (p, move (ls.front ()), r, c);
+ else
+ print_diag_impl<dir_path> (p, move (ls), r, c);
}
void