以下 Python 脚本可用于收集和处理nm
当前目录中所有目标文件的输出:
#! /usr/bin/env python
import collections
import os
import re
import subprocess
addr_re = r"(?P<address>[0-9a-f]{1,16})?"
code_re = r"(?P<code>[a-z])"
symbol_re = r"(?P<symbol>[a-z0-9_.$]+)"
nm_line_re = re.compile(r"\s+".join([addr_re, code_re, symbol_re]) + "\s*$",
re.I)
requires = collections.defaultdict(set)
provides = collections.defaultdict(set)
def get_symbols(fname):
lines = subprocess.check_output(["nm", "-g", fname])
for l in lines.splitlines():
m = nm_line_re.match(l)
symbol = m.group('symbol')
if m.group('code') == 'U':
requires[fname].add(symbol)
else:
provides[symbol].add(fname)
for dirpath, dirnames, filenames in os.walk("."):
for f in filenames:
if f.endswith(".o"):
get_symbols(f)
def pick(symbols):
# If several files provide a symbol, choose the one with the shortest name.
best = None
for s in symbols:
if best is None or len(s) < len(best):
best = s
if len(symbols) > 1:
best = "*" + best
return best
for fname, symbols in requires.items():
dependencies = set(pick(provides[s]) for s in symbols if s in provides)
print fname + ': ' + ' '.join(sorted(dependencies))
该脚本在当前目录和所有子目录中搜索.o
文件,调用nm
找到的每个文件并剖析结果输出。在一个文件中未定义而在另一个文件中定义的符号.o
被解释为两个文件之间的依赖关系。无处定义的符号(通常由外部库提供)被忽略。最后,脚本打印所有目标文件的直接依赖项列表。
如果一个符号由多个目标文件提供,则此脚本任意假定依赖于具有最短文件名的目标文件(并*
在输出中用 a 标记所选文件)。这种行为可以通过修改函数来改变pick
。
该脚本适用于我在 Linux 和 MacOS 上,我没有尝试过任何其他操作系统,并且该脚本只是经过轻微测试。