Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 1538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1549 break | 1549 break |
| 1550 | 1550 |
| 1551 if is_in_degree_zero: | 1551 if is_in_degree_zero: |
| 1552 # All of the dependent's dependencies are already in flat_list. Add | 1552 # All of the dependent's dependencies are already in flat_list. Add |
| 1553 # it to in_degree_zeros where it will be processed in a future | 1553 # it to in_degree_zeros where it will be processed in a future |
| 1554 # iteration of the outer loop. | 1554 # iteration of the outer loop. |
| 1555 in_degree_zeros.add(node_dependent) | 1555 in_degree_zeros.add(node_dependent) |
| 1556 | 1556 |
| 1557 return list(flat_list) | 1557 return list(flat_list) |
| 1558 | 1558 |
| 1559 def FindCycles(self, path=None): | 1559 def FindCycles(self): |
| 1560 """ | 1560 """ |
| 1561 Returns a list of cycles in the graph, where each cycle is its own list. | 1561 Returns a list of cycles in the graph, where each cycle is its own list. |
| 1562 """ | 1562 """ |
| 1563 if path is None: | 1563 results = [] |
| 1564 path = [self] | 1564 visited = set() |
| 1565 | 1565 |
| 1566 results = [] | 1566 def Visit(node, path): |
| 1567 for node in self.dependents: | 1567 for child in node.dependents: |
| 1568 if node in path: | 1568 if child in path: |
| 1569 cycle = [node] | 1569 results.append([child] + path[:path.index(child) + 1]) |
| 1570 for part in path: | 1570 elif not child in visited: |
| 1571 cycle.append(part) | 1571 visited.add(child) |
| 1572 if part == node: | 1572 Visit(child, [child] + path) |
| 1573 break | |
| 1574 results.append(tuple(cycle)) | |
| 1575 else: | |
| 1576 results.extend(node.FindCycles([node] + path)) | |
| 1577 | 1573 |
| 1578 return list(set(results)) | 1574 visited.add(self) |
| 1575 Visit(self, [self]) | |
| 1576 | |
| 1577 return results | |
| 1579 | 1578 |
| 1580 def DirectDependencies(self, dependencies=None): | 1579 def DirectDependencies(self, dependencies=None): |
| 1581 """Returns a list of just direct dependencies.""" | 1580 """Returns a list of just direct dependencies.""" |
| 1582 if dependencies == None: | 1581 if dependencies == None: |
| 1583 dependencies = [] | 1582 dependencies = [] |
| 1584 | 1583 |
| 1585 for dependency in self.dependencies: | 1584 for dependency in self.dependencies: |
| 1586 # Check for None, corresponding to the root node. | 1585 # Check for None, corresponding to the root node. |
| 1587 if dependency.ref != None and dependency.ref not in dependencies: | 1586 if dependency.ref != None and dependency.ref not in dependencies: |
| 1588 dependencies.append(dependency.ref) | 1587 dependencies.append(dependency.ref) |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1785 dependency_node = dependency_nodes.get(dependency) | 1784 dependency_node = dependency_nodes.get(dependency) |
| 1786 if not dependency_node: | 1785 if not dependency_node: |
| 1787 raise GypError("Dependency '%s' not found while " | 1786 raise GypError("Dependency '%s' not found while " |
| 1788 "trying to load target %s" % (dependency, target)) | 1787 "trying to load target %s" % (dependency, target)) |
| 1789 target_node.dependencies.append(dependency_node) | 1788 target_node.dependencies.append(dependency_node) |
| 1790 dependency_node.dependents.append(target_node) | 1789 dependency_node.dependents.append(target_node) |
| 1791 | 1790 |
| 1792 flat_list = root_node.FlattenToList() | 1791 flat_list = root_node.FlattenToList() |
| 1793 | 1792 |
| 1794 # If there's anything left unvisited, there must be a circular dependency | 1793 # If there's anything left unvisited, there must be a circular dependency |
| 1795 # (cycle). If you need to figure out what's wrong, look for elements of | 1794 # (cycle). |
| 1796 # targets that are not in flat_list. | |
| 1797 if len(flat_list) != len(targets): | 1795 if len(flat_list) != len(targets): |
| 1798 raise DependencyGraphNode.CircularException( | 1796 if not root_node.dependents: |
| 1799 'Some targets not reachable, cycle in dependency graph detected: ' + | 1797 # If all targets have dependencies, add the first target as a dependent |
| 1800 ' '.join(set(flat_list) ^ set(targets))) | 1798 # of root_node so that the cycle can be discovered from root_node. |
| 1799 target = targets.keys()[0] | |
| 1800 target_node = dependency_nodes[target] | |
| 1801 target_node.dependencies.append(root_node) | |
| 1802 root_node.dependents.append(target_node) | |
| 1803 | |
| 1804 cycles = [] | |
| 1805 for cycle in root_node.FindCycles(): | |
| 1806 paths = [node.ref for node in cycle] | |
| 1807 cycles.append('Cycle: %s' % ' -> '.join(paths)) | |
| 1808 raise DependencyGraphNode.CircularException, \ | |
|
scottmg
2014/10/21 18:31:47
I meant this \ vs. (, mostly since that's what it
cjhopman
2014/10/21 19:52:54
Ha, I really thought I fixed it here before.
| |
| 1809 'Cycles in dependency graph detected:\n' + '\n'.join(cycles) | |
| 1801 | 1810 |
| 1802 return [dependency_nodes, flat_list] | 1811 return [dependency_nodes, flat_list] |
| 1803 | 1812 |
| 1804 | 1813 |
| 1805 def VerifyNoGYPFileCircularDependencies(targets): | 1814 def VerifyNoGYPFileCircularDependencies(targets): |
| 1806 # Create a DependencyGraphNode for each gyp file containing a target. Put | 1815 # Create a DependencyGraphNode for each gyp file containing a target. Put |
| 1807 # it into a dict for easy access. | 1816 # it into a dict for easy access. |
| 1808 dependency_nodes = {} | 1817 dependency_nodes = {} |
| 1809 for target in targets.iterkeys(): | 1818 for target in targets.iterkeys(): |
| 1810 build_file = gyp.common.BuildFile(target) | 1819 build_file = gyp.common.BuildFile(target) |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1840 for build_file_node in dependency_nodes.itervalues(): | 1849 for build_file_node in dependency_nodes.itervalues(): |
| 1841 if len(build_file_node.dependencies) == 0: | 1850 if len(build_file_node.dependencies) == 0: |
| 1842 build_file_node.dependencies.append(root_node) | 1851 build_file_node.dependencies.append(root_node) |
| 1843 root_node.dependents.append(build_file_node) | 1852 root_node.dependents.append(build_file_node) |
| 1844 | 1853 |
| 1845 flat_list = root_node.FlattenToList() | 1854 flat_list = root_node.FlattenToList() |
| 1846 | 1855 |
| 1847 # If there's anything left unvisited, there must be a circular dependency | 1856 # If there's anything left unvisited, there must be a circular dependency |
| 1848 # (cycle). | 1857 # (cycle). |
| 1849 if len(flat_list) != len(dependency_nodes): | 1858 if len(flat_list) != len(dependency_nodes): |
| 1850 bad_files = [] | 1859 if not root_node.dependents: |
| 1851 for file in dependency_nodes.iterkeys(): | 1860 # If all files have dependencies, add the first file as a dependent |
| 1852 if not file in flat_list: | 1861 # of root_node so that the cycle can be discovered from root_node. |
| 1853 bad_files.append(file) | 1862 file_node = dependency_nodes.values()[0] |
| 1854 common_path_prefix = os.path.commonprefix(dependency_nodes) | 1863 file_node.dependencies.append(root_node) |
| 1864 root_node.dependents.append(file_node) | |
| 1855 cycles = [] | 1865 cycles = [] |
| 1856 for cycle in root_node.FindCycles(): | 1866 for cycle in root_node.FindCycles(): |
| 1857 simplified_paths = [] | 1867 paths = [node.ref for node in cycle] |
| 1858 for node in cycle: | 1868 cycles.append('Cycle: %s' % ' -> '.join(paths)) |
| 1859 assert(node.ref.startswith(common_path_prefix)) | 1869 raise DependencyGraphNode.CircularException( |
| 1860 simplified_paths.append(node.ref[len(common_path_prefix):]) | 1870 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles)) |
| 1861 cycles.append('Cycle: %s' % ' -> '.join(simplified_paths)) | |
| 1862 raise DependencyGraphNode.CircularException, \ | |
| 1863 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles) | |
| 1864 | 1871 |
| 1865 | 1872 |
| 1866 def DoDependentSettings(key, flat_list, targets, dependency_nodes): | 1873 def DoDependentSettings(key, flat_list, targets, dependency_nodes): |
| 1867 # key should be one of all_dependent_settings, direct_dependent_settings, | 1874 # key should be one of all_dependent_settings, direct_dependent_settings, |
| 1868 # or link_settings. | 1875 # or link_settings. |
| 1869 | 1876 |
| 1870 for target in flat_list: | 1877 for target in flat_list: |
| 1871 target_dict = targets[target] | 1878 target_dict = targets[target] |
| 1872 build_file = gyp.common.BuildFile(target) | 1879 build_file = gyp.common.BuildFile(target) |
| 1873 | 1880 |
| (...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2864 ValidateRunAsInTarget(target, target_dict, build_file) | 2871 ValidateRunAsInTarget(target, target_dict, build_file) |
| 2865 ValidateActionsInTarget(target, target_dict, build_file) | 2872 ValidateActionsInTarget(target, target_dict, build_file) |
| 2866 | 2873 |
| 2867 # Generators might not expect ints. Turn them into strs. | 2874 # Generators might not expect ints. Turn them into strs. |
| 2868 TurnIntIntoStrInDict(data) | 2875 TurnIntIntoStrInDict(data) |
| 2869 | 2876 |
| 2870 # TODO(mark): Return |data| for now because the generator needs a list of | 2877 # TODO(mark): Return |data| for now because the generator needs a list of |
| 2871 # build files that came in. In the future, maybe it should just accept | 2878 # build files that came in. In the future, maybe it should just accept |
| 2872 # a list, and not the whole data dict. | 2879 # a list, and not the whole data dict. |
| 2873 return [flat_list, targets, data] | 2880 return [flat_list, targets, data] |
| OLD | NEW |