symbian-qemu-0.9.1-12/python-2.6.1/Tools/freeze/freeze.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #! /usr/bin/env python
       
     2 
       
     3 """Freeze a Python script into a binary.
       
     4 
       
     5 usage: freeze [options...] script [module]...
       
     6 
       
     7 Options:
       
     8 -p prefix:    This is the prefix used when you ran ``make install''
       
     9               in the Python build directory.
       
    10               (If you never ran this, freeze won't work.)
       
    11               The default is whatever sys.prefix evaluates to.
       
    12               It can also be the top directory of the Python source
       
    13               tree; then -P must point to the build tree.
       
    14 
       
    15 -P exec_prefix: Like -p but this is the 'exec_prefix', used to
       
    16                 install objects etc.  The default is whatever sys.exec_prefix
       
    17                 evaluates to, or the -p argument if given.
       
    18                 If -p points to the Python source tree, -P must point
       
    19                 to the build tree, if different.
       
    20 
       
    21 -e extension: A directory containing additional .o files that
       
    22               may be used to resolve modules.  This directory
       
    23               should also have a Setup file describing the .o files.
       
    24               On Windows, the name of a .INI file describing one
       
    25               or more extensions is passed.
       
    26               More than one -e option may be given.
       
    27 
       
    28 -o dir:       Directory where the output files are created; default '.'.
       
    29 
       
    30 -m:           Additional arguments are module names instead of filenames.
       
    31 
       
    32 -a package=dir: Additional directories to be added to the package's
       
    33                 __path__.  Used to simulate directories added by the
       
    34                 package at runtime (eg, by OpenGL and win32com).
       
    35                 More than one -a option may be given for each package.
       
    36 
       
    37 -l file:      Pass the file to the linker (windows only)
       
    38 
       
    39 -d:           Debugging mode for the module finder.
       
    40 
       
    41 -q:           Make the module finder totally quiet.
       
    42 
       
    43 -h:           Print this help message.
       
    44 
       
    45 -x module     Exclude the specified module. It will still be imported
       
    46               by the frozen binary if it exists on the host system.
       
    47 
       
    48 -X module     Like -x, except the module can never be imported by
       
    49               the frozen binary.
       
    50 
       
    51 -E:           Freeze will fail if any modules can't be found (that
       
    52               were not excluded using -x or -X).
       
    53 
       
    54 -i filename:  Include a file with additional command line options.  Used
       
    55               to prevent command lines growing beyond the capabilities of
       
    56               the shell/OS.  All arguments specified in filename
       
    57               are read and the -i option replaced with the parsed
       
    58               params (note - quoting args in this file is NOT supported)
       
    59 
       
    60 -s subsystem: Specify the subsystem (For Windows only.);
       
    61               'console' (default), 'windows', 'service' or 'com_dll'
       
    62 
       
    63 -w:           Toggle Windows (NT or 95) behavior.
       
    64               (For debugging only -- on a win32 platform, win32 behavior
       
    65               is automatic.)
       
    66 
       
    67 -r prefix=f:  Replace path prefix.
       
    68               Replace prefix with f in the source path references
       
    69               contained in the resulting binary.
       
    70 
       
    71 Arguments:
       
    72 
       
    73 script:       The Python script to be executed by the resulting binary.
       
    74 
       
    75 module ...:   Additional Python modules (referenced by pathname)
       
    76               that will be included in the resulting binary.  These
       
    77               may be .py or .pyc files.  If -m is specified, these are
       
    78               module names that are search in the path instead.
       
    79 
       
    80 NOTES:
       
    81 
       
    82 In order to use freeze successfully, you must have built Python and
       
    83 installed it ("make install").
       
    84 
       
    85 The script should not use modules provided only as shared libraries;
       
    86 if it does, the resulting binary is not self-contained.
       
    87 """
       
    88 
       
    89 
       
    90 # Import standard modules
       
    91 
       
    92 import modulefinder
       
    93 import getopt
       
    94 import os
       
    95 import sys
       
    96 
       
    97 
       
    98 # Import the freeze-private modules
       
    99 
       
   100 import checkextensions
       
   101 import makeconfig
       
   102 import makefreeze
       
   103 import makemakefile
       
   104 import parsesetup
       
   105 import bkfile
       
   106 
       
   107 
       
   108 # Main program
       
   109 
       
   110 def main():
       
   111     # overridable context
       
   112     prefix = None                       # settable with -p option
       
   113     exec_prefix = None                  # settable with -P option
       
   114     extensions = []
       
   115     exclude = []                        # settable with -x option
       
   116     addn_link = []      # settable with -l, but only honored under Windows.
       
   117     path = sys.path[:]
       
   118     modargs = 0
       
   119     debug = 1
       
   120     odir = ''
       
   121     win = sys.platform[:3] == 'win'
       
   122     replace_paths = []                  # settable with -r option
       
   123     error_if_any_missing = 0
       
   124 
       
   125     # default the exclude list for each platform
       
   126     if win: exclude = exclude + [
       
   127         'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix',
       
   128         'os2', 'ce', 'riscos', 'riscosenviron', 'riscospath',
       
   129         ]
       
   130 
       
   131     fail_import = exclude[:]
       
   132 
       
   133     # output files
       
   134     frozen_c = 'frozen.c'
       
   135     config_c = 'config.c'
       
   136     target = 'a.out'                    # normally derived from script name
       
   137     makefile = 'Makefile'
       
   138     subsystem = 'console'
       
   139 
       
   140     # parse command line by first replacing any "-i" options with the
       
   141     # file contents.
       
   142     pos = 1
       
   143     while pos < len(sys.argv)-1:
       
   144         # last option can not be "-i", so this ensures "pos+1" is in range!
       
   145         if sys.argv[pos] == '-i':
       
   146             try:
       
   147                 options = open(sys.argv[pos+1]).read().split()
       
   148             except IOError, why:
       
   149                 usage("File name '%s' specified with the -i option "
       
   150                       "can not be read - %s" % (sys.argv[pos+1], why) )
       
   151             # Replace the '-i' and the filename with the read params.
       
   152             sys.argv[pos:pos+2] = options
       
   153             pos = pos + len(options) - 1 # Skip the name and the included args.
       
   154         pos = pos + 1
       
   155 
       
   156     # Now parse the command line with the extras inserted.
       
   157     try:
       
   158         opts, args = getopt.getopt(sys.argv[1:], 'r:a:dEe:hmo:p:P:qs:wX:x:l:')
       
   159     except getopt.error, msg:
       
   160         usage('getopt error: ' + str(msg))
       
   161 
       
   162     # proces option arguments
       
   163     for o, a in opts:
       
   164         if o == '-h':
       
   165             print __doc__
       
   166             return
       
   167         if o == '-d':
       
   168             debug = debug + 1
       
   169         if o == '-e':
       
   170             extensions.append(a)
       
   171         if o == '-m':
       
   172             modargs = 1
       
   173         if o == '-o':
       
   174             odir = a
       
   175         if o == '-p':
       
   176             prefix = a
       
   177         if o == '-P':
       
   178             exec_prefix = a
       
   179         if o == '-q':
       
   180             debug = 0
       
   181         if o == '-w':
       
   182             win = not win
       
   183         if o == '-s':
       
   184             if not win:
       
   185                 usage("-s subsystem option only on Windows")
       
   186             subsystem = a
       
   187         if o == '-x':
       
   188             exclude.append(a)
       
   189         if o == '-X':
       
   190             exclude.append(a)
       
   191             fail_import.append(a)
       
   192         if o == '-E':
       
   193             error_if_any_missing = 1
       
   194         if o == '-l':
       
   195             addn_link.append(a)
       
   196         if o == '-a':
       
   197             apply(modulefinder.AddPackagePath, tuple(a.split("=", 2)))
       
   198         if o == '-r':
       
   199             f,r = a.split("=", 2)
       
   200             replace_paths.append( (f,r) )
       
   201 
       
   202     # modules that are imported by the Python runtime
       
   203     implicits = []
       
   204     for module in ('site', 'warnings',):
       
   205         if module not in exclude:
       
   206             implicits.append(module)
       
   207 
       
   208     # default prefix and exec_prefix
       
   209     if not exec_prefix:
       
   210         if prefix:
       
   211             exec_prefix = prefix
       
   212         else:
       
   213             exec_prefix = sys.exec_prefix
       
   214     if not prefix:
       
   215         prefix = sys.prefix
       
   216 
       
   217     # determine whether -p points to the Python source tree
       
   218     ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c'))
       
   219 
       
   220     # locations derived from options
       
   221     version = sys.version[:3]
       
   222     if win:
       
   223         extensions_c = 'frozen_extensions.c'
       
   224     if ishome:
       
   225         print "(Using Python source directory)"
       
   226         binlib = exec_prefix
       
   227         incldir = os.path.join(prefix, 'Include')
       
   228         config_h_dir = exec_prefix
       
   229         config_c_in = os.path.join(prefix, 'Modules', 'config.c.in')
       
   230         frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c')
       
   231         makefile_in = os.path.join(exec_prefix, 'Makefile')
       
   232         if win:
       
   233             frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c')
       
   234     else:
       
   235         binlib = os.path.join(exec_prefix,
       
   236                               'lib', 'python%s' % version, 'config')
       
   237         incldir = os.path.join(prefix, 'include', 'python%s' % version)
       
   238         config_h_dir = os.path.join(exec_prefix, 'include',
       
   239                                     'python%s' % version)
       
   240         config_c_in = os.path.join(binlib, 'config.c.in')
       
   241         frozenmain_c = os.path.join(binlib, 'frozenmain.c')
       
   242         makefile_in = os.path.join(binlib, 'Makefile')
       
   243         frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c')
       
   244     supp_sources = []
       
   245     defines = []
       
   246     includes = ['-I' + incldir, '-I' + config_h_dir]
       
   247 
       
   248     # sanity check of directories and files
       
   249     check_dirs = [prefix, exec_prefix, binlib, incldir]
       
   250     if not win:
       
   251         # These are not directories on Windows.
       
   252         check_dirs = check_dirs + extensions
       
   253     for dir in check_dirs:
       
   254         if not os.path.exists(dir):
       
   255             usage('needed directory %s not found' % dir)
       
   256         if not os.path.isdir(dir):
       
   257             usage('%s: not a directory' % dir)
       
   258     if win:
       
   259         files = supp_sources + extensions # extensions are files on Windows.
       
   260     else:
       
   261         files = [config_c_in, makefile_in] + supp_sources
       
   262     for file in supp_sources:
       
   263         if not os.path.exists(file):
       
   264             usage('needed file %s not found' % file)
       
   265         if not os.path.isfile(file):
       
   266             usage('%s: not a plain file' % file)
       
   267     if not win:
       
   268         for dir in extensions:
       
   269             setup = os.path.join(dir, 'Setup')
       
   270             if not os.path.exists(setup):
       
   271                 usage('needed file %s not found' % setup)
       
   272             if not os.path.isfile(setup):
       
   273                 usage('%s: not a plain file' % setup)
       
   274 
       
   275     # check that enough arguments are passed
       
   276     if not args:
       
   277         usage('at least one filename argument required')
       
   278 
       
   279     # check that file arguments exist
       
   280     for arg in args:
       
   281         if arg == '-m':
       
   282             break
       
   283         # if user specified -m on the command line before _any_
       
   284         # file names, then nothing should be checked (as the
       
   285         # very first file should be a module name)
       
   286         if modargs:
       
   287             break
       
   288         if not os.path.exists(arg):
       
   289             usage('argument %s not found' % arg)
       
   290         if not os.path.isfile(arg):
       
   291             usage('%s: not a plain file' % arg)
       
   292 
       
   293     # process non-option arguments
       
   294     scriptfile = args[0]
       
   295     modules = args[1:]
       
   296 
       
   297     # derive target name from script name
       
   298     base = os.path.basename(scriptfile)
       
   299     base, ext = os.path.splitext(base)
       
   300     if base:
       
   301         if base != scriptfile:
       
   302             target = base
       
   303         else:
       
   304             target = base + '.bin'
       
   305 
       
   306     # handle -o option
       
   307     base_frozen_c = frozen_c
       
   308     base_config_c = config_c
       
   309     base_target = target
       
   310     if odir and not os.path.isdir(odir):
       
   311         try:
       
   312             os.mkdir(odir)
       
   313             print "Created output directory", odir
       
   314         except os.error, msg:
       
   315             usage('%s: mkdir failed (%s)' % (odir, str(msg)))
       
   316     base = ''
       
   317     if odir:
       
   318         base = os.path.join(odir, '')
       
   319         frozen_c = os.path.join(odir, frozen_c)
       
   320         config_c = os.path.join(odir, config_c)
       
   321         target = os.path.join(odir, target)
       
   322         makefile = os.path.join(odir, makefile)
       
   323         if win: extensions_c = os.path.join(odir, extensions_c)
       
   324 
       
   325     # Handle special entry point requirements
       
   326     # (on Windows, some frozen programs do not use __main__, but
       
   327     # import the module directly.  Eg, DLLs, Services, etc
       
   328     custom_entry_point = None  # Currently only used on Windows
       
   329     python_entry_is_main = 1   # Is the entry point called __main__?
       
   330     # handle -s option on Windows
       
   331     if win:
       
   332         import winmakemakefile
       
   333         try:
       
   334             custom_entry_point, python_entry_is_main = \
       
   335                 winmakemakefile.get_custom_entry_point(subsystem)
       
   336         except ValueError, why:
       
   337             usage(why)
       
   338 
       
   339 
       
   340     # Actual work starts here...
       
   341 
       
   342     # collect all modules of the program
       
   343     dir = os.path.dirname(scriptfile)
       
   344     path[0] = dir
       
   345     mf = modulefinder.ModuleFinder(path, debug, exclude, replace_paths)
       
   346 
       
   347     if win and subsystem=='service':
       
   348         # If a Windows service, then add the "built-in" module.
       
   349         mod = mf.add_module("servicemanager")
       
   350         mod.__file__="dummy.pyd" # really built-in to the resulting EXE
       
   351 
       
   352     for mod in implicits:
       
   353         mf.import_hook(mod)
       
   354     for mod in modules:
       
   355         if mod == '-m':
       
   356             modargs = 1
       
   357             continue
       
   358         if modargs:
       
   359             if mod[-2:] == '.*':
       
   360                 mf.import_hook(mod[:-2], None, ["*"])
       
   361             else:
       
   362                 mf.import_hook(mod)
       
   363         else:
       
   364             mf.load_file(mod)
       
   365 
       
   366     # Add the main script as either __main__, or the actual module name.
       
   367     if python_entry_is_main:
       
   368         mf.run_script(scriptfile)
       
   369     else:
       
   370         mf.load_file(scriptfile)
       
   371 
       
   372     if debug > 0:
       
   373         mf.report()
       
   374         print
       
   375     dict = mf.modules
       
   376 
       
   377     if error_if_any_missing:
       
   378         missing = mf.any_missing()
       
   379         if missing:
       
   380             sys.exit("There are some missing modules: %r" % missing)
       
   381 
       
   382     # generate output for frozen modules
       
   383     files = makefreeze.makefreeze(base, dict, debug, custom_entry_point,
       
   384                                   fail_import)
       
   385 
       
   386     # look for unfrozen modules (builtin and of unknown origin)
       
   387     builtins = []
       
   388     unknown = []
       
   389     mods = dict.keys()
       
   390     mods.sort()
       
   391     for mod in mods:
       
   392         if dict[mod].__code__:
       
   393             continue
       
   394         if not dict[mod].__file__:
       
   395             builtins.append(mod)
       
   396         else:
       
   397             unknown.append(mod)
       
   398 
       
   399     # search for unknown modules in extensions directories (not on Windows)
       
   400     addfiles = []
       
   401     frozen_extensions = [] # Windows list of modules.
       
   402     if unknown or (not win and builtins):
       
   403         if not win:
       
   404             addfiles, addmods = \
       
   405                       checkextensions.checkextensions(unknown+builtins,
       
   406                                                       extensions)
       
   407             for mod in addmods:
       
   408                 if mod in unknown:
       
   409                     unknown.remove(mod)
       
   410                     builtins.append(mod)
       
   411         else:
       
   412             # Do the windows thang...
       
   413             import checkextensions_win32
       
   414             # Get a list of CExtension instances, each describing a module
       
   415             # (including its source files)
       
   416             frozen_extensions = checkextensions_win32.checkextensions(
       
   417                 unknown, extensions, prefix)
       
   418             for mod in frozen_extensions:
       
   419                 unknown.remove(mod.name)
       
   420 
       
   421     # report unknown modules
       
   422     if unknown:
       
   423         sys.stderr.write('Warning: unknown modules remain: %s\n' %
       
   424                          ' '.join(unknown))
       
   425 
       
   426     # windows gets different treatment
       
   427     if win:
       
   428         # Taking a shortcut here...
       
   429         import winmakemakefile, checkextensions_win32
       
   430         checkextensions_win32.write_extension_table(extensions_c,
       
   431                                                     frozen_extensions)
       
   432         # Create a module definition for the bootstrap C code.
       
   433         xtras = [frozenmain_c, os.path.basename(frozen_c),
       
   434                  frozendllmain_c, os.path.basename(extensions_c)] + files
       
   435         maindefn = checkextensions_win32.CExtension( '__main__', xtras )
       
   436         frozen_extensions.append( maindefn )
       
   437         outfp = open(makefile, 'w')
       
   438         try:
       
   439             winmakemakefile.makemakefile(outfp,
       
   440                                          locals(),
       
   441                                          frozen_extensions,
       
   442                                          os.path.basename(target))
       
   443         finally:
       
   444             outfp.close()
       
   445         return
       
   446 
       
   447     # generate config.c and Makefile
       
   448     builtins.sort()
       
   449     infp = open(config_c_in)
       
   450     outfp = bkfile.open(config_c, 'w')
       
   451     try:
       
   452         makeconfig.makeconfig(infp, outfp, builtins)
       
   453     finally:
       
   454         outfp.close()
       
   455     infp.close()
       
   456 
       
   457     cflags = ['$(OPT)']
       
   458     cppflags = defines + includes
       
   459     libs = [os.path.join(binlib, 'libpython$(VERSION).a')]
       
   460 
       
   461     somevars = {}
       
   462     if os.path.exists(makefile_in):
       
   463         makevars = parsesetup.getmakevars(makefile_in)
       
   464         for key in makevars.keys():
       
   465             somevars[key] = makevars[key]
       
   466 
       
   467     somevars['CFLAGS'] = ' '.join(cflags) # override
       
   468     somevars['CPPFLAGS'] = ' '.join(cppflags) # override
       
   469     files = [base_config_c, base_frozen_c] + \
       
   470             files + supp_sources +  addfiles + libs + \
       
   471             ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
       
   472 
       
   473     outfp = bkfile.open(makefile, 'w')
       
   474     try:
       
   475         makemakefile.makemakefile(outfp, somevars, files, base_target)
       
   476     finally:
       
   477         outfp.close()
       
   478 
       
   479     # Done!
       
   480 
       
   481     if odir:
       
   482         print 'Now run "make" in', odir,
       
   483         print 'to build the target:', base_target
       
   484     else:
       
   485         print 'Now run "make" to build the target:', base_target
       
   486 
       
   487 
       
   488 # Print usage message and exit
       
   489 
       
   490 def usage(msg):
       
   491     sys.stdout = sys.stderr
       
   492     print "Error:", msg
       
   493     print "Use ``%s -h'' for help" % sys.argv[0]
       
   494     sys.exit(2)
       
   495 
       
   496 
       
   497 main()