home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Python 1.1 / Demo / freeze / freeze.py < prev    next >
Encoding:
Python Source  |  1994-10-05  |  6.0 KB  |  251 lines  |  [TEXT/R*ch]

  1. #! /usr/local/bin/python
  2.  
  3. # "Freeze" a Python script into a binary.
  4. # Usage: see variable usage_msg below (before the imports!)
  5.  
  6. # HINTS:
  7. # - Edit the lines marked XXX below to localize.
  8. # - You must have done "make inclinstall libainstall" in the Python
  9. #   build directory.
  10. # - The script should not use dynamically loaded modules
  11. #   (*.so on most systems).
  12.  
  13.  
  14. # Usage message
  15.  
  16. usage_msg = """
  17. usage: freeze [-p prefix] [-e extension] ... script [module] ...
  18.  
  19. -p prefix:    This is the prefix used when you ran
  20.               'Make inclinstall libainstall' in the Python build directory.
  21.               (If you never ran this, freeze won't work.)
  22.                The default is /usr/local.
  23.  
  24. -e extension: A directory containing additional .o files that
  25.               may be used to resolve modules.  This directory
  26.               should also have a Setup file describing the .o files.
  27.               More than one -e option may be given.
  28.  
  29. script:       The Python script to be executed by the resulting binary.
  30.  
  31. module ...:   Additional Python modules (referenced by pathname)
  32.               that will be included in the resulting binary.  These
  33.               may be .py or .pyc files.
  34. """
  35.  
  36.  
  37. # XXX Change the following line to point to your Demo/freeze directory
  38. PACK = '/ufs/guido/src/python/Demo/freeze'
  39.  
  40. # XXX Change the following line to point to your install prefix
  41. PREFIX = '/usr/local'
  42.  
  43.  
  44. # Import standard modules
  45.  
  46. import cmp
  47. import getopt
  48. import os
  49. import string
  50. import sys
  51. import addpack
  52.  
  53.  
  54. # Set the directory to look for the freeze-private modules
  55.  
  56. dir = os.path.dirname(sys.argv[0])
  57. if dir:
  58.     pack = dir
  59. else:
  60.     pack = PACK
  61. addpack.addpack(pack)
  62.  
  63.  
  64. # Import the freeze-private modules
  65.  
  66. import checkextensions
  67. import findmodules
  68. import makeconfig
  69. import makefreeze
  70. import makemakefile
  71. import parsesetup
  72.  
  73.  
  74. # Main program
  75.  
  76. def main():
  77.     # overridable context
  78.     prefix = PREFIX            # settable with -p option
  79.     extensions = []
  80.     path = sys.path
  81.  
  82.     # output files
  83.     frozen_c = 'frozen.c'
  84.     config_c = 'config.c'
  85.     target = 'a.out'        # normally derived from script name
  86.     makefile = 'Makefile'
  87.  
  88.     # parse command line
  89.     try:
  90.         opts, args = getopt.getopt(sys.argv[1:], 'e:p:')
  91.     except getopt.error, msg:
  92.         usage('getopt error: ' + str(msg))
  93.  
  94.     # proces option arguments
  95.     for o, a in opts:
  96.         if o == '-e':
  97.             extensions.append(a)
  98.         if o == '-p':
  99.             prefix = a
  100.  
  101.     # locations derived from options
  102.     binlib = os.path.join(prefix, 'lib/python/lib')
  103.     incldir = os.path.join(prefix, 'include/Py')
  104.     config_c_in = os.path.join(binlib, 'config.c.in')
  105.     frozenmain_c = os.path.join(binlib, 'frozenmain.c')
  106.     makefile_in = os.path.join(binlib, 'Makefile')
  107.     defines = ['-DHAVE_CONFIG_H', '-DUSE_FROZEN', '-DNO_MAIN',
  108.            '-DPYTHONPATH=\\"$(PYTHONPATH)\\"']
  109.     includes = ['-I' + incldir, '-I' + binlib]
  110.  
  111.     # sanity check of directories and files
  112.     for dir in [prefix, binlib, incldir] + extensions:
  113.         if not os.path.exists(dir):
  114.             usage('needed directory %s not found' % dir)
  115.         if not os.path.isdir(dir):
  116.             usage('%s: not a directory' % dir)
  117.     for file in config_c_in, makefile_in, frozenmain_c:
  118.         if not os.path.exists(file):
  119.             usage('needed file %s not found' % file)
  120.         if not os.path.isfile(file):
  121.             usage('%s: not a plain file' % file)
  122.     for dir in extensions:
  123.         setup = os.path.join(dir, 'Setup')
  124.         if not os.path.exists(setup):
  125.             usage('needed file %s not found' % setup)
  126.         if not os.path.isfile(setup):
  127.             usage('%s: not a plain file' % setup)
  128.  
  129.     # check that enough arguments are passed
  130.     if not args:
  131.         usage('at least one filename argument required')
  132.  
  133.     # check that file arguments exist
  134.     for arg in args:
  135.         if not os.path.exists(arg):
  136.             usage('argument %s not found' % arg)
  137.         if not os.path.isfile(arg):
  138.             usage('%s: not a plain file' % arg)
  139.  
  140.     # process non-option arguments
  141.     scriptfile = args[0]
  142.     modules = args[1:]
  143.  
  144.     # derive target name from script name
  145.     base = os.path.basename(scriptfile)
  146.     base, ext = os.path.splitext(base)
  147.     if base:
  148.         if base != scriptfile:
  149.             target = base
  150.         else:
  151.             target = base + '.bin'
  152.  
  153.     # Actual work starts here...
  154.  
  155.     dict = findmodules.findmodules(scriptfile, modules, path)
  156.  
  157.     backup = frozen_c + '~'
  158.     try:
  159.         os.rename(frozen_c, backup)
  160.     except os.error:
  161.         backup = None
  162.     outfp = open(frozen_c, 'w')
  163.     try:
  164.         makefreeze.makefreeze(outfp, dict)
  165.     finally:
  166.         outfp.close()
  167.     if backup:
  168.         if cmp.cmp(backup, frozen_c):
  169.             sys.stderr.write('%s not changed, not written\n' %
  170.                      frozen_c)
  171.             os.rename(backup, frozen_c)
  172.  
  173.     builtins = []
  174.     unknown = []
  175.     mods = dict.keys()
  176.     mods.sort()
  177.     for mod in mods:
  178.         if dict[mod] == '<builtin>':
  179.             builtins.append(mod)
  180.         elif dict[mod] == '<unknown>':
  181.             unknown.append(mod)
  182.  
  183.     addfiles = []
  184.     if unknown:
  185.         addfiles, addmods = \
  186.               checkextensions.checkextensions(unknown, extensions)
  187.         for mod in addmods:
  188.             unknown.remove(mod)
  189.         builtins = builtins + addmods
  190.     if unknown:
  191.         sys.stderr.write('Warning: unknown modules remain: %s\n' %
  192.                  string.join(unknown))
  193.  
  194.     builtins.sort()
  195.     infp = open(config_c_in)
  196.     backup = config_c + '~'
  197.     try:
  198.         os.rename(config_c, backup)
  199.     except os.error:
  200.         backup = None
  201.     outfp = open(config_c, 'w')
  202.     try:
  203.         makeconfig.makeconfig(infp, outfp, builtins)
  204.     finally:
  205.         outfp.close()
  206.     infp.close()
  207.     if backup:
  208.         if cmp.cmp(backup, config_c):
  209.             sys.stderr.write('%s not changed, not written\n' %
  210.                      config_c)
  211.             os.rename(backup, config_c)
  212.  
  213.     cflags = defines + includes + ['$(OPT)']
  214.     libs = []
  215.     for n in 'Modules', 'Python', 'Objects', 'Parser':
  216.         n = 'lib%s.a' % n
  217.         n = os.path.join(binlib, n)
  218.         libs.append(n)
  219.  
  220.     makevars = parsesetup.getmakevars(makefile_in)
  221.     somevars = {}
  222.     for key in makevars.keys():
  223.         somevars[key] = makevars[key]
  224.  
  225.     somevars['CFLAGS'] = string.join(cflags) # override
  226.     files = ['$(OPT)', config_c, frozen_c, frozenmain_c] + \
  227.         addfiles + libs + \
  228.         ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
  229.  
  230.     outfp = open(makefile, 'w')
  231.     try:
  232.         makemakefile.makemakefile(outfp, somevars, files, target)
  233.     finally:
  234.         outfp.close()
  235.  
  236.     # Done!
  237.  
  238.     print 'Now run make to build the target:', target
  239.  
  240.  
  241. # Print usage message and exit
  242.  
  243. def usage(msg = None):
  244.     if msg:
  245.         sys.stderr.write(str(msg) + '\n')
  246.     sys.stderr.write(usage_msg)
  247.     sys.exit(2)
  248.  
  249.  
  250. main()
  251.