symbian-qemu-0.9.1-12/python-2.6.1/Tools/freeze/checkextensions_win32.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Extension management for Windows.
       
     2 
       
     3 Under Windows it is unlikely the .obj files are of use, as special compiler options
       
     4 are needed (primarily to toggle the behavior of "public" symbols.
       
     5 
       
     6 I dont consider it worth parsing the MSVC makefiles for compiler options.  Even if
       
     7 we get it just right, a specific freeze application may have specific compiler
       
     8 options anyway (eg, to enable or disable specific functionality)
       
     9 
       
    10 So my basic stragtegy is:
       
    11 
       
    12 * Have some Windows INI files which "describe" one or more extension modules.
       
    13   (Freeze comes with a default one for all known modules - but you can specify
       
    14   your own).
       
    15 * This description can include:
       
    16   - The MSVC .dsp file for the extension.  The .c source file names
       
    17     are extraced from there.
       
    18   - Specific compiler/linker options
       
    19   - Flag to indicate if Unicode compilation is expected.
       
    20 
       
    21 At the moment the name and location of this INI file is hardcoded,
       
    22 but an obvious enhancement would be to provide command line options.
       
    23 """
       
    24 
       
    25 import os, sys
       
    26 try:
       
    27     import win32api
       
    28 except ImportError:
       
    29     win32api = None # User has already been warned
       
    30 
       
    31 class CExtension:
       
    32     """An abstraction of an extension implemented in C/C++
       
    33     """
       
    34     def __init__(self, name, sourceFiles):
       
    35         self.name = name
       
    36         # A list of strings defining additional compiler options.
       
    37         self.sourceFiles = sourceFiles
       
    38         # A list of special compiler options to be applied to
       
    39         # all source modules in this extension.
       
    40         self.compilerOptions = []
       
    41         # A list of .lib files the final .EXE will need.
       
    42         self.linkerLibs = []
       
    43 
       
    44     def GetSourceFiles(self):
       
    45         return self.sourceFiles
       
    46 
       
    47     def AddCompilerOption(self, option):
       
    48         self.compilerOptions.append(option)
       
    49     def GetCompilerOptions(self):
       
    50         return self.compilerOptions
       
    51 
       
    52     def AddLinkerLib(self, lib):
       
    53         self.linkerLibs.append(lib)
       
    54     def GetLinkerLibs(self):
       
    55         return self.linkerLibs
       
    56 
       
    57 def checkextensions(unknown, extra_inis, prefix):
       
    58     # Create a table of frozen extensions
       
    59 
       
    60     defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini")
       
    61     if not os.path.isfile(defaultMapName):
       
    62         sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found\n" % defaultMapName)
       
    63     else:
       
    64         # must go on end, so other inis can override.
       
    65         extra_inis.append(defaultMapName)
       
    66 
       
    67     ret = []
       
    68     for mod in unknown:
       
    69         for ini in extra_inis:
       
    70 #                       print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...",
       
    71             defn = get_extension_defn( mod, ini, prefix )
       
    72             if defn is not None:
       
    73 #                               print "Yay - found it!"
       
    74                 ret.append( defn )
       
    75                 break
       
    76 #                       print "Nope!"
       
    77         else: # For not broken!
       
    78             sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod))
       
    79 
       
    80     return ret
       
    81 
       
    82 def get_extension_defn(moduleName, mapFileName, prefix):
       
    83     if win32api is None: return None
       
    84     os.environ['PYTHONPREFIX'] = prefix
       
    85     dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName)
       
    86     if dsp=="":
       
    87         return None
       
    88 
       
    89     # We allow environment variables in the file name
       
    90     dsp = win32api.ExpandEnvironmentStrings(dsp)
       
    91     # If the path to the .DSP file is not absolute, assume it is relative
       
    92     # to the description file.
       
    93     if not os.path.isabs(dsp):
       
    94         dsp = os.path.join( os.path.split(mapFileName)[0], dsp)
       
    95     # Parse it to extract the source files.
       
    96     sourceFiles = parse_dsp(dsp)
       
    97     if sourceFiles is None:
       
    98         return None
       
    99 
       
   100     module = CExtension(moduleName, sourceFiles)
       
   101     # Put the path to the DSP into the environment so entries can reference it.
       
   102     os.environ['dsp_path'] = os.path.split(dsp)[0]
       
   103     os.environ['ini_path'] = os.path.split(mapFileName)[0]
       
   104 
       
   105     cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName)
       
   106     if cl_options:
       
   107         module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))
       
   108 
       
   109     exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)
       
   110     exclude = exclude.split()
       
   111 
       
   112     if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
       
   113         module.AddCompilerOption('/D UNICODE /D _UNICODE')
       
   114 
       
   115     libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split()
       
   116     for lib in libs:
       
   117         module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))
       
   118 
       
   119     for exc in exclude:
       
   120         if exc in module.sourceFiles:
       
   121             modules.sourceFiles.remove(exc)
       
   122 
       
   123     return module
       
   124 
       
   125 # Given an MSVC DSP file, locate C source files it uses
       
   126 # returns a list of source files.
       
   127 def parse_dsp(dsp):
       
   128 #       print "Processing", dsp
       
   129     # For now, only support
       
   130     ret = []
       
   131     dsp_path, dsp_name = os.path.split(dsp)
       
   132     try:
       
   133         lines = open(dsp, "r").readlines()
       
   134     except IOError, msg:
       
   135         sys.stderr.write("%s: %s\n" % (dsp, msg))
       
   136         return None
       
   137     for line in lines:
       
   138         fields = line.strip().split("=", 2)
       
   139         if fields[0]=="SOURCE":
       
   140             if os.path.splitext(fields[1])[1].lower() in ['.cpp', '.c']:
       
   141                 ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )
       
   142     return ret
       
   143 
       
   144 def write_extension_table(fname, modules):
       
   145     fp = open(fname, "w")
       
   146     try:
       
   147         fp.write (ext_src_header)
       
   148         # Write fn protos
       
   149         for module in modules:
       
   150             # bit of a hack for .pyd's as part of packages.
       
   151             name = module.name.split('.')[-1]
       
   152             fp.write('extern void init%s(void);\n' % (name) )
       
   153         # Write the table
       
   154         fp.write (ext_tab_header)
       
   155         for module in modules:
       
   156             name = module.name.split('.')[-1]
       
   157             fp.write('\t{"%s", init%s},\n' % (name, name) )
       
   158 
       
   159         fp.write (ext_tab_footer)
       
   160         fp.write(ext_src_footer)
       
   161     finally:
       
   162         fp.close()
       
   163 
       
   164 
       
   165 ext_src_header = """\
       
   166 #include "Python.h"
       
   167 """
       
   168 
       
   169 ext_tab_header = """\
       
   170 
       
   171 static struct _inittab extensions[] = {
       
   172 """
       
   173 
       
   174 ext_tab_footer = """\
       
   175         /* Sentinel */
       
   176         {0, 0}
       
   177 };
       
   178 """
       
   179 
       
   180 ext_src_footer = """\
       
   181 extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
       
   182 
       
   183 int PyInitFrozenExtensions()
       
   184 {
       
   185         return PyImport_ExtendInittab(extensions);
       
   186 }
       
   187 
       
   188 """