From acfa68e443f2ec694d2716b8437bee1594d004b6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 4 Dec 2020 11:48:55 +0200 Subject: Fix bug in installed libraries matching logic --- libbuild2/bin/target.cxx | 2 +- libbuild2/bin/target.hxx | 8 +++++-- libbuild2/cc/common.cxx | 58 ++++++++++++++++++++++++++++-------------------- 3 files changed, 41 insertions(+), 27 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/bin/target.cxx b/libbuild2/bin/target.cxx index 94851cd..bf701c9 100644 --- a/libbuild2/bin/target.cxx +++ b/libbuild2/bin/target.cxx @@ -53,7 +53,7 @@ namespace build2 const target_type libx::static_type { "libx", - &target::static_type, + &mtime_target::static_type, nullptr, nullptr, nullptr, diff --git a/libbuild2/bin/target.hxx b/libbuild2/bin/target.hxx index 8be8c23..f8d2dd0 100644 --- a/libbuild2/bin/target.hxx +++ b/libbuild2/bin/target.hxx @@ -200,10 +200,14 @@ namespace build2 // Common base for lib{} and libul{} groups. // - class LIBBUILD2_BIN_SYMEXPORT libx: public target + // Use mtime_target as a base for the "trust me it exists" functionality + // which we use, for example, to have installed lib{} prerequisites that + // are matched by the fallback file rule. + // + class LIBBUILD2_BIN_SYMEXPORT libx: public mtime_target { public: - using target::target; + using mtime_target::mtime_target; public: static const target_type static_type; diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx index 2f55dcb..62f0ee0 100644 --- a/libbuild2/cc/common.cxx +++ b/libbuild2/cc/common.cxx @@ -840,36 +840,36 @@ namespace build2 return r; // If we cannot acquire the lock then this mean the target has already - // been matched (though not clear by whom) and we assume all of this - // has already been done. + // been matched and we assume all of this has already been done. // - target_lock ll (lock (act, *lt)); + auto lock = [act] (const target* t) -> target_lock + { + auto l (t != nullptr ? build2::lock (act, *t, true) : target_lock ()); + + if (l && l.offset == target::offset_matched) + { + assert ((*t)[act].rule == &file_rule::rule_match); + l.unlock (); + } + + return l; + }; + + target_lock ll (lock (lt)); // Set lib{} group members to indicate what's available. Note that we // must be careful here since its possible we have already imported some // of its members. // + timestamp mt (timestamp_nonexistent); if (ll) { - if (a != nullptr) lt->a = a; - if (s != nullptr) lt->s = s; + if (s != nullptr) {lt->s = s; mt = s->mtime ();} + if (a != nullptr) {lt->a = a; mt = a->mtime ();} } - target_lock al (a != nullptr ? lock (act, *a, true) : target_lock ()); - - if (al && al.offset == target::offset_matched) - { - assert ((*a)[act].rule == &file_rule::rule_match); - al.unlock (); - } - - target_lock sl (s != nullptr ? lock (act, *s, true) : target_lock ()); - - if (sl && sl.offset == target::offset_matched) - { - assert ((*s)[act].rule == &file_rule::rule_match); - sl.unlock (); - } + target_lock al (lock (a)); + target_lock sl (lock (s)); if (!al) a = nullptr; if (!sl) s = nullptr; @@ -965,9 +965,9 @@ namespace build2 pkgconfig_load (act, *p.scope, *lt, a, s, pc, *pd, sysd, *usrd); } - // If we have the lock (meaning this is the first time), set the - // traget's rule/recipe. Failed that we will keep re-locking it, - // updating its members, etc. + // If we have the lock (meaning this is the first time), set the matched + // rule. Failed that we will keep re-locking it, updating its members, + // etc. // // For members, use the fallback file rule instead of noop since we may // need their prerequisites matched (used for modules support; see @@ -977,7 +977,17 @@ namespace build2 // if (al) match_rule (al, file_rule::rule_match); if (sl) match_rule (sl, file_rule::rule_match); - if (ll) match_recipe (ll, noop_recipe); + if (ll) + { + match_rule (ll, file_rule::rule_match); + + // Also bless the library group with a "trust me it exists" timestamp. + // Failed that, if the rule match gets cleared (e.g., because of + // multiple operations being executed), then the fallback file rule + // won't match. + // + lt->mtime (mt); + } return r; } -- cgit v1.1