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