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('"')))))
|
---|