/Tools/freeze/makefreeze.py

http://unladen-swallow.googlecode.com/ · Python · 90 lines · 68 code · 10 blank · 12 comment · 13 complexity · 817a00cde90dfb39ee285f34aa6b5979 MD5 · raw file

  1. import marshal
  2. import bkfile
  3. # Write a file containing frozen code for the modules in the dictionary.
  4. header = """
  5. #include "Python.h"
  6. static struct _frozen _PyImport_FrozenModules[] = {
  7. """
  8. trailer = """\
  9. {0, 0, 0} /* sentinel */
  10. };
  11. """
  12. # if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app.
  13. default_entry_point = """
  14. int
  15. main(int argc, char **argv)
  16. {
  17. extern int Py_FrozenMain(int, char **);
  18. """ + ((not __debug__ and """
  19. Py_OptimizeFlag++;
  20. """) or "") + """
  21. PyImport_FrozenModules = _PyImport_FrozenModules;
  22. return Py_FrozenMain(argc, argv);
  23. }
  24. """
  25. def makefreeze(base, dict, debug=0, entry_point=None, fail_import=()):
  26. if entry_point is None: entry_point = default_entry_point
  27. done = []
  28. files = []
  29. mods = dict.keys()
  30. mods.sort()
  31. for mod in mods:
  32. m = dict[mod]
  33. mangled = "__".join(mod.split("."))
  34. if m.__code__:
  35. file = 'M_' + mangled + '.c'
  36. outfp = bkfile.open(base + file, 'w')
  37. files.append(file)
  38. if debug:
  39. print "freezing", mod, "..."
  40. str = marshal.dumps(m.__code__)
  41. size = len(str)
  42. if m.__path__:
  43. # Indicate package by negative size
  44. size = -size
  45. done.append((mod, mangled, size))
  46. writecode(outfp, mangled, str)
  47. outfp.close()
  48. if debug:
  49. print "generating table of frozen modules"
  50. outfp = bkfile.open(base + 'frozen.c', 'w')
  51. for mod, mangled, size in done:
  52. outfp.write('extern unsigned char M_%s[];\n' % mangled)
  53. outfp.write(header)
  54. for mod, mangled, size in done:
  55. outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size))
  56. outfp.write('\n')
  57. # The following modules have a NULL code pointer, indicating
  58. # that the prozen program should not search for them on the host
  59. # system. Importing them will *always* raise an ImportError.
  60. # The zero value size is never used.
  61. for mod in fail_import:
  62. outfp.write('\t{"%s", NULL, 0},\n' % (mod,))
  63. outfp.write(trailer)
  64. outfp.write(entry_point)
  65. outfp.close()
  66. return files
  67. # Write a C initializer for a module containing the frozen python code.
  68. # The array is called M_<mod>.
  69. def writecode(outfp, mod, str):
  70. outfp.write('unsigned char M_%s[] = {' % mod)
  71. for i in range(0, len(str), 16):
  72. outfp.write('\n\t')
  73. for c in str[i:i+16]:
  74. outfp.write('%d,' % ord(c))
  75. outfp.write('\n};\n')
  76. ## def writecode(outfp, mod, str):
  77. ## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str),
  78. ## '\\"'.join(map(lambda s: repr(s)[1:-1], str.split('"')))))