17db96d56Sopenharmony_ciimport marshal
27db96d56Sopenharmony_ciimport bkfile
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ci# Write a file containing frozen code for the modules in the dictionary.
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciheader = """
87db96d56Sopenharmony_ci#include "Python.h"
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_cistatic struct _frozen _PyImport_FrozenModules[] = {
117db96d56Sopenharmony_ci"""
127db96d56Sopenharmony_citrailer = """\
137db96d56Sopenharmony_ci    {0, 0, 0} /* sentinel */
147db96d56Sopenharmony_ci};
157db96d56Sopenharmony_ci"""
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci# if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app.
187db96d56Sopenharmony_cidefault_entry_point = """
197db96d56Sopenharmony_ciint
207db96d56Sopenharmony_cimain(int argc, char **argv)
217db96d56Sopenharmony_ci{
227db96d56Sopenharmony_ci        extern int Py_FrozenMain(int, char **);
237db96d56Sopenharmony_ci""" + ((not __debug__ and """
247db96d56Sopenharmony_ci        Py_OptimizeFlag++;
257db96d56Sopenharmony_ci""") or "")  + """
267db96d56Sopenharmony_ci        PyImport_FrozenModules = _PyImport_FrozenModules;
277db96d56Sopenharmony_ci        return Py_FrozenMain(argc, argv);
287db96d56Sopenharmony_ci}
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci"""
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_cidef makefreeze(base, dict, debug=0, entry_point=None, fail_import=()):
337db96d56Sopenharmony_ci    if entry_point is None: entry_point = default_entry_point
347db96d56Sopenharmony_ci    done = []
357db96d56Sopenharmony_ci    files = []
367db96d56Sopenharmony_ci    mods = sorted(dict.keys())
377db96d56Sopenharmony_ci    for mod in mods:
387db96d56Sopenharmony_ci        m = dict[mod]
397db96d56Sopenharmony_ci        mangled = "__".join(mod.split("."))
407db96d56Sopenharmony_ci        if m.__code__:
417db96d56Sopenharmony_ci            file = 'M_' + mangled + '.c'
427db96d56Sopenharmony_ci            with bkfile.open(base + file, 'w') as outfp:
437db96d56Sopenharmony_ci                files.append(file)
447db96d56Sopenharmony_ci                if debug:
457db96d56Sopenharmony_ci                    print("freezing", mod, "...")
467db96d56Sopenharmony_ci                str = marshal.dumps(m.__code__)
477db96d56Sopenharmony_ci                size = len(str)
487db96d56Sopenharmony_ci                is_package = '0'
497db96d56Sopenharmony_ci                if m.__path__:
507db96d56Sopenharmony_ci                    is_package = '1'
517db96d56Sopenharmony_ci                done.append((mod, mangled, size, is_package))
527db96d56Sopenharmony_ci                writecode(outfp, mangled, str)
537db96d56Sopenharmony_ci    if debug:
547db96d56Sopenharmony_ci        print("generating table of frozen modules")
557db96d56Sopenharmony_ci    with bkfile.open(base + 'frozen.c', 'w') as outfp:
567db96d56Sopenharmony_ci        for mod, mangled, size, _ in done:
577db96d56Sopenharmony_ci            outfp.write('extern unsigned char M_%s[];\n' % mangled)
587db96d56Sopenharmony_ci        outfp.write(header)
597db96d56Sopenharmony_ci        for mod, mangled, size, is_package in done:
607db96d56Sopenharmony_ci            outfp.write('\t{"%s", M_%s, %d, %s},\n' % (mod, mangled, size, is_package))
617db96d56Sopenharmony_ci        outfp.write('\n')
627db96d56Sopenharmony_ci        # The following modules have a NULL code pointer, indicating
637db96d56Sopenharmony_ci        # that the frozen program should not search for them on the host
647db96d56Sopenharmony_ci        # system. Importing them will *always* raise an ImportError.
657db96d56Sopenharmony_ci        # The zero value size is never used.
667db96d56Sopenharmony_ci        for mod in fail_import:
677db96d56Sopenharmony_ci            outfp.write('\t{"%s", NULL, 0},\n' % (mod,))
687db96d56Sopenharmony_ci        outfp.write(trailer)
697db96d56Sopenharmony_ci        outfp.write(entry_point)
707db96d56Sopenharmony_ci    return files
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci# Write a C initializer for a module containing the frozen python code.
757db96d56Sopenharmony_ci# The array is called M_<mod>.
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_cidef writecode(fp, mod, data):
787db96d56Sopenharmony_ci    print('unsigned char M_%s[] = {' % mod, file=fp)
797db96d56Sopenharmony_ci    indent = ' ' * 4
807db96d56Sopenharmony_ci    for i in range(0, len(data), 16):
817db96d56Sopenharmony_ci        print(indent, file=fp, end='')
827db96d56Sopenharmony_ci        for c in bytes(data[i:i+16]):
837db96d56Sopenharmony_ci            print('%d,' % c, file=fp, end='')
847db96d56Sopenharmony_ci        print('', file=fp)
857db96d56Sopenharmony_ci    print('};', file=fp)
86