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

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

Issue 1506733002: GYP: Make GYP build deterministic (Closed) Base URL: https://chromium.googlesource.com/external/gyp.git@master
Patch Set: Clearer naming, better understanding Created 5 years 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
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 'outputs', 51 'outputs',
52 'sources', 52 'sources',
53 ] 53 ]
54 path_sections = set() 54 path_sections = set()
55 55
56 # These per-process dictionaries are used to cache build file data when loading 56 # These per-process dictionaries are used to cache build file data when loading
57 # in parallel mode. 57 # in parallel mode.
58 per_process_data = {} 58 per_process_data = {}
59 per_process_aux_data = {} 59 per_process_aux_data = {}
60 60
61 def OrderDeterministically(l, **kwargs):
62 """ Sorts l so that it is ordered deterministically. """
63 return sorted(l, **kwargs)
mithro-old 2015/12/10 03:15:28 DRY
Zachary Forman 2015/12/30 02:18:43 Done.
64
61 def IsPathSection(section): 65 def IsPathSection(section):
62 # If section ends in one of the '=+?!' characters, it's applied to a section 66 # If section ends in one of the '=+?!' characters, it's applied to a section
63 # without the trailing characters. '/' is notably absent from this list, 67 # without the trailing characters. '/' is notably absent from this list,
64 # because there's no way for a regular expression to be treated as a path. 68 # because there's no way for a regular expression to be treated as a path.
65 while section and section[-1:] in '=+?!': 69 while section and section[-1:] in '=+?!':
66 section = section[:-1] 70 section = section[:-1]
67 71
68 if section in path_sections: 72 if section in path_sections:
69 return True 73 return True
70 74
(...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 def __repr__(self): 1536 def __repr__(self):
1533 return '<DependencyGraphNode: %r>' % self.ref 1537 return '<DependencyGraphNode: %r>' % self.ref
1534 1538
1535 def FlattenToList(self): 1539 def FlattenToList(self):
1536 # flat_list is the sorted list of dependencies - actually, the list items 1540 # flat_list is the sorted list of dependencies - actually, the list items
1537 # are the "ref" attributes of DependencyGraphNodes. Every target will 1541 # are the "ref" attributes of DependencyGraphNodes. Every target will
1538 # appear in flat_list after all of its dependencies, and before all of its 1542 # appear in flat_list after all of its dependencies, and before all of its
1539 # dependents. 1543 # dependents.
1540 flat_list = OrderedSet() 1544 flat_list = OrderedSet()
1541 1545
1546 def ExtractNodeRef(node):
1547 """Extracts the object that the node represents from the given node."""
1548 return node.ref
1549
1542 # in_degree_zeros is the list of DependencyGraphNodes that have no 1550 # in_degree_zeros is the list of DependencyGraphNodes that have no
1543 # dependencies not in flat_list. Initially, it is a copy of the children 1551 # dependencies not in flat_list. Initially, it is a copy of the children
1544 # of this node, because when the graph was built, nodes with no 1552 # of this node, because when the graph was built, nodes with no
1545 # dependencies were made implicit dependents of the root node. 1553 # dependencies were made implicit dependents of the root node.
1546 in_degree_zeros = set(self.dependents[:]) 1554 in_degree_zeros = OrderDeterministically(self.dependents[:],
1555 key=ExtractNodeRef)
1547 1556
1548 while in_degree_zeros: 1557 while in_degree_zeros:
1549 # Nodes in in_degree_zeros have no dependencies not in flat_list, so they 1558 # Nodes in in_degree_zeros have no dependencies not in flat_list, so they
1550 # can be appended to flat_list. Take these nodes out of in_degree_zeros 1559 # can be appended to flat_list. Take these nodes out of in_degree_zeros
1551 # as work progresses, so that the next node to process from the list can 1560 # as work progresses, so that the next node to process from the list can
1552 # always be accessed at a consistent position. 1561 # always be accessed at a consistent position.
1553 node = in_degree_zeros.pop() 1562 node = in_degree_zeros.pop()
1554 flat_list.add(node.ref) 1563 flat_list.add(node.ref)
1555 1564
1556 # Look at dependents of the node just added to flat_list. Some of them 1565 # Look at dependents of the node just added to flat_list. Some of them
1557 # may now belong in in_degree_zeros. 1566 # may now belong in in_degree_zeros.
1558 for node_dependent in node.dependents: 1567 for node_dependent in OrderDeterministically(node.dependents,
1568 key=ExtractNodeRef):
1559 is_in_degree_zero = True 1569 is_in_degree_zero = True
1560 # TODO: We want to check through the 1570 # TODO: We want to check through the
1561 # node_dependent.dependencies list but if it's long and we 1571 # node_dependent.dependencies list but if it's long and we
1562 # always start at the beginning, then we get O(n^2) behaviour. 1572 # always start at the beginning, then we get O(n^2) behaviour.
1563 for node_dependent_dependency in node_dependent.dependencies: 1573 for node_dependent_dependency in (
1574 OrderDeterministically(node_dependent.dependencies,
1575 key=ExtractNodeRef)):
1564 if not node_dependent_dependency.ref in flat_list: 1576 if not node_dependent_dependency.ref in flat_list:
1565 # The dependent one or more dependencies not in flat_list. There 1577 # The dependent one or more dependencies not in flat_list. There
1566 # will be more chances to add it to flat_list when examining 1578 # will be more chances to add it to flat_list when examining
1567 # it again as a dependent of those other dependencies, provided 1579 # it again as a dependent of those other dependencies, provided
1568 # that there are no cycles. 1580 # that there are no cycles.
1569 is_in_degree_zero = False 1581 is_in_degree_zero = False
1570 break 1582 break
1571 1583
1572 if is_in_degree_zero: 1584 if is_in_degree_zero:
1573 # All of the dependent's dependencies are already in flat_list. Add 1585 # All of the dependent's dependencies are already in flat_list. Add
1574 # it to in_degree_zeros where it will be processed in a future 1586 # it to in_degree_zeros where it will be processed in a future
1575 # iteration of the outer loop. 1587 # iteration of the outer loop.
1576 in_degree_zeros.add(node_dependent) 1588 in_degree_zeros += [node_dependent]
1577 1589
1578 return list(flat_list) 1590 return list(flat_list)
1579 1591
1580 def FindCycles(self): 1592 def FindCycles(self):
1581 """ 1593 """
1582 Returns a list of cycles in the graph, where each cycle is its own list. 1594 Returns a list of cycles in the graph, where each cycle is its own list.
1583 """ 1595 """
1584 results = [] 1596 results = []
1585 visited = set() 1597 visited = set()
1586 1598
(...skipping 1298 matching lines...) Expand 10 before | Expand all | Expand 10 after
2885 ValidateRunAsInTarget(target, target_dict, build_file) 2897 ValidateRunAsInTarget(target, target_dict, build_file)
2886 ValidateActionsInTarget(target, target_dict, build_file) 2898 ValidateActionsInTarget(target, target_dict, build_file)
2887 2899
2888 # Generators might not expect ints. Turn them into strs. 2900 # Generators might not expect ints. Turn them into strs.
2889 TurnIntIntoStrInDict(data) 2901 TurnIntIntoStrInDict(data)
2890 2902
2891 # TODO(mark): Return |data| for now because the generator needs a list of 2903 # TODO(mark): Return |data| for now because the generator needs a list of
2892 # build files that came in. In the future, maybe it should just accept 2904 # build files that came in. In the future, maybe it should just accept
2893 # a list, and not the whole data dict. 2905 # a list, and not the whole data dict.
2894 return [flat_list, targets, data] 2906 return [flat_list, targets, data]
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698