Add a tools that detects include cycles in the Dolphin codebase.
This commit is contained in:
parent
48f930c06e
commit
65bbfdb812
|
@ -0,0 +1,80 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
|
||||||
|
'''
|
||||||
|
Run this script from Source/Core/ to find all the #include cycles.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def get_local_includes_for(path):
|
||||||
|
lines = open(path).read().split('\n')
|
||||||
|
includes = [l.strip() for l in lines if l.strip().startswith('#include')]
|
||||||
|
return [i.split()[1][1:-1] for i in includes if '"' in i.split()[1]]
|
||||||
|
|
||||||
|
def find_all_files():
|
||||||
|
'''Could probably use os.walk, but meh.'''
|
||||||
|
f = subprocess.check_output(['find', '.', '-name', '*.h'],
|
||||||
|
universal_newlines=True).strip().split('\n')
|
||||||
|
return [p[2:] for p in f]
|
||||||
|
|
||||||
|
def make_include_graph():
|
||||||
|
return { f: get_local_includes_for(f) for f in find_all_files() }
|
||||||
|
|
||||||
|
def strongly_connected_components(graph):
|
||||||
|
"""
|
||||||
|
Tarjan's Algorithm (named for its discoverer, Robert Tarjan) is a graph theory algorithm
|
||||||
|
for finding the strongly connected components of a graph.
|
||||||
|
|
||||||
|
Based on: http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
|
||||||
|
"""
|
||||||
|
|
||||||
|
index_counter = [0]
|
||||||
|
stack = []
|
||||||
|
lowlinks = {}
|
||||||
|
index = {}
|
||||||
|
result = []
|
||||||
|
|
||||||
|
def strongconnect(node):
|
||||||
|
# set the depth index for this node to the smallest unused index
|
||||||
|
index[node] = index_counter[0]
|
||||||
|
lowlinks[node] = index_counter[0]
|
||||||
|
index_counter[0] += 1
|
||||||
|
stack.append(node)
|
||||||
|
|
||||||
|
# Consider successors of `node`
|
||||||
|
try:
|
||||||
|
successors = graph[node]
|
||||||
|
except:
|
||||||
|
successors = []
|
||||||
|
for successor in successors:
|
||||||
|
if successor not in lowlinks:
|
||||||
|
# Successor has not yet been visited; recurse on it
|
||||||
|
strongconnect(successor)
|
||||||
|
lowlinks[node] = min(lowlinks[node],lowlinks[successor])
|
||||||
|
elif successor in stack:
|
||||||
|
# the successor is in the stack and hence in the current strongly connected component (SCC)
|
||||||
|
lowlinks[node] = min(lowlinks[node],index[successor])
|
||||||
|
|
||||||
|
# If `node` is a root node, pop the stack and generate an SCC
|
||||||
|
if lowlinks[node] == index[node]:
|
||||||
|
connected_component = []
|
||||||
|
|
||||||
|
while True:
|
||||||
|
successor = stack.pop()
|
||||||
|
connected_component.append(successor)
|
||||||
|
if successor == node: break
|
||||||
|
component = tuple(connected_component)
|
||||||
|
# storing the result
|
||||||
|
result.append(component)
|
||||||
|
|
||||||
|
for node in graph:
|
||||||
|
if node not in lowlinks:
|
||||||
|
strongconnect(node)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
comp = strongly_connected_components(make_include_graph())
|
||||||
|
for c in comp:
|
||||||
|
if len(c) != 1:
|
||||||
|
print(c)
|
Loading…
Reference in New Issue