Home | History | Annotate | Download | only in freeze
      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('"')))))
     91