+++ /dev/null
-"""Extension management for Windows.\r
-\r
-Under Windows it is unlikely the .obj files are of use, as special compiler options\r
-are needed (primarily to toggle the behavior of "public" symbols.\r
-\r
-I dont consider it worth parsing the MSVC makefiles for compiler options. Even if\r
-we get it just right, a specific freeze application may have specific compiler\r
-options anyway (eg, to enable or disable specific functionality)\r
-\r
-So my basic strategy is:\r
-\r
-* Have some Windows INI files which "describe" one or more extension modules.\r
- (Freeze comes with a default one for all known modules - but you can specify\r
- your own).\r
-* This description can include:\r
- - The MSVC .dsp file for the extension. The .c source file names\r
- are extraced from there.\r
- - Specific compiler/linker options\r
- - Flag to indicate if Unicode compilation is expected.\r
-\r
-At the moment the name and location of this INI file is hardcoded,\r
-but an obvious enhancement would be to provide command line options.\r
-"""\r
-\r
-import os, sys\r
-try:\r
- import win32api\r
-except ImportError:\r
- win32api = None # User has already been warned\r
-\r
-class CExtension:\r
- """An abstraction of an extension implemented in C/C++\r
- """\r
- def __init__(self, name, sourceFiles):\r
- self.name = name\r
- # A list of strings defining additional compiler options.\r
- self.sourceFiles = sourceFiles\r
- # A list of special compiler options to be applied to\r
- # all source modules in this extension.\r
- self.compilerOptions = []\r
- # A list of .lib files the final .EXE will need.\r
- self.linkerLibs = []\r
-\r
- def GetSourceFiles(self):\r
- return self.sourceFiles\r
-\r
- def AddCompilerOption(self, option):\r
- self.compilerOptions.append(option)\r
- def GetCompilerOptions(self):\r
- return self.compilerOptions\r
-\r
- def AddLinkerLib(self, lib):\r
- self.linkerLibs.append(lib)\r
- def GetLinkerLibs(self):\r
- return self.linkerLibs\r
-\r
-def checkextensions(unknown, extra_inis, prefix):\r
- # Create a table of frozen extensions\r
-\r
- defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini")\r
- if not os.path.isfile(defaultMapName):\r
- sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found\n" % defaultMapName)\r
- else:\r
- # must go on end, so other inis can override.\r
- extra_inis.append(defaultMapName)\r
-\r
- ret = []\r
- for mod in unknown:\r
- for ini in extra_inis:\r
-# print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...",\r
- defn = get_extension_defn( mod, ini, prefix )\r
- if defn is not None:\r
-# print "Yay - found it!"\r
- ret.append( defn )\r
- break\r
-# print "Nope!"\r
- else: # For not broken!\r
- sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod))\r
-\r
- return ret\r
-\r
-def get_extension_defn(moduleName, mapFileName, prefix):\r
- if win32api is None: return None\r
- os.environ['PYTHONPREFIX'] = prefix\r
- dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName)\r
- if dsp=="":\r
- return None\r
-\r
- # We allow environment variables in the file name\r
- dsp = win32api.ExpandEnvironmentStrings(dsp)\r
- # If the path to the .DSP file is not absolute, assume it is relative\r
- # to the description file.\r
- if not os.path.isabs(dsp):\r
- dsp = os.path.join( os.path.split(mapFileName)[0], dsp)\r
- # Parse it to extract the source files.\r
- sourceFiles = parse_dsp(dsp)\r
- if sourceFiles is None:\r
- return None\r
-\r
- module = CExtension(moduleName, sourceFiles)\r
- # Put the path to the DSP into the environment so entries can reference it.\r
- os.environ['dsp_path'] = os.path.split(dsp)[0]\r
- os.environ['ini_path'] = os.path.split(mapFileName)[0]\r
-\r
- cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName)\r
- if cl_options:\r
- module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))\r
-\r
- exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)\r
- exclude = exclude.split()\r
-\r
- if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):\r
- module.AddCompilerOption('/D UNICODE /D _UNICODE')\r
-\r
- libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split()\r
- for lib in libs:\r
- module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))\r
-\r
- for exc in exclude:\r
- if exc in module.sourceFiles:\r
- modules.sourceFiles.remove(exc)\r
-\r
- return module\r
-\r
-# Given an MSVC DSP file, locate C source files it uses\r
-# returns a list of source files.\r
-def parse_dsp(dsp):\r
-# print "Processing", dsp\r
- # For now, only support\r
- ret = []\r
- dsp_path, dsp_name = os.path.split(dsp)\r
- try:\r
- lines = open(dsp, "r").readlines()\r
- except IOError, msg:\r
- sys.stderr.write("%s: %s\n" % (dsp, msg))\r
- return None\r
- for line in lines:\r
- fields = line.strip().split("=", 2)\r
- if fields[0]=="SOURCE":\r
- if os.path.splitext(fields[1])[1].lower() in ['.cpp', '.c']:\r
- ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )\r
- return ret\r
-\r
-def write_extension_table(fname, modules):\r
- fp = open(fname, "w")\r
- try:\r
- fp.write (ext_src_header)\r
- # Write fn protos\r
- for module in modules:\r
- # bit of a hack for .pyd's as part of packages.\r
- name = module.name.split('.')[-1]\r
- fp.write('extern void init%s(void);\n' % (name) )\r
- # Write the table\r
- fp.write (ext_tab_header)\r
- for module in modules:\r
- name = module.name.split('.')[-1]\r
- fp.write('\t{"%s", init%s},\n' % (name, name) )\r
-\r
- fp.write (ext_tab_footer)\r
- fp.write(ext_src_footer)\r
- finally:\r
- fp.close()\r
-\r
-\r
-ext_src_header = """\\r
-#include "Python.h"\r
-"""\r
-\r
-ext_tab_header = """\\r
-\r
-static struct _inittab extensions[] = {\r
-"""\r
-\r
-ext_tab_footer = """\\r
- /* Sentinel */\r
- {0, 0}\r
-};\r
-"""\r
-\r
-ext_src_footer = """\\r
-extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);\r
-\r
-int PyInitFrozenExtensions()\r
-{\r
- return PyImport_ExtendInittab(extensions);\r
-}\r
-\r
-"""\r