|
1 import marshal |
|
2 import bkfile |
|
3 |
|
4 |
|
5 # Write a file containing frozen code for the modules in the dictionary. |
|
6 |
|
7 header = """ |
|
8 #include "Python.h" |
|
9 |
|
10 static struct _frozen _PyImport_FrozenModules[] = { |
|
11 """ |
|
12 trailer = """\ |
|
13 {0, 0, 0} /* sentinel */ |
|
14 }; |
|
15 """ |
|
16 |
|
17 # if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app. |
|
18 default_entry_point = """ |
|
19 int |
|
20 main(int argc, char **argv) |
|
21 { |
|
22 extern int Py_FrozenMain(int, char **); |
|
23 """ + ((not __debug__ and """ |
|
24 Py_OptimizeFlag++; |
|
25 """) or "") + """ |
|
26 PyImport_FrozenModules = _PyImport_FrozenModules; |
|
27 return Py_FrozenMain(argc, argv); |
|
28 } |
|
29 |
|
30 """ |
|
31 |
|
32 def makefreeze(base, dict, debug=0, entry_point=None, fail_import=()): |
|
33 if entry_point is None: entry_point = default_entry_point |
|
34 done = [] |
|
35 files = [] |
|
36 mods = dict.keys() |
|
37 mods.sort() |
|
38 for mod in mods: |
|
39 m = dict[mod] |
|
40 mangled = "__".join(mod.split(".")) |
|
41 if m.__code__: |
|
42 file = 'M_' + mangled + '.c' |
|
43 outfp = bkfile.open(base + file, 'w') |
|
44 files.append(file) |
|
45 if debug: |
|
46 print "freezing", mod, "..." |
|
47 str = marshal.dumps(m.__code__) |
|
48 size = len(str) |
|
49 if m.__path__: |
|
50 # Indicate package by negative size |
|
51 size = -size |
|
52 done.append((mod, mangled, size)) |
|
53 writecode(outfp, mangled, str) |
|
54 outfp.close() |
|
55 if debug: |
|
56 print "generating table of frozen modules" |
|
57 outfp = bkfile.open(base + 'frozen.c', 'w') |
|
58 for mod, mangled, size in done: |
|
59 outfp.write('extern unsigned char M_%s[];\n' % mangled) |
|
60 outfp.write(header) |
|
61 for mod, mangled, size in done: |
|
62 outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size)) |
|
63 outfp.write('\n') |
|
64 # The following modules have a NULL code pointer, indicating |
|
65 # that the prozen program should not search for them on the host |
|
66 # system. Importing them will *always* raise an ImportError. |
|
67 # The zero value size is never used. |
|
68 for mod in fail_import: |
|
69 outfp.write('\t{"%s", NULL, 0},\n' % (mod,)) |
|
70 outfp.write(trailer) |
|
71 outfp.write(entry_point) |
|
72 outfp.close() |
|
73 return files |
|
74 |
|
75 |
|
76 |
|
77 # Write a C initializer for a module containing the frozen python code. |
|
78 # The array is called M_<mod>. |
|
79 |
|
80 def writecode(outfp, mod, str): |
|
81 outfp.write('unsigned char M_%s[] = {' % mod) |
|
82 for i in range(0, len(str), 16): |
|
83 outfp.write('\n\t') |
|
84 for c in str[i:i+16]: |
|
85 outfp.write('%d,' % ord(c)) |
|
86 outfp.write('\n};\n') |
|
87 |
|
88 ## def writecode(outfp, mod, str): |
|
89 ## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str), |
|
90 ## '\\"'.join(map(lambda s: repr(s)[1:-1], str.split('"'))))) |