Index: pylib/gyp/xcode_emulation.py |
=================================================================== |
--- pylib/gyp/xcode_emulation.py (revision 1374) |
+++ pylib/gyp/xcode_emulation.py (working copy) |
@@ -979,62 +979,29 @@ |
# order is important. Below is the logic to compute the dependency graph |
# and sort it. |
regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}') |
- |
- # First sort the list of keys. |
- key_list = sorted(env.keys()) |
- |
- # Phase 1: Create a set of edges of (DEPENDEE, DEPENDER) where in the graph, |
- # DEPENDEE -> DEPENDER. Also create sets of dependers and dependees. |
- edges = set() |
- dependees = set() |
- dependers = set() |
- for k in key_list: |
- matches = regex.findall(env[k]) |
- if not len(matches): |
- continue |
- |
- depends_on_other_var = False |
+ def GetEdges(node): |
+ # Use a definition of edges such that user_of_variable -> used_varible. |
+ # This happens to be easier in this case, since a variable's |
+ # definition contains all variables it references in a single string. |
+ # We can then reverse the result of the topological sort at the end. |
+ # Since: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) |
+ matches = set([v for v in regex.findall(env[node]) if v in env]) |
for dependee in matches: |
assert '${' not in dependee, 'Nested variables not supported: ' + dependee |
- if dependee in env: |
- edges.add((dependee, k)) |
- dependees.add(dependee) |
- depends_on_other_var = True |
- if depends_on_other_var: |
- dependers.add(k) |
+ return matches |
- # Phase 2: Create a list of graph nodes with no incoming edges. |
- sorted_nodes = [] |
- edgeless_nodes = dependees - dependers |
+ try: |
+ # Topologically sort, and then reverse, because we used an edge definition |
+ # that's inverted from the expected result of this function (see comment |
+ # above). |
+ order = gyp.common.TopologicallySorted(env.keys(), GetEdges) |
+ order.reverse() |
+ return order |
+ except CycleError, e: |
+ raise Exception( |
+ 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) |
- # Phase 3: Perform Kahn topological sort. |
- while len(edgeless_nodes): |
- # Find a node with no incoming edges, add it to the sorted list, and |
- # remove it from the list of nodes that aren't part of the graph. |
- node = edgeless_nodes.pop() |
- sorted_nodes.append(node) |
- key_list.remove(node) |
- # Find all the edges between |node| and other nodes. |
- edges_to_node = [e for e in edges if e[0] == node] |
- for edge in edges_to_node: |
- edges.remove(edge) |
- # If the node connected to |node| by |edge| has no other incoming edges, |
- # add it to |edgeless_nodes|. |
- if not len([e for e in edges if e[1] == edge[1]]): |
- edgeless_nodes.add(edge[1]) |
- |
- # Any remaining edges indicate a cycle. |
- if len(edges): |
- raise Exception('Xcode environment variables are cyclically dependent: ' + |
- str(edges)) |
- |
- # Append the "nodes" not in the graph to those that were just sorted. |
- sorted_nodes.extend(key_list) |
- |
- return sorted_nodes |
- |
- |
def GetSpecPostbuildCommands(spec, quiet=False): |
"""Returns the list of postbuilds explicitly defined on |spec|, in a form |
executable by a shell.""" |