From 0db17bfec8b3b6c436f3c9c346d17d98458c3654 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 3 Aug 2015 13:10:28 +0200 Subject: match_only and dependents count rework, part 1 --- build/algorithm | 16 ++++++++++++++-- build/algorithm.ixx | 7 +++++++ build/bin/rule.cxx | 48 +++++++++++++++++++++++++++++------------------- build/cli/rule.cxx | 2 +- build/cxx/compile.cxx | 25 ++++++++++++++++++++----- build/install/rule.cxx | 4 ++-- 6 files changed, 73 insertions(+), 29 deletions(-) (limited to 'build') diff --git a/build/algorithm b/build/algorithm index 1171f9d..99e6c2b 100644 --- a/build/algorithm +++ b/build/algorithm @@ -64,11 +64,23 @@ namespace build target& search (name, scope&); - // Match a rule to the action/target with ambiguity detection. + // 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(), decrement the dependents + // cound manually to compensate. // void match (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. + // + void + match_only (action, target&); + // Match a "delegate rule" from withing another rules' apply() // function. Return recipe and recipe action (if any). Note // that unlike match(), this call doesn't increment the @@ -120,7 +132,7 @@ namespace build // Execute the action on target, assuming a rule has been matched // and the recipe for this action has been set. This is the default - // executor implementation. + // executor implementation. Decrements the dependents count. // target_state execute (action, target&); diff --git a/build/algorithm.ixx b/build/algorithm.ixx index 26761bf..ce581c5 100644 --- a/build/algorithm.ixx +++ b/build/algorithm.ixx @@ -62,6 +62,13 @@ namespace build t.dependents++; } + inline void + match_only (action a, target& t) + { + if (!t.recipe (a)) + match_impl (a, t, false); + } + inline std::pair match_delegate (action a, target& t) { diff --git a/build/bin/rule.cxx b/build/bin/rule.cxx index 0845627..8df1ee0 100644 --- a/build/bin/rule.cxx +++ b/build/bin/rule.cxx @@ -37,8 +37,36 @@ namespace build // members as our prerequisites. // match_result lib_rule:: - match (action, target& t, const std::string&) const + match (action a, target& t, const std::string&) const { + // Search and match prerequisite libraries and add them to the + // prerequisite targets. While we never execute this list + // ourselves (see perform() below), this is necessary to make + // the exported options machinery work for the library chains + // (chaining is the reason why we have to do match, recursively). + // See the cxx.export.*-related code in cxx/compile.cxx for + // details. + // + for (prerequisite& p: group_prerequisites (t)) + { + if (p.is_a ()) + { + target& pt (search (p)); + match_only (a, pt); + t.prerequisite_targets.push_back (&pt); + } + else if (p.is_a () || p.is_a ()) + { + //@@ TMP: C++ link rule hasn't been converted to support + // match_only(). + // + target& pt (search (p)); + build::match (a, pt); + t.prerequisite_targets.push_back (&pt); + pt.dependents--; // No intent to execute. + } + } + return t; } @@ -75,24 +103,6 @@ namespace build build::match (a, *t.so); } - // Search and match prerequisite libraries and add them to the - // prerequisite targets. While we never execute this list - // ourselves (see perform() below), this is necessary to make - // the exported options machinery work for the library chains. - // See cxx.export.*-related code in cxx/compile.cxx for details. - // - // @@ Messes up dependents count. - // - for (prerequisite& p: group_prerequisites (t)) - { - if (p.is_a () || p.is_a () || p.is_a ()) - { - target& pt (search (p)); - build::match (a, pt); - t.prerequisite_targets.push_back (&pt); - } - } - return &perform; } diff --git a/build/cli/rule.cxx b/build/cli/rule.cxx index d1cb616..247b5b4 100644 --- a/build/cli/rule.cxx +++ b/build/cli/rule.cxx @@ -179,7 +179,7 @@ namespace build { cli_cxx& g (*static_cast (mr.target)); build::match (a, g); - return group_recipe; + return group_recipe; // Execute the group's recipe. } } diff --git a/build/cxx/compile.cxx b/build/cxx/compile.cxx index d89aaac..48d2240 100644 --- a/build/cxx/compile.cxx +++ b/build/cxx/compile.cxx @@ -113,17 +113,32 @@ namespace build // match() in order to get options (if any, they would // be set by search_library()). // + // @@ What if this is an installed import with an export + // stub? How will such a stub capture prerequsite libs? + // Probably as imported prerequisites, e.g., %lib{z}, not + // as -lz in .libs variable. + // + // In fact, even if we tried match() on lib{}, nothing + // would have matched since that lib{} is out of any + // project and is not a file (which is the case for + // liba/libso). So probably the importing code would + // have to take care of importing all the prerequisite + // libraries. It does make sense since we don't really + // want to match a rule to an installed library. + // if (link::search_library (lib_paths, p.prerequisite) != nullptr) continue; } target& pt (p.search ()); - // @@ The fact that we match but never execute messes up - // the dependents count. This is a workaround, not a - // solution. - // - build::match (a, pt); + if (p.is_a ()) //@@ TMP + build::match_only (a, pt); + else + { + build::match (a, pt); + pt.dependents--; + } } continue; diff --git a/build/install/rule.cxx b/build/install/rule.cxx index 5642388..890228c 100644 --- a/build/install/rule.cxx +++ b/build/install/rule.cxx @@ -127,10 +127,10 @@ namespace build // will help a lot in case of any static installable content // (headers, documentation, etc). // - // @@ This messes up the dependents count logic. - // if (pt.state () != target_state::unchanged) t.prerequisite_targets.push_back (&pt); + else + pt.dependents--; // No intent to execute, so compensate. } // This is where we diverge depending on the operation. In the -- cgit v1.1