Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Tools/freeze/makefreeze.py
12 views
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 = sorted(dict.keys())
37
for mod in mods:
38
m = dict[mod]
39
mangled = "__".join(mod.split("."))
40
if m.__code__:
41
file = 'M_' + mangled + '.c'
42
with bkfile.open(base + file, 'w') as outfp:
43
files.append(file)
44
if debug:
45
print("freezing", mod, "...")
46
str = marshal.dumps(m.__code__)
47
size = len(str)
48
is_package = '0'
49
if m.__path__:
50
is_package = '1'
51
done.append((mod, mangled, size, is_package))
52
writecode(outfp, mangled, str)
53
if debug:
54
print("generating table of frozen modules")
55
with bkfile.open(base + 'frozen.c', 'w') as outfp:
56
for mod, mangled, size, _ in done:
57
outfp.write('extern unsigned char M_%s[];\n' % mangled)
58
outfp.write(header)
59
for mod, mangled, size, is_package in done:
60
outfp.write('\t{"%s", M_%s, %d, %s},\n' % (mod, mangled, size, is_package))
61
outfp.write('\n')
62
# The following modules have a NULL code pointer, indicating
63
# that the frozen program should not search for them on the host
64
# system. Importing them will *always* raise an ImportError.
65
# The zero value size is never used.
66
for mod in fail_import:
67
outfp.write('\t{"%s", NULL, 0},\n' % (mod,))
68
outfp.write(trailer)
69
outfp.write(entry_point)
70
return files
71
72
73
74
# Write a C initializer for a module containing the frozen python code.
75
# The array is called M_<mod>.
76
77
def writecode(fp, mod, data):
78
print('unsigned char M_%s[] = {' % mod, file=fp)
79
indent = ' ' * 4
80
for i in range(0, len(data), 16):
81
print(indent, file=fp, end='')
82
for c in bytes(data[i:i+16]):
83
print('%d,' % c, file=fp, end='')
84
print('', file=fp)
85
print('};', file=fp)
86
87