Add option to show dependency tags in soongdbg

Test: soongdbg between --svg ~/Desktop/foo.svg --deptags android.content.pm.flags-aconfig PackageInstaller
Change-Id: I00786ff982ecff71e6f3cdc8d72bba5f23a093b5
This commit is contained in:
Joe Onorato 2024-02-09 16:35:27 -08:00
parent b3ffad1992
commit 04b63b1870

View file

@ -30,6 +30,7 @@ class Graph:
dep = get_or_make_node(self.nodes, d.id, None) dep = get_or_make_node(self.nodes, d.id, None)
node.deps.add(dep) node.deps.add(dep)
dep.rdeps.add(node) dep.rdeps.add(node)
node.dep_tags.setdefault(dep, list()).append(d)
def find_paths(self, id1, id2): def find_paths(self, id1, id2):
# Throws KeyError if one of the names isn't found # Throws KeyError if one of the names isn't found
@ -63,6 +64,7 @@ class Node:
self.module = module self.module = module
self.deps = set() self.deps = set()
self.rdeps = set() self.rdeps = set()
self.dep_tags = {}
PROVIDERS = [ PROVIDERS = [
@ -71,6 +73,20 @@ PROVIDERS = [
] ]
def format_dep_label(node, dep):
tags = node.dep_tags.get(dep)
labels = []
if tags:
labels = [tag.tag_type.split("/")[-1] for tag in tags]
labels = sorted(set(labels))
if labels:
result = "<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
for label in labels:
result += f"<tr><td>{label}</td></tr>"
result += "</table>>"
return result
def format_node_label(node, module_formatter): def format_node_label(node, module_formatter):
result = "<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">" result = "<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
@ -196,6 +212,8 @@ def load_and_filter_modules(args):
def print_args(parser): def print_args(parser):
parser.add_argument("--label", action="append", metavar="JQ_FILTER", parser.add_argument("--label", action="append", metavar="JQ_FILTER",
help="jq query for each module metadata") help="jq query for each module metadata")
parser.add_argument("--deptags", action="store_true",
help="show dependency tags (makes the graph much more complex)")
group = parser.add_argument_group("output formats", group = parser.add_argument_group("output formats",
"If no format is provided, a dot file will be written to" "If no format is provided, a dot file will be written to"
@ -209,13 +227,24 @@ def print_args(parser):
def print_nodes(args, nodes, module_formatter): def print_nodes(args, nodes, module_formatter):
# Generate the graphviz # Generate the graphviz
dep_tag_id = 0
dot = io.StringIO() dot = io.StringIO()
dot.write("digraph {\n") dot.write("digraph {\n")
dot.write("node [shape=box];")
for node in nodes: for node in nodes:
dot.write(f"\"{node.id}\"[label={format_node_label(node, module_formatter)}];\n") dot.write(f"\"{node.id}\" [label={format_node_label(node, module_formatter)}];\n")
for dep in node.deps: for dep in node.deps:
if dep in nodes: if dep in nodes:
dot.write(f"\"{node.id}\" -> \"{dep.id}\";\n") if args.deptags:
dot.write(f"\"{node.id}\" -> \"__dep_tag_{dep_tag_id}\" [ arrowhead=none ];\n")
dot.write(f"\"__dep_tag_{dep_tag_id}\" -> \"{dep.id}\";\n")
dot.write(f"\"__dep_tag_{dep_tag_id}\""
+ f"[label={format_dep_label(node, dep)} shape=ellipse"
+ " color=\"#666666\" fontcolor=\"#666666\"];\n")
else:
dot.write(f"\"{node.id}\" -> \"{dep.id}\";\n")
dep_tag_id += 1
dot.write("}\n") dot.write("}\n")
text = dot.getvalue() text = dot.getvalue()
@ -224,7 +253,7 @@ def print_nodes(args, nodes, module_formatter):
with open(args.dot, "w") as f: with open(args.dot, "w") as f:
f.write(text) f.write(text)
elif args.svg: elif args.svg:
subprocess.run(["dot", "-Tsvg", "-Nshape=box", "-o", args.svg], subprocess.run(["dot", "-Tsvg", "-o", args.svg],
input=text, text=True, check=True) input=text, text=True, check=True)
else: else:
sys.stdout.write(text) sys.stdout.write(text)