Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:49

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