blob: f66066455a73d05f3eb4d7a437a4e2026ead4242 [file] [log] [blame]
Guido van Rossum00ff4331994-10-03 16:33:08 +00001import marshal
2
3
4# Write a file containing frozen code for the modules in the dictionary.
5
6header = """
Guido van Rossumf75f80e1996-06-17 17:48:30 +00007#include "Python.h"
8
9static struct _frozen _PyImport_FrozenModules[] = {
Guido van Rossum00ff4331994-10-03 16:33:08 +000010"""
11trailer = """\
12 {0, 0, 0} /* sentinel */
13};
Guido van Rossumf75f80e1996-06-17 17:48:30 +000014
15struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules;
Guido van Rossum00ff4331994-10-03 16:33:08 +000016"""
17
18def makefreeze(outfp, dict):
19 done = []
20 mods = dict.keys()
21 mods.sort()
22 for mod in mods:
23 modfn = dict[mod]
24 try:
25 str = makecode(modfn)
26 except IOError, msg:
27 sys.stderr.write("%s: %s\n" % (modfn, str(msg)))
28 continue
29 if str:
30 done.append(mod, len(str))
31 writecode(outfp, mod, str)
32 outfp.write(header)
33 for mod, size in done:
34 outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mod, size))
35 outfp.write(trailer)
36
37
38# Return code string for a given module -- either a .py or a .pyc
39# file. Return either a string or None (if it's not Python code).
40# May raise IOError.
41
42def makecode(filename):
43 if filename[-3:] == '.py':
44 f = open(filename, 'r')
45 try:
46 text = f.read()
47 code = compile(text, filename, 'exec')
48 finally:
49 f.close()
50 return marshal.dumps(code)
51 if filename[-4:] == '.pyc':
52 f = open(filename, 'rb')
53 try:
54 f.seek(8)
55 str = f.read()
56 finally:
57 f.close()
58 return str
59 # Can't generate code for this extension
60 return None
61
62
63# Write a C initializer for a module containing the frozen python code.
64# The array is called M_<mod>.
65
66def writecode(outfp, mod, str):
67 outfp.write('static unsigned char M_%s[] = {' % mod)
68 for i in range(0, len(str), 16):
69 outfp.write('\n\t')
70 for c in str[i:i+16]:
71 outfp.write('%d,' % ord(c))
72 outfp.write('\n};\n')
73
74
75# Test for the above functions.
76
77def test():
78 import os
79 import sys
80 if not sys.argv[1:]:
81 print 'usage: python freezepython.py file.py(c) ...'
82 sys.exit(2)
83 dict = {}
84 for arg in sys.argv[1:]:
85 base = os.path.basename(arg)
86 mod, ext = os.path.splitext(base)
87 dict[mod] = arg
88 makefreeze(sys.stdout, dict)
89
90if __name__ == '__main__':
91 test()