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