Make transitive_deps as a topologically sorted list

pull/21515/head
Esun Kim 5 years ago
parent a27b2c2015
commit 4a68e396a2
  1. 2
      templates/gRPC-C++.podspec.template
  2. 2
      templates/gRPC-Core.podspec.template
  3. 53
      tools/buildgen/plugins/transitive_dependencies.py

@ -35,7 +35,7 @@
return "abseil/" + label[5:].replace(":", "/") return "abseil/" + label[5:].replace(":", "/")
def lib_and_transitive_deps(lib): def lib_and_transitive_deps(lib):
return list(sorted(set({lib} | lib_maps[lib].transitive_deps))) return list(sorted(set({lib} | set(lib_maps[lib].transitive_deps))))
def non_abseil_lib_and_transitive_deps(lib): def non_abseil_lib_and_transitive_deps(lib):
return [l for l in lib_and_transitive_deps(lib) if not is_absl_lib(l)] return [l for l in lib_and_transitive_deps(lib) if not is_absl_lib(l)]

@ -34,7 +34,7 @@
return "abseil/" + label[5:].replace(":", "/") return "abseil/" + label[5:].replace(":", "/")
def lib_and_transitive_deps(lib): def lib_and_transitive_deps(lib):
return list(sorted(set({lib} | lib_maps[lib].transitive_deps))) return list(sorted(set({lib} | set(lib_maps[lib].transitive_deps))))
def non_abseil_lib_and_transitive_deps(lib): def non_abseil_lib_and_transitive_deps(lib):
return [l for l in lib_and_transitive_deps(lib) if not is_absl_lib(l)] return [l for l in lib_and_transitive_deps(lib) if not is_absl_lib(l)]

@ -16,43 +16,48 @@
This takes the list of libs, node_modules, and targets from our This takes the list of libs, node_modules, and targets from our
yaml dictionary, and adds to each the transitive closure yaml dictionary, and adds to each the transitive closure
of the list of dependencies. of the list of dependencies.
""" """
def get_lib(libs, name): def transitive_deps(lib_map, node):
try: """Returns a list of transitive dependencies from node.
return next(lib for lib in libs if lib['name'] == name)
except StopIteration: Recursively iterate all dependent node in a depth-first fashion and
return None list a result using a topological sorting.
"""
result = []
seen = set()
start = node
def recursive_helper(node):
if node is None:
return
for dep in node.get("deps", []):
if dep not in seen:
seen.add(dep)
next_node = lib_map.get(dep)
recursive_helper(next_node)
if node is not start:
result.insert(0, node["name"])
def transitive_deps(lib, libs): recursive_helper(node)
if lib is not None and 'deps' in lib: return result
# Recursively call transitive_deps on each dependency, and take the union
return set.union(
set(lib['deps']), *[
set(transitive_deps(get_lib(libs, dep), libs))
for dep in lib['deps']
])
else:
return set()
def mako_plugin(dictionary): def mako_plugin(dictionary):
"""The exported plugin code for transitive_dependencies. """The exported plugin code for transitive_dependencies.
Iterate over each list and check each item for a deps list. We add a Iterate over each list and check each item for a deps list. We add a
transitive_deps property to each with the transitive closure of those transitive_deps property to each with the transitive closure of those
dependency lists. dependency lists. The result list is sorted in a topological ordering.
""" """
libs = dictionary.get('libs') lib_map = {lib['name']: lib for lib in dictionary.get('libs')}
for target_name, target_list in dictionary.items(): for target_name, target_list in dictionary.items():
for target in target_list: for target in target_list:
if isinstance(target, dict) and 'deps' in target: if isinstance(target, dict) and 'deps' in target:
target['transitive_deps'] = transitive_deps(target, libs) target['transitive_deps'] = transitive_deps(lib_map, target)
python_dependencies = dictionary.get('python_dependencies') python_dependencies = dictionary.get('python_dependencies')
python_dependencies['transitive_deps'] = (transitive_deps( python_dependencies['transitive_deps'] = transitive_deps(
python_dependencies, libs)) lib_map, python_dependencies)

Loading…
Cancel
Save