Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: tools/gn/header_checker.cc

Issue 424133002: GN: (HeaderChecker) Allow any chain to forward direct dependent configs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update comments in header Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/header_checker.h ('k') | tools/gn/header_checker_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/header_checker.cc
diff --git a/tools/gn/header_checker.cc b/tools/gn/header_checker.cc
index 62a0f44d580baa41a03d2938fd6f36dc0b7d6ba7..29e0d485495e84e5fde51a4030e9b9ecc60c3189 100644
--- a/tools/gn/header_checker.cc
+++ b/tools/gn/header_checker.cc
@@ -274,6 +274,7 @@ bool HeaderChecker::CheckInclude(const Target* from_target,
const TargetVector& targets = found->second;
std::vector<const Target*> chain; // Prevent reallocating in the loop.
+ bool direct_dependent_configs_apply = false;
// For all targets containing this file, we require that at least one be
// a dependency of the current target, and all targets that are dependencies
@@ -286,7 +287,13 @@ bool HeaderChecker::CheckInclude(const Target* from_target,
if (to_target == from_target)
return true;
- if (IsDependencyOf(to_target, from_target, &chain)) {
+ bool has_direct_dependent_compiler_settings =
+ HasDirectDependentCompilerSettings(to_target);
+ if (IsDependencyOf(to_target,
+ from_target,
+ has_direct_dependent_compiler_settings,
+ &chain,
+ &direct_dependent_configs_apply)) {
DCHECK(chain.size() >= 2);
DCHECK(chain[0] == to_target);
DCHECK(chain[chain.size() - 1] == from_target);
@@ -318,9 +325,10 @@ bool HeaderChecker::CheckInclude(const Target* from_target,
// If the to_target has direct_dependent_configs, they must apply to the
// from_target.
- if (HasDirectDependentCompilerSettings(to_target)) {
- size_t problematic_index;
- if (!DoDirectDependentConfigsApply(chain, &problematic_index)) {
+ if (has_direct_dependent_compiler_settings &&
+ !direct_dependent_configs_apply) {
+ size_t problematic_index = GetDependentConfigChainProblemIndex(chain);
+ if (!direct_dependent_configs_apply) {
*err = Err(CreatePersistentRange(source_file, range),
"Can't include this header from here.",
GetDependentConfigChainError(chain, problematic_index));
@@ -373,33 +381,67 @@ bool HeaderChecker::CheckInclude(const Target* from_target,
bool HeaderChecker::IsDependencyOf(const Target* search_for,
const Target* search_from,
- std::vector<const Target*>* chain) const {
- std::set<const Target*> checked;
- return IsDependencyOf(search_for, search_from, chain, &checked);
+ bool prefer_direct_dependent_configs,
+ std::vector<const Target*>* chain,
+ bool* direct_dependent_configs_apply) const {
+ if (search_for == search_from)
+ return false;
+
+ // Find the shortest path that forwards dependent configs, if one exists.
+ if (prefer_direct_dependent_configs &&
+ IsDependencyOf(search_for, search_from, true, chain)) {
+ if (direct_dependent_configs_apply)
+ *direct_dependent_configs_apply = true;
+ return true;
+ }
+
+ // If not, try to find any dependency path at all.
+ if (IsDependencyOf(search_for, search_from, false, chain)) {
+ if (direct_dependent_configs_apply)
+ *direct_dependent_configs_apply = false;
+ return true;
+ }
+
+ return false;
}
bool HeaderChecker::IsDependencyOf(const Target* search_for,
const Target* search_from,
- std::vector<const Target*>* chain,
- std::set<const Target*>* checked) const {
- if (checked->find(search_for) != checked->end())
- return false; // Already checked this subtree.
-
- const LabelTargetVector& deps = search_from->deps();
- for (size_t i = 0; i < deps.size(); i++) {
- if (deps[i].ptr == search_for) {
- // Found it.
+ bool requires_dependent_configs,
+ std::vector<const Target*>* chain) const {
+ // This maps targets to the target which receives dependent configs from it.
brettw 2014/07/31 20:50:49 I'm a bit confused about this function. Rather tha
jbroman 2014/07/31 22:05:37 It maps targets to their predecessor in a shortest
+ std::map<const Target*, const Target*> breadcrumbs;
+ std::queue<const Target*> work_queue;
+ breadcrumbs.insert(std::make_pair(
+ search_from, static_cast<const Target*>(NULL)));
brettw 2014/07/31 20:50:49 I see you add this to make the reconstruction step
jbroman 2014/07/31 22:05:37 It's unnecessarily clever. I can just make getting
+ work_queue.push(search_from);
+
+ while (!work_queue.empty()) {
+ const Target* target = work_queue.front();
+ work_queue.pop();
+
+ if (target == search_for) {
+ // Found it! Reconstruct the chain.
chain->clear();
- chain->push_back(deps[i].ptr);
- chain->push_back(search_from);
+ while (target) {
+ chain->push_back(target);
+ target = breadcrumbs[target];
+ }
return true;
}
- // Recursive search.
- checked->insert(deps[i].ptr);
- if (IsDependencyOf(search_for, deps[i].ptr, chain, checked)) {
- chain->push_back(search_from);
- return true;
+ // All deps of a group implicitly forward dependent configs.
+ bool uses_all_deps = !requires_dependent_configs ||
+ target == search_from ||
+ target->output_type() == Target::GROUP;
+
+ const LabelTargetVector& deps = uses_all_deps ? target->deps() :
+ target->forward_dependent_configs();
+ for (size_t i = 0; i < deps.size(); i++) {
+ bool seeing_for_first_time = breadcrumbs.insert(
+ std::make_pair(deps[i].ptr, target)).second;
+ if (seeing_for_first_time)
+ work_queue.push(deps[i].ptr);
}
}
@@ -407,24 +449,18 @@ bool HeaderChecker::IsDependencyOf(const Target* search_for,
}
// static
-bool HeaderChecker::DoDirectDependentConfigsApply(
- const std::vector<const Target*>& chain,
- size_t* problematic_index) {
+size_t HeaderChecker::GetDependentConfigChainProblemIndex(
+ const std::vector<const Target*>& chain)
+{
// Direct dependent configs go up the chain one level with the following
// exceptions:
// - Skip over groups
// - Skip anything that explicitly forwards it
- // All chains should be at least two (or it wouldn't be a chain).
- DCHECK(chain.size() >= 2);
-
- // A chain of length 2 is always OK as far as direct dependent configs are
- // concerned since the targets are direct dependents.
- if (chain.size() == 2)
- return true;
+ // Chains of length less than three have no problems.
+ // These should have been filtered out earlier.
+ DCHECK(chain.size() >= 3);
- // Check the middle configs to make sure they're either groups or configs
- // are forwarded.
for (size_t i = 1; i < chain.size() - 1; i++) {
if (chain[i]->output_type() == Target::GROUP)
continue; // This one is OK, skip to next one.
@@ -434,11 +470,10 @@ bool HeaderChecker::DoDirectDependentConfigsApply(
const LabelTargetVector& forwarded = chain[i]->forward_dependent_configs();
if (std::find_if(forwarded.begin(), forwarded.end(),
LabelPtrPtrEquals<Target>(chain[i - 1])) ==
- forwarded.end()) {
- *problematic_index = i;
- return false;
- }
+ forwarded.end())
+ return i;
}
- return true;
+ CHECK(false) << "Unable to diagnose dependent config chain problem.";
+ return 0;
}
« no previous file with comments | « tools/gn/header_checker.h ('k') | tools/gn/header_checker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698