From 747ff339c4be7d271a33996638b3b026a166d805 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 17 Dec 2016 11:48:40 +0200 Subject: Don't try to test out-of-project prerequisites --- build2/algorithm | 29 +++++----- build2/algorithm.cxx | 16 ++---- build2/algorithm.ixx | 31 ++++++++--- build2/test/init.cxx | 3 +- build2/test/rule | 10 ++++ build2/test/rule.cxx | 74 +++++++++++++++----------- old-tests/test/generated/build/bootstrap.build | 6 ++- 7 files changed, 102 insertions(+), 67 deletions(-) diff --git a/build2/algorithm b/build2/algorithm index 4c12148..8d8889d 100644 --- a/build2/algorithm +++ b/build2/algorithm @@ -45,7 +45,8 @@ namespace build2 const dir_path& out, const string& name, const string* ext, - scope*); + scope*, + const string* proj = nullptr); // As above but specify the target type as template argument. // @@ -57,32 +58,30 @@ namespace build2 const string* ext, scope*); - // Search for a target identified by the name. The semantics - // is "as if" we first created a prerequisite based on this - // name in exactly the same way as the parser would and then - // searched based on this prerequisite. + // Search for a target identified by the name. The semantics is "as if" we + // first created a prerequisite based on this name in exactly the same way + // as the parser would and then searched based on this prerequisite. // target& search (name, scope&); - // Match and apply a rule to the action/target with ambiguity - // detection. Increment the target's dependents count, which - // means that you should call this function with the intent - // to also call execute(). In case of optimizations that would - // avoid calling execute(), call unmatch() to indicate this. + // Match and apply a rule to the action/target with ambiguity detection. + // Increment the target's dependents count, which means that you should call + // this function with the intent to also call execute(). In case of + // optimizations that would avoid calling execute(), call unmatch() to + // indicate this. // void match (action, target&); - // Note that calling this function only makes sense if the - // target itself doesn't have its own dependents. + // Note that calling this function only makes sense if the target itself + // doesn't have its own dependents. // void unmatch (action, target&); - // Match (but do not apply) a rule to the action/target with - // ambiguity detection. Note that this function does not touch - // the dependents count. + // Match (but do not apply) a rule to the action/target with ambiguity + // detection. Note that this function does not touch the dependents count. // void match_only (action, target&); diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index dbdf81c..7a3b773 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -49,7 +49,7 @@ namespace build2 // @@ OUT: for now we assume the prerequisite's out is undetermined. // Would need to pass a pair of names. // - return search (*tt, n.dir, dir_path (), n.value, e, &s); + return search (*tt, n.dir, dir_path (), n.value, e, &s, n.proj); } pair @@ -275,15 +275,13 @@ namespace build2 } void - search_and_match_prerequisites (action a, target& t, const dir_path& d) + search_and_match_prerequisites (action a, target& t, scope* s) { - const bool e (d.empty ()); - for (prerequisite p: group_prerequisites (t)) { target& pt (search (p)); - if (e || pt.dir.sub (d)) + if (s == nullptr || pt.in (*s)) { match (a, pt); t.prerequisite_targets.push_back (&pt); @@ -292,17 +290,13 @@ namespace build2 } void - search_and_match_prerequisite_members (action a, - target& t, - const dir_path& d) + search_and_match_prerequisite_members (action a, target& t, scope* s) { - const bool e (d.empty ()); - for (prerequisite_member p: group_prerequisite_members (a, t)) { target& pt (p.search ()); - if (e || pt.dir.sub (d)) + if (s == nullptr || pt.in (*s)) { match (a, pt); t.prerequisite_targets.push_back (&pt); diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx index b2c4941..ac81dbe 100644 --- a/build2/algorithm.ixx +++ b/build2/algorithm.ixx @@ -31,10 +31,11 @@ namespace build2 const dir_path& out, const string& name, const string* ext, - scope* scope) + scope* scope, + const string* proj) { return search ( - prerequisite_key {nullptr, {&type, &dir, &out, &name, ext}, scope}); + prerequisite_key {proj, {&type, &dir, &out, &name, ext}, scope}); } template @@ -99,28 +100,44 @@ namespace build2 return r.members != nullptr ? r : resolve_group_members_impl (a, g); } + void + search_and_match_prerequisites (action, target&, scope*); + + void + search_and_match_prerequisite_members (action, target&, scope*); + inline void search_and_match_prerequisites (action a, target& t) { search_and_match_prerequisites ( a, t, - (a.operation () != clean_id - ? dir_path () - : t.root_scope ().out_path ())); + (a.operation () != clean_id ? nullptr : &t.root_scope ())); } inline void search_and_match_prerequisite_members (action a, target& t) { if (a.operation () != clean_id) - search_and_match_prerequisite_members (a, t, dir_path ()); + search_and_match_prerequisite_members (a, t, nullptr); else // Note that here we don't iterate over members even for see- // through groups since the group target should clean eveything // up. A bit of an optimization. // - search_and_match_prerequisites (a, t, t.root_scope ().out_path ()); + search_and_match_prerequisites (a, t, &t.root_scope ()); + } + + inline void + search_and_match_prerequisites (action a, target& t, scope& s) + { + search_and_match_prerequisites (a, t, &s); + } + + inline void + search_and_match_prerequisite_members (action a, target& t, scope& s) + { + search_and_match_prerequisite_members (a, t, &s); } target_state diff --git a/build2/test/init.cxx b/build2/test/init.cxx index 098718b..21a6612 100644 --- a/build2/test/init.cxx +++ b/build2/test/init.cxx @@ -21,6 +21,7 @@ namespace build2 namespace test { static rule rule_; + static alias_rule alias_rule_; void boot (scope& rs, const location&, unique_ptr&) @@ -105,7 +106,7 @@ namespace build2 // Register our test running rule. // r.insert (perform_test_id, "test", rule_); - r.insert (perform_test_id, "test", rule_); // Override generic. + r.insert (perform_test_id, "test", alias_rule_); // Register our rule for the dist meta-operation. We need to do this // because we may have ad hoc prerequisites (test input/output files) diff --git a/build2/test/rule b/build2/test/rule index b915ea7..d1790e0 100644 --- a/build2/test/rule +++ b/build2/test/rule @@ -30,6 +30,16 @@ namespace build2 static target_state perform_test (action, target&); }; + + class alias_rule: public rule + { + public: + virtual recipe + apply (action, target&) const override; + + static target_state + perform_test (action, target&); + }; } } diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx index a8adb9e..d313925 100644 --- a/build2/test/rule.cxx +++ b/build2/test/rule.cxx @@ -147,47 +147,44 @@ namespace build2 return mr; } - recipe rule:: + recipe alias_rule:: apply (action a, target& t) const { - tracer trace ("test::rule::apply"); - match_data md (move (t.data ())); t.clear_data (); // In case delegated-to rule also uses aux storage. - // The alias case is special so handle it first. + // We can only test an alias via a testscript, not a simple test. // - if (t.is_a ()) - { - // We can only test an alias via a testscript, not a simple test. - // - assert (!md.test || md.script); + assert (!md.test || md.script); - // Find the actual alias rule. - // - recipe d (match_delegate (a, t, *this).first); + // If this is the update pre-operation then simply redirect to the + // standard alias rule. + // + if (a.operation () == update_id) + return match_delegate (a, t, *this).first; + + // For the test operation we have to implement our own search and match + // because we need to ignore prerequisites that are outside of our + // project. They can be from projects that don't use the test module + // (and thus won't have a suitable rule). Or they can be from no project + // at all (e.g., installed). Also, generally, not testing stuff that's + // not ours seems right. Note that we still want to make sure they are + // up to date (via the above delegate) since our tests might use them. + // + search_and_match_prerequisites (a, t, t.root_scope ()); - // If not a test or this is the update pre-operation then simply - // redirect to the alias rule. - // - if (!md.test || a.operation () == update_id) - return d; + // If not a test then also redirect to the alias rule. + // + return md.test ? perform_test : default_recipe; + } - // Otherwise, we have to combine the two recipes. Note that we will - // reuse the prerequisite_targets prepared by the alias rule. - // - // Note: this most likely won't fit the small object optimization. We - // could check if the target is a function pointer (which it will most - // likely be) and return an optimized lambda in this case. - // - return [dr = move (d)] (action a, target& t) -> target_state - { - // Run the alias recipe first then the test. - // - target_state r (execute_delegate (dr, a, t)); - return r |= perform_script (a, t); - }; - } + recipe rule:: + apply (action a, target& t) const + { + tracer trace ("test::rule::apply"); + + match_data md (move (t.data ())); + t.clear_data (); // In case delegated-to rule also uses aux storage. if (!md.test) return noop_recipe; @@ -593,5 +590,18 @@ namespace build2 return target_state::changed; } + + target_state alias_rule:: + perform_test (action a, target& t) + { + // Run the alias recipe first then the test. + // + target_state r (execute_prerequisites (a, t)); + + // Note that we reuse the prerequisite_targets prepared by the standard + // search and match. + // + return r |= perform_script (a, t); + } } } diff --git a/old-tests/test/generated/build/bootstrap.build b/old-tests/test/generated/build/bootstrap.build index 5428eb8..1b04c1d 100644 --- a/old-tests/test/generated/build/bootstrap.build +++ b/old-tests/test/generated/build/bootstrap.build @@ -1,4 +1,8 @@ -project = test-generated +project = generated amalgamation = # Disabled. + +dist.package = $project + using config using test +using dist -- cgit v1.1