[2] | 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
|
---|
[391] | 65 | # that the frozen program should not search for them on the host
|
---|
[2] | 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('"')))))
|
---|