Chromium Code Reviews| Index: pylib/gyp/xcode_emulation.py |
| =================================================================== |
| --- pylib/gyp/xcode_emulation.py (revision 1364) |
| +++ pylib/gyp/xcode_emulation.py (working copy) |
| @@ -968,7 +968,7 @@ |
| expansions dict. If the variable expands to something that references |
| another variable, this variable is expanded as well if it's in env -- |
| until no variables present in env are left.""" |
| - for k in reversed(TopologicallySortedEnvVarKeys(expansions)): |
| + for k in TopologicallySortedEnvVarKeys(expansions): |
| string = string.replace('${' + k + '}', expansions[k]) |
| string = string.replace('$(' + k + ')', expansions[k]) |
| string = string.replace('$' + k, expansions[k]) |
| @@ -978,7 +978,7 @@ |
| def TopologicallySortedEnvVarKeys(env): |
| """Takes a dict |env| whose values are strings that can refer to other keys, |
| for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of |
| - env such that key2 is after key1 in L if env[key2] refers to env[key1]. |
| + env such that key1 is after key2 in L if env[key2] refers to env[key1]. |
| Throws an Exception in case of dependency cycles. |
| """ |
| @@ -986,62 +986,20 @@ |
| # 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): |
|
Nico
2012/05/11 14:53:44
This function is the wrong way round. We want an e
bradn
2012/05/11 18:57:23
Done.
|
| + # Get all variable references for variable defined in env. |
| + 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: |
| + return gyp.common.TopologicallySorted(env.keys(), GetEdges) |
| + 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.""" |