From b61e0de250d522ec9a8e16146ef979a65c181db1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 20 Jul 2023 07:44:36 +0200 Subject: Change inner rule/prerequisites match order in install::file_rule The old order messed up the for-install signaling logic. See the long comment in install::file_rule::apply_impl() for background and details. --- libbuild2/install/rule.cxx | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'libbuild2/install') diff --git a/libbuild2/install/rule.cxx b/libbuild2/install/rule.cxx index 20a4bc3..4dd11e8 100644 --- a/libbuild2/install/rule.cxx +++ b/libbuild2/install/rule.cxx @@ -378,11 +378,36 @@ namespace build2 // (actual update). We used to do this after matching the prerequisites // but the inner rule may provide some rule-specific information (like // the target extension for exe{}) that may be required during the - // prerequisite search (like the base name for in{}). + // prerequisite search (like the base name for in{}; this no longer + // reproduces likely due to the changes to exe{} extension derivation + // but a contrived arrangement can still be made to trigger this). // + // But then we discovered that doing this before the prerequisites messes + // up with the for-install signaling. Specifically, matching the + // prerequisites may signal that they are being updated for install, + // for example, for a library via a metadata library used in a moc + // recipe. While matching the inner rule may trigger updating during + // match of such prerequisites, for example, a source file generated by + // that moc recipe that depends on this metadata library. If we match + // prerequisites before, then the library that is pulled by the metadata + // library will be updated before we had a chance to signal that it + // should be updated for install. + // + // To try to accommodate both cases (as best as we can) we now split the + // inner rule match into two steps: we do the match before and apply + // after. This allows rules that deal with tricky prerequisites like + // in{} to assign the target path in match() instead of apply() (see + // in::rule, for example). + // +#if 0 optional unchanged; if (a.operation () == update_id) unchanged = match_inner (a, t, unmatch::unchanged).first; +#else + action ia (a.inner_action ()); + if (a.operation () == update_id) + match_only_sync (ia, t); +#endif optional is; // Installation scope (resolve lazily). @@ -454,6 +479,12 @@ namespace build2 pts.push_back (prerequisite_target (pt, pi)); } +#if 1 + optional unchanged; + if (a.operation () == update_id) + unchanged = match_sync (ia, t, unmatch::unchanged).first; +#endif + if (a.operation () == update_id) { return *unchanged -- cgit v1.1