nm2def.py 2.42 KB
Newer Older
1
#! /usr/bin/env python3
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
"""nm2def.py

Helpers to extract symbols from Unix libs and auto-generate
Windows definition files from them. Depends on nm(1). Tested
on Linux and Solaris only (-p option to nm is for Solaris only).

By Marc-Andre Lemburg, Aug 1998.

Additional notes: the output of nm is supposed to look like this:

acceler.o:
000001fd T PyGrammar_AddAccelerators
         U PyGrammar_FindDFA
00000237 T PyGrammar_RemoveAccelerators
         U _IO_stderr_
         U exit
         U fprintf
         U free
         U malloc
         U printf

grammar1.o:
00000000 T PyGrammar_FindDFA
00000034 T PyGrammar_LabelRepr
         U _PyParser_TokenNames
         U abort
         U printf
         U sprintf

...

Even if this isn't the default output of your nm, there is generally an
option to produce this format (since it is the original v7 Unix format).

"""
37
import os, sys
38

39 40
PYTHONLIB = 'libpython%d.%d.a' % sys.version_info[:2]
PC_PYTHONLIB = 'Python%d%d.dll' % sys.version_info[:2]
41 42 43 44
NM = 'nm -p -g %s'                      # For Linux, use "nm -g %s"

def symbols(lib=PYTHONLIB,types=('T','C','D')):

45 46
    with os.popen(NM % lib) as pipe:
        lines = pipe.readlines()
47
    lines = [s.strip() for s in lines]
48 49
    symbols = {}
    for line in lines:
Guido van Rossum's avatar
Guido van Rossum committed
50 51
        if len(line) == 0 or ':' in line:
            continue
52
        items = line.split()
Guido van Rossum's avatar
Guido van Rossum committed
53 54 55 56 57 58
        if len(items) != 3:
            continue
        address, type, name = items
        if type not in types:
            continue
        symbols[name] = address,type
59 60 61 62 63 64 65
    return symbols

def export_list(symbols):

    data = []
    code = []
    for name,(addr,type) in symbols.items():
Guido van Rossum's avatar
Guido van Rossum committed
66 67 68 69
        if type in ('C','D'):
            data.append('\t'+name)
        else:
            code.append('\t'+name)
70 71 72
    data.sort()
    data.append('')
    code.sort()
73
    return ' DATA\n'.join(data)+'\n'+'\n'.join(code)
74 75 76 77 78 79 80 81 82 83 84 85 86 87

# Definition file template
DEF_TEMPLATE = """\
EXPORTS
%s
"""

# Special symbols that have to be included even though they don't
# pass the filter
SPECIALS = (
    )

def filter_Python(symbols,specials=SPECIALS):

88
    for name in list(symbols.keys()):
Guido van Rossum's avatar
Guido van Rossum committed
89 90 91 92
        if name[:2] == 'Py' or name[:3] == '_Py':
            pass
        elif name not in specials:
            del symbols[name]
93 94 95 96 97 98 99 100

def main():

    s = symbols(PYTHONLIB)
    filter_Python(s)
    exports = export_list(s)
    f = sys.stdout # open('PC/python_nt.def','w')
    f.write(DEF_TEMPLATE % (exports))
101
    # f.close()
Tim Peters's avatar
Tim Peters committed
102

103 104
if __name__ == '__main__':
    main()