Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-01 23:40:44

0001 #! /usr/bin/env python3
0002 
0003 import networkx as nx
0004 import collections
0005 import os
0006 import re
0007 import subprocess
0008 
0009 addr_re = r"(?P<address>[0-9a-f]{1,16})?"
0010 code_re = r"(?P<code>[a-zA-Z])"
0011 symbol_re = r"(?P<symbol>[a-zA-Z0-9_.$@]+)"
0012 symbol_demunged_re = r"(?P<symbol>[a-zA-Z0-9_.$@:&()<>{}\[\]|^!%,~*+-=# ]+)"
0013 symbols_re_skip = re.compile("(@@)")
0014 nm_line_re = re.compile(r"\s+".join([addr_re, code_re, symbol_re]) + r"\s*$",
0015                         re.I)
0016 ldd_line_re = re.compile(r"\s+(.*) => (.*) \(0x")
0017 
0018 requires = collections.defaultdict(set)
0019 provides = collections.defaultdict(set)
0020 dependencies = collections.defaultdict(set)
0021 libraries = collections.defaultdict(set)
0022 
0023 
0024 def get_symbols(fname):
0025     lines = subprocess.check_output(["nm", "-g", fname])
0026     for line in lines.splitlines():
0027         m = nm_line_re.match(line)
0028         if not m:
0029             continue
0030         symbol = m.group('symbol')
0031         if m.group('code') == 'U':
0032             requires[os.path.basename(fname)].add(symbol)
0033         else:
0034             provides[symbol].add(os.path.basename(fname))
0035 
0036 
0037 def get_libraries(fname):
0038     lines = subprocess.check_output(["ldd", fname])
0039     for line in lines.splitlines():
0040         m = ldd_line_re.match(line)
0041         if not m:
0042             continue
0043         library = m.group(2)
0044         libraries[os.path.basename(fname)].add(
0045             os.path.basename(library.rstrip('\r\n')))
0046 
0047 
0048 paths = os.environ['LD_LIBRARY_PATH'].split(':')
0049 
0050 for p in paths:
0051     for dirpath, dirnames, filenames in os.walk(p):
0052         for f in filenames:
0053             fpth = os.path.realpath(os.path.join(dirpath, f))
0054             filetype = subprocess.check_output(["file", fpth])
0055             if filetype.find("dynamically linked") >= 0:
0056                 get_symbols(fpth)
0057                 get_libraries(fpth)
0058 
0059 for fname, symbols in requires.items():
0060     deps = set()
0061     for library in libraries[fname]:
0062         for s in symbols:
0063             if library in provides[s]:
0064                 deps.add(library)
0065     dependencies[fname] = deps
0066     print(fname + ' : primary dependencies : ' +
0067           ',  '.join(sorted(dependencies[fname]))+'\n')
0068     unmet = set()
0069     demangled = set()
0070     for s in symbols:
0071         if s not in provides and not symbols_re_skip.search(s):
0072             unmet.add(s)
0073     for u in sorted(unmet):
0074         dm = subprocess.check_output(["c++filt", u])
0075         demangled.add(dm.rstrip('\r\n'))
0076     if demangled:
0077         print(fname + ': undefined : ' + ',  '.join(sorted(demangled)))
0078 
0079 G = nx.DiGraph()
0080 for key, values in dependencies.items():
0081     G.add_node(key)
0082     for val in values:
0083         G.add_edge(key, val)
0084 
0085 for node in nx.nodes_iter(G):
0086     s = nx.dfs_successors(G, node)
0087     deps = set()
0088     if s:
0089         for key, vals in s.items():
0090             if key != node:
0091                 deps.add(key)
0092             for v in vals:
0093                 deps.add(v)
0094     print(node + ': primary and secondary dependencies :' + ', '.join(sorted(deps)))
0095 
0096 
0097 H = nx.DiGraph()
0098 for key, values in dependencies.items():
0099     H.add_node(os.path.basename(key))
0100     for val in values:
0101         H.add_edge(os.path.basename(key), os.path.basename(val))
0102 for node in nx.nodes_iter(H):
0103     T = nx.dfs_tree(H, node)
0104     name = node + ".dot"
0105     nx.write_dot(T, name)