From f1c981a22365411794806ed0744b857ef0804e35 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 24 Jun 2022 10:29:09 +0200 Subject: Allow ad hoc rules not to list targets that are updated during match For example, this allows a Qt moc rule not to list generated headers from libQtCore since they are pre-generated by the library. --- libbuild2/dyndep.cxx | 53 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) (limited to 'libbuild2/dyndep.cxx') diff --git a/libbuild2/dyndep.cxx b/libbuild2/dyndep.cxx index 61fa8cb..bc307f6 100644 --- a/libbuild2/dyndep.cxx +++ b/libbuild2/dyndep.cxx @@ -56,9 +56,43 @@ namespace build2 return r; } + // Check if the specified prerequisite is updated during match by any other + // prerequisites of the specified target, recursively. + // + static bool + updated_during_match (action a, const target& t, size_t pts_n, + const target& pt) + { + const auto& pts (t.prerequisite_targets[a]); + + for (size_t i (0); i != pts_n; ++i) + { + const prerequisite_target& p (pts[i]); + + // @@ This currently doesn't cover adhoc targets if matched with + // buildscript (it stores them in p.data). Probably need to redo + // things there (see adhoc_buildscript_rule::apply()). + // + if (p.target != nullptr) + { + if (p.target == &pt && + (p.include & prerequisite_target::include_udm) != 0) + return true; + + if (size_t n = p.target->prerequisite_targets[a].size ()) + { + if (updated_during_match (a, *p.target, n, pt)) + return true; + } + } + } + + return false; + } + optional dyndep_rule:: inject_existing_file (tracer& trace, const char* what, - action a, target& t, + action a, target& t, size_t pts_n, const file& pt, timestamp mt, bool f, @@ -81,8 +115,11 @@ namespace build2 recipe_function* const* rf (pt[a].recipe.target ()); if (rf == nullptr || *rf != &noop_action) { - fail << what << ' ' << pt << " has non-noop recipe" << - info << "consider listing it as static prerequisite of " << t; + if (!updated_during_match (a, t, pts_n, pt)) + { + fail << what << ' ' << pt << " has non-noop recipe" << + info << "consider listing it as static prerequisite of " << t; + } } bool r (update (trace, a, pt, mt)); @@ -96,7 +133,7 @@ namespace build2 void dyndep_rule:: verify_existing_file (tracer&, const char* what, - action a, const target& t, + action a, const target& t, size_t pts_n, const file& pt) { diag_record dr; @@ -106,11 +143,17 @@ namespace build2 recipe_function* const* rf (pt[a].recipe.target ()); if (rf == nullptr || *rf != &noop_action) { - dr << fail << what << ' ' << pt << " has non-noop recipe"; + if (!updated_during_match (a, t, pts_n, pt)) + { + dr << fail << what << ' ' << pt << " has non-noop recipe"; + } } } else if (pt.decl == target_decl::real) { + // Note that this target could not possibly be updated during match + // since it's not matched. + // dr << fail << what << ' ' << pt << " is explicitly declared as " << "target and may have non-noop recipe"; } -- cgit v1.1