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

Side by Side Diff: pylib/gyp/input.py

Issue 23018008: GTTF: Print much better error message for dependency cycles. (Closed) Base URL: http://gyp.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 4 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pylib/gyp/input_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 Google Inc. All rights reserved. 1 # Copyright (c) 2012 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from compiler.ast import Const 5 from compiler.ast import Const
6 from compiler.ast import Dict 6 from compiler.ast import Dict
7 from compiler.ast import Discard 7 from compiler.ast import Discard
8 from compiler.ast import List 8 from compiler.ast import List
9 from compiler.ast import Module 9 from compiler.ast import Module
10 from compiler.ast import Node 10 from compiler.ast import Node
(...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1436 """ 1436 """
1437 1437
1438 class CircularException(GypError): 1438 class CircularException(GypError):
1439 pass 1439 pass
1440 1440
1441 def __init__(self, ref): 1441 def __init__(self, ref):
1442 self.ref = ref 1442 self.ref = ref
1443 self.dependencies = [] 1443 self.dependencies = []
1444 self.dependents = [] 1444 self.dependents = []
1445 1445
1446 def __repr__(self):
1447 return '<DependencyGraphNode: %r>' % self.ref
1448
1446 def FlattenToList(self): 1449 def FlattenToList(self):
1447 # flat_list is the sorted list of dependencies - actually, the list items 1450 # flat_list is the sorted list of dependencies - actually, the list items
1448 # are the "ref" attributes of DependencyGraphNodes. Every target will 1451 # are the "ref" attributes of DependencyGraphNodes. Every target will
1449 # appear in flat_list after all of its dependencies, and before all of its 1452 # appear in flat_list after all of its dependencies, and before all of its
1450 # dependents. 1453 # dependents.
1451 flat_list = [] 1454 flat_list = []
1452 1455
1453 # in_degree_zeros is the list of DependencyGraphNodes that have no 1456 # in_degree_zeros is the list of DependencyGraphNodes that have no
1454 # dependencies not in flat_list. Initially, it is a copy of the children 1457 # dependencies not in flat_list. Initially, it is a copy of the children
1455 # of this node, because when the graph was built, nodes with no 1458 # of this node, because when the graph was built, nodes with no
(...skipping 22 matching lines...) Expand all
1478 break 1481 break
1479 1482
1480 if is_in_degree_zero: 1483 if is_in_degree_zero:
1481 # All of the dependent's dependencies are already in flat_list. Add 1484 # All of the dependent's dependencies are already in flat_list. Add
1482 # it to in_degree_zeros where it will be processed in a future 1485 # it to in_degree_zeros where it will be processed in a future
1483 # iteration of the outer loop. 1486 # iteration of the outer loop.
1484 in_degree_zeros.add(node_dependent) 1487 in_degree_zeros.add(node_dependent)
1485 1488
1486 return flat_list 1489 return flat_list
1487 1490
1491 def FindCycles(self, path=None):
1492 """
1493 Returns a list of cycles in the graph, where each cycle is its own list.
1494 """
1495 if path is None:
1496 path = [self]
1497
1498 results = []
1499 for node in self.dependents:
1500 if node in path:
1501 cycle = [node]
1502 for part in path:
1503 cycle.append(part)
1504 if part == node:
1505 break
1506 results.append(tuple(cycle))
1507 else:
1508 results.extend(node.FindCycles([node] + path))
1509
1510 return list(set(results))
1511
1488 def DirectDependencies(self, dependencies=None): 1512 def DirectDependencies(self, dependencies=None):
1489 """Returns a list of just direct dependencies.""" 1513 """Returns a list of just direct dependencies."""
1490 if dependencies == None: 1514 if dependencies == None:
1491 dependencies = [] 1515 dependencies = []
1492 1516
1493 for dependency in self.dependencies: 1517 for dependency in self.dependencies:
1494 # Check for None, corresponding to the root node. 1518 # Check for None, corresponding to the root node.
1495 if dependency.ref != None and dependency.ref not in dependencies: 1519 if dependency.ref != None and dependency.ref not in dependencies:
1496 dependencies.append(dependency.ref) 1520 dependencies.append(dependency.ref)
1497 1521
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1710 1734
1711 flat_list = root_node.FlattenToList() 1735 flat_list = root_node.FlattenToList()
1712 1736
1713 # If there's anything left unvisited, there must be a circular dependency 1737 # If there's anything left unvisited, there must be a circular dependency
1714 # (cycle). 1738 # (cycle).
1715 if len(flat_list) != len(dependency_nodes): 1739 if len(flat_list) != len(dependency_nodes):
1716 bad_files = [] 1740 bad_files = []
1717 for file in dependency_nodes.iterkeys(): 1741 for file in dependency_nodes.iterkeys():
1718 if not file in flat_list: 1742 if not file in flat_list:
1719 bad_files.append(file) 1743 bad_files.append(file)
1744 common_path_prefix = os.path.commonprefix(dependency_nodes)
1745 cycles = []
1746 for cycle in root_node.FindCycles():
1747 simplified_paths = []
1748 for node in cycle:
1749 assert(node.ref.startswith(common_path_prefix))
1750 simplified_paths.append(node.ref[len(common_path_prefix):])
1751 cycles.append('Cycle: %s' % ' -> '.join(simplified_paths))
1720 raise DependencyGraphNode.CircularException, \ 1752 raise DependencyGraphNode.CircularException, \
1721 'Some files not reachable, cycle in .gyp file dependency graph ' + \ 1753 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles)
1722 'detected involving some or all of: ' + \
1723 ' '.join(bad_files)
1724 1754
1725 1755
1726 def DoDependentSettings(key, flat_list, targets, dependency_nodes): 1756 def DoDependentSettings(key, flat_list, targets, dependency_nodes):
1727 # key should be one of all_dependent_settings, direct_dependent_settings, 1757 # key should be one of all_dependent_settings, direct_dependent_settings,
1728 # or link_settings. 1758 # or link_settings.
1729 1759
1730 for target in flat_list: 1760 for target in flat_list:
1731 target_dict = targets[target] 1761 target_dict = targets[target]
1732 build_file = gyp.common.BuildFile(target) 1762 build_file = gyp.common.BuildFile(target)
1733 1763
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after
2674 ValidateRunAsInTarget(target, target_dict, build_file) 2704 ValidateRunAsInTarget(target, target_dict, build_file)
2675 ValidateActionsInTarget(target, target_dict, build_file) 2705 ValidateActionsInTarget(target, target_dict, build_file)
2676 2706
2677 # Generators might not expect ints. Turn them into strs. 2707 # Generators might not expect ints. Turn them into strs.
2678 TurnIntIntoStrInDict(data) 2708 TurnIntIntoStrInDict(data)
2679 2709
2680 # TODO(mark): Return |data| for now because the generator needs a list of 2710 # TODO(mark): Return |data| for now because the generator needs a list of
2681 # build files that came in. In the future, maybe it should just accept 2711 # build files that came in. In the future, maybe it should just accept
2682 # a list, and not the whole data dict. 2712 # a list, and not the whole data dict.
2683 return [flat_list, targets, data] 2713 return [flat_list, targets, data]
OLDNEW
« no previous file with comments | « no previous file | pylib/gyp/input_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698