summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct1
-rw-r--r--buildscripts/libdeps/SCHEMA_CHANGE_LOG.txt3
-rw-r--r--buildscripts/libdeps/analyzer_unittests.py38
-rwxr-xr-xbuildscripts/libdeps/gacli.py9
-rw-r--r--buildscripts/libdeps/libdeps/analyzer.py63
-rw-r--r--buildscripts/libdeps/libdeps/graph.py3
-rw-r--r--site_scons/libdeps_next.py3
7 files changed, 72 insertions, 48 deletions
diff --git a/SConstruct b/SConstruct
index be5c60e5956..fb573d5513c 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1284,7 +1284,6 @@ def shim_library(env, name, needs_link=False, *args, **kwargs):
for n in nodes:
setattr(n.attributes, "needs_link", needs_link)
- setattr(n.attributes, "is_shim", True)
return nodes
diff --git a/buildscripts/libdeps/SCHEMA_CHANGE_LOG.txt b/buildscripts/libdeps/SCHEMA_CHANGE_LOG.txt
new file mode 100644
index 00000000000..4e170dfd6e1
--- /dev/null
+++ b/buildscripts/libdeps/SCHEMA_CHANGE_LOG.txt
@@ -0,0 +1,3 @@
+3 removed shim node property
+2 flipped edge direction in graph file data
+1 initial schema \ No newline at end of file
diff --git a/buildscripts/libdeps/analyzer_unittests.py b/buildscripts/libdeps/analyzer_unittests.py
index c0f9b3bbd2d..b1f0fde43a3 100644
--- a/buildscripts/libdeps/analyzer_unittests.py
+++ b/buildscripts/libdeps/analyzer_unittests.py
@@ -33,10 +33,10 @@ import libdeps.analyzer
from libdeps.graph import LibdepsGraph, EdgeProps, NodeProps, CountTypes
-def add_node(graph, node, builder, shim):
+def add_node(graph, node, builder):
"""Add a node to the graph."""
- graph.add_nodes_from([(node, {NodeProps.bin_type.name: builder, NodeProps.shim.name: shim})])
+ graph.add_nodes_from([(node, {NodeProps.bin_type.name: builder})])
def add_edge(graph, from_node, to_node, **kwargs):
@@ -74,15 +74,15 @@ def get_double_diamond_mock_graph():
# \lib4.so \lib8.so
#
- add_node(graph, 'lib1.so', 'SharedLibrary', False)
- add_node(graph, 'lib2.so', 'SharedLibrary', False)
- add_node(graph, 'lib3.so', 'SharedLibrary', False)
- add_node(graph, 'lib4.so', 'SharedLibrary', False)
- add_node(graph, 'lib5.so', 'SharedLibrary', False)
- add_node(graph, 'lib6.so', 'SharedLibrary', False)
- add_node(graph, 'lib7.so', 'SharedLibrary', False)
- add_node(graph, 'lib8.so', 'SharedLibrary', False)
- add_node(graph, 'lib9.so', 'SharedLibrary', False)
+ add_node(graph, 'lib1.so', 'SharedLibrary')
+ add_node(graph, 'lib2.so', 'SharedLibrary')
+ add_node(graph, 'lib3.so', 'SharedLibrary')
+ add_node(graph, 'lib4.so', 'SharedLibrary')
+ add_node(graph, 'lib5.so', 'SharedLibrary')
+ add_node(graph, 'lib6.so', 'SharedLibrary')
+ add_node(graph, 'lib7.so', 'SharedLibrary')
+ add_node(graph, 'lib8.so', 'SharedLibrary')
+ add_node(graph, 'lib9.so', 'SharedLibrary')
add_edge(graph, 'lib1.so', 'lib2.so', direct=True, visibility=graph.get_deptype('Public'))
add_edge(graph, 'lib2.so', 'lib3.so', direct=True, visibility=graph.get_deptype('Public'))
@@ -159,12 +159,12 @@ def get_basic_mock_graph():
# \-lib6.so
# nodes
- add_node(graph, 'lib1.so', 'SharedLibrary', False)
- add_node(graph, 'lib2.so', 'SharedLibrary', False)
- add_node(graph, 'lib3.so', 'SharedLibrary', False)
- add_node(graph, 'lib4.so', 'SharedLibrary', False)
- add_node(graph, 'lib5.so', 'SharedLibrary', False)
- add_node(graph, 'lib6.so', 'SharedLibrary', False)
+ add_node(graph, 'lib1.so', 'SharedLibrary')
+ add_node(graph, 'lib2.so', 'SharedLibrary')
+ add_node(graph, 'lib3.so', 'SharedLibrary')
+ add_node(graph, 'lib4.so', 'SharedLibrary')
+ add_node(graph, 'lib5.so', 'SharedLibrary')
+ add_node(graph, 'lib6.so', 'SharedLibrary')
# direct edges
add_edge(graph, 'lib1.so', 'lib2.so', direct=True, visibility=graph.get_deptype('Public'))
@@ -428,7 +428,7 @@ class Tests(unittest.TestCase):
expected_result = {
"NODE": 6, "EDGE": 13, "DIR_EDGE": 7, "TRANS_EDGE": 6, "DIR_PUB_EDGE": 6,
- "PUB_EDGE": 12, "PRIV_EDGE": 1, "IF_EDGE": 0, "SHIM": 0, "PROG": 0, "LIB": 6
+ "PUB_EDGE": 12, "PRIV_EDGE": 1, "IF_EDGE": 0, "PROG": 0, "LIB": 6
}
self.run_counts(expected_result, libdeps_graph)
@@ -439,7 +439,7 @@ class Tests(unittest.TestCase):
expected_result = {
"NODE": 9, "EDGE": 34, "DIR_EDGE": 10, "TRANS_EDGE": 24, "DIR_PUB_EDGE": 10,
- "PUB_EDGE": 34, "PRIV_EDGE": 0, "IF_EDGE": 0, "SHIM": 0, "PROG": 0, "LIB": 9
+ "PUB_EDGE": 34, "PRIV_EDGE": 0, "IF_EDGE": 0, "PROG": 0, "LIB": 9
}
self.run_counts(expected_result, libdeps_graph)
diff --git a/buildscripts/libdeps/gacli.py b/buildscripts/libdeps/gacli.py
index 6b0bafb467b..9b71e1544fe 100755
--- a/buildscripts/libdeps/gacli.py
+++ b/buildscripts/libdeps/gacli.py
@@ -103,7 +103,6 @@ class CustomFormatter(argparse.RawTextHelpFormatter, argparse.ArgumentDefaultsHe
{help_text[CountTypes.PUB_EDGE.name]}count edges that are public
{help_text[CountTypes.PRIV_EDGE.name]}count edges that are private
{help_text[CountTypes.IF_EDGE.name]}count edges that are interface
- {help_text[CountTypes.SHIM.name]}count shim nodes
{help_text[CountTypes.LIB.name]}count library nodes
{help_text[CountTypes.PROG.name]}count program nodes
""")
@@ -159,6 +158,11 @@ def setup_args_parser():
"[from_node] [to_node]: Print edges between two nodes, which if removed would break the dependency between those "
+ "nodes,.")
+ parser.add_argument(
+ '--indegree-one', action='store_true', default=False, help=
+ "Find candidate nodes for merging by searching the graph for nodes with only one node which depends on them."
+ )
+
args = parser.parse_args()
for arg_list in args.graph_paths:
@@ -212,6 +216,9 @@ def main():
analysis.append(
libdeps_analyzer.CriticalEdges(libdeps_graph, analyzer_args[0], analyzer_args[1]))
+ if args.indegree_one:
+ analysis.append(libdeps_analyzer.InDegreeOne(libdeps_graph))
+
analysis += libdeps_analyzer.linter_factory(libdeps_graph, args.lint)
if args.build_data:
diff --git a/buildscripts/libdeps/libdeps/analyzer.py b/buildscripts/libdeps/libdeps/analyzer.py
index 58f18413e0a..756d410d4e8 100644
--- a/buildscripts/libdeps/libdeps/analyzer.py
+++ b/buildscripts/libdeps/libdeps/analyzer.py
@@ -328,22 +328,6 @@ class InterfaceEdgeCounter(Counter):
int(self.get_deptype('Interface')))
-class ShimCounter(Counter):
- """Counts and reports number of shim nodes in the graph."""
-
- def __init__(self, graph):
- """Store graph and set type."""
-
- super().__init__(graph)
- self._count_type = CountTypes.SHIM.name
-
- @schema_check(schema_version=1)
- def run(self):
- """Count the graphs shim nodes."""
-
- return self.node_type_count(NodeProps.shim.name, True)
-
-
class LibCounter(Counter):
"""Counts and reports number of library nodes in the graph."""
@@ -388,7 +372,6 @@ def counter_factory(graph, counters, progressbar=True):
CountTypes.PUB_EDGE.name: PublicEdgeCounter,
CountTypes.PRIV_EDGE.name: PrivateEdgeCounter,
CountTypes.IF_EDGE.name: InterfaceEdgeCounter,
- CountTypes.SHIM.name: ShimCounter,
CountTypes.LIB.name: LibCounter,
CountTypes.PROG.name: ProgCounter,
}
@@ -492,6 +475,37 @@ class ExcludeDependents(Analyzer):
report[DependsReportTypes.EXCLUDE_DEPENDS.name][tuple(self._nodes)] = self.run()
+class InDegreeOne(Analyzer):
+ """
+ Finds library nodes which have 1 or 0 dependers.
+
+ Such libraries are good candidates for merging or deletion.
+ """
+
+ @schema_check(schema_version=1)
+ def run(self):
+ """Search the graph for in degree 1 or 0 nodes."""
+
+ in_degree_one_nodes = []
+ for node, data in self._dependency_graph.nodes(data=True):
+ if (len(self._dependents_graph[node]) < 2
+ and data[NodeProps.bin_type.name] == 'SharedLibrary'):
+
+ if len(self._dependents_graph[node]) == 1:
+ depender = list(self._dependents_graph[node].items())[0][0]
+ else:
+ depender = None
+
+ in_degree_one_nodes.append([node, depender])
+
+ return sorted(in_degree_one_nodes)
+
+ def report(self, report):
+ """Add the indegree one list to the report."""
+
+ report[DependsReportTypes.IN_DEGREE_ONE.name] = self.run()
+
+
class GraphPaths(Analyzer):
"""Finds all paths between two nodes in the graph."""
@@ -631,11 +645,10 @@ class UnusedPublicLinter(Analyzer):
for edge in self._dependents_graph.edges:
edge_attribs = self._dependents_graph[edge[0]][edge[1]]
- if (edge_attribs.get(EdgeProps.direct.name) and edge_attribs.get(
- EdgeProps.visibility.name) == int(self.get_deptype('Public'))
- and not self._dependents_graph.nodes()[edge[0]].get(NodeProps.shim.name)
- and self._dependents_graph.nodes()[edge[1]].get(
- NodeProps.bin_type.name) == 'SharedLibrary'):
+ if (edge_attribs.get(EdgeProps.direct.name)
+ and edge_attribs.get(EdgeProps.visibility.name) == int(
+ self.get_deptype('Public')) and self._dependents_graph.nodes()[edge[1]].get(
+ NodeProps.bin_type.name) == 'SharedLibrary'):
# First we will get all the transitive libdeps the dependent node
# induces, while we are getting those we also check if the depender
@@ -760,7 +773,6 @@ class GaPrettyPrinter(GaPrinter):
CountTypes.PUB_EDGE.name: "Public Edges in Graph: {}",
CountTypes.PRIV_EDGE.name: "Private Edges in Graph: {}",
CountTypes.IF_EDGE.name: "Interface Edges in Graph: {}",
- CountTypes.SHIM.name: "Shim Nodes in Graph: {}",
CountTypes.LIB.name: "Library Nodes in Graph: {}",
CountTypes.PROG.name: "Program Nodes in Graph: {}",
}
@@ -813,6 +825,11 @@ class GaPrettyPrinter(GaPrinter):
f"=>critical edges between {nodes[0]} and {nodes[1]}:",
results[DependsReportTypes.CRITICAL_EDGES.name][nodes])
+ if DependsReportTypes.IN_DEGREE_ONE.name in results:
+ print("\nLibrary nodes with 1 or 0 dependers:")
+ for count, nodes in enumerate(results[DependsReportTypes.IN_DEGREE_ONE.name], start=1):
+ print(f" {count}: '{nodes[0]}' <- '{nodes[1]}'")
+
def print(self):
"""Print the result data."""
results = self._libdeps_graph_analysis.get_results()
diff --git a/buildscripts/libdeps/libdeps/graph.py b/buildscripts/libdeps/libdeps/graph.py
index 078b832ceb2..2e7dbbcd234 100644
--- a/buildscripts/libdeps/libdeps/graph.py
+++ b/buildscripts/libdeps/libdeps/graph.py
@@ -54,7 +54,6 @@ class CountTypes(Enum):
PUB_EDGE = auto()
PRIV_EDGE = auto()
IF_EDGE = auto()
- SHIM = auto()
PROG = auto()
LIB = auto()
@@ -67,6 +66,7 @@ class DependsReportTypes(Enum):
EXCLUDE_DEPENDS = auto()
GRAPH_PATHS = auto()
CRITICAL_EDGES = auto()
+ IN_DEGREE_ONE = auto()
class LinterTypes(Enum):
@@ -87,7 +87,6 @@ class EdgeProps(Enum):
class NodeProps(Enum):
"""Enums for node properties."""
- shim = auto()
bin_type = auto()
diff --git a/site_scons/libdeps_next.py b/site_scons/libdeps_next.py
index 194613d3e8a..402b3d265dd 100644
--- a/site_scons/libdeps_next.py
+++ b/site_scons/libdeps_next.py
@@ -964,7 +964,6 @@ def add_node_from(env, node):
str(node.abspath),
{
NodeProps.bin_type.name: node.builder.get_name(env),
- NodeProps.shim.name: getattr(node.attributes, "is_shim", False)
})])
def add_edge_from(env, from_node, to_node, visibility, direct):
@@ -1438,7 +1437,7 @@ def setup_environment(env, emitting_shared=False, debug='off', linting='on', san
env['LIBDEPS_SYMBOL_DEP_FILES'] = symbol_deps
env['LIBDEPS_GRAPH_FILE'] = env.File("${BUILD_DIR}/libdeps/libdeps.graphml")
- env['LIBDEPS_GRAPH_SCHEMA_VERSION'] = 2
+ env['LIBDEPS_GRAPH_SCHEMA_VERSION'] = 3
env["SYMBOLDEPSSUFFIX"] = '.symbol_deps'
libdeps_graph = LibdepsGraph()