17db96d56Sopenharmony_ci"""Extension management for Windows. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciUnder Windows it is unlikely the .obj files are of use, as special compiler options 47db96d56Sopenharmony_ciare needed (primarily to toggle the behavior of "public" symbols. 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciI don't consider it worth parsing the MSVC makefiles for compiler options. Even if 77db96d56Sopenharmony_ciwe get it just right, a specific freeze application may have specific compiler 87db96d56Sopenharmony_cioptions anyway (eg, to enable or disable specific functionality) 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ciSo my basic strategy is: 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ci* Have some Windows INI files which "describe" one or more extension modules. 137db96d56Sopenharmony_ci (Freeze comes with a default one for all known modules - but you can specify 147db96d56Sopenharmony_ci your own). 157db96d56Sopenharmony_ci* This description can include: 167db96d56Sopenharmony_ci - The MSVC .dsp file for the extension. The .c source file names 177db96d56Sopenharmony_ci are extracted from there. 187db96d56Sopenharmony_ci - Specific compiler/linker options 197db96d56Sopenharmony_ci - Flag to indicate if Unicode compilation is expected. 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ciAt the moment the name and location of this INI file is hardcoded, 227db96d56Sopenharmony_cibut an obvious enhancement would be to provide command line options. 237db96d56Sopenharmony_ci""" 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ciimport os, sys 267db96d56Sopenharmony_citry: 277db96d56Sopenharmony_ci import win32api 287db96d56Sopenharmony_ciexcept ImportError: 297db96d56Sopenharmony_ci win32api = None # User has already been warned 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ciclass CExtension: 327db96d56Sopenharmony_ci """An abstraction of an extension implemented in C/C++ 337db96d56Sopenharmony_ci """ 347db96d56Sopenharmony_ci def __init__(self, name, sourceFiles): 357db96d56Sopenharmony_ci self.name = name 367db96d56Sopenharmony_ci # A list of strings defining additional compiler options. 377db96d56Sopenharmony_ci self.sourceFiles = sourceFiles 387db96d56Sopenharmony_ci # A list of special compiler options to be applied to 397db96d56Sopenharmony_ci # all source modules in this extension. 407db96d56Sopenharmony_ci self.compilerOptions = [] 417db96d56Sopenharmony_ci # A list of .lib files the final .EXE will need. 427db96d56Sopenharmony_ci self.linkerLibs = [] 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci def GetSourceFiles(self): 457db96d56Sopenharmony_ci return self.sourceFiles 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci def AddCompilerOption(self, option): 487db96d56Sopenharmony_ci self.compilerOptions.append(option) 497db96d56Sopenharmony_ci def GetCompilerOptions(self): 507db96d56Sopenharmony_ci return self.compilerOptions 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci def AddLinkerLib(self, lib): 537db96d56Sopenharmony_ci self.linkerLibs.append(lib) 547db96d56Sopenharmony_ci def GetLinkerLibs(self): 557db96d56Sopenharmony_ci return self.linkerLibs 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_cidef checkextensions(unknown, extra_inis, prefix): 587db96d56Sopenharmony_ci # Create a table of frozen extensions 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini") 617db96d56Sopenharmony_ci if not os.path.isfile(defaultMapName): 627db96d56Sopenharmony_ci sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found\n" % defaultMapName) 637db96d56Sopenharmony_ci else: 647db96d56Sopenharmony_ci # must go on end, so other inis can override. 657db96d56Sopenharmony_ci extra_inis.append(defaultMapName) 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci ret = [] 687db96d56Sopenharmony_ci for mod in unknown: 697db96d56Sopenharmony_ci for ini in extra_inis: 707db96d56Sopenharmony_ci# print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...", 717db96d56Sopenharmony_ci defn = get_extension_defn( mod, ini, prefix ) 727db96d56Sopenharmony_ci if defn is not None: 737db96d56Sopenharmony_ci# print "Yay - found it!" 747db96d56Sopenharmony_ci ret.append( defn ) 757db96d56Sopenharmony_ci break 767db96d56Sopenharmony_ci# print "Nope!" 777db96d56Sopenharmony_ci else: # For not broken! 787db96d56Sopenharmony_ci sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod)) 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci return ret 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_cidef get_extension_defn(moduleName, mapFileName, prefix): 837db96d56Sopenharmony_ci if win32api is None: return None 847db96d56Sopenharmony_ci os.environ['PYTHONPREFIX'] = prefix 857db96d56Sopenharmony_ci dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName) 867db96d56Sopenharmony_ci if dsp=="": 877db96d56Sopenharmony_ci return None 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci # We allow environment variables in the file name 907db96d56Sopenharmony_ci dsp = win32api.ExpandEnvironmentStrings(dsp) 917db96d56Sopenharmony_ci # If the path to the .DSP file is not absolute, assume it is relative 927db96d56Sopenharmony_ci # to the description file. 937db96d56Sopenharmony_ci if not os.path.isabs(dsp): 947db96d56Sopenharmony_ci dsp = os.path.join( os.path.split(mapFileName)[0], dsp) 957db96d56Sopenharmony_ci # Parse it to extract the source files. 967db96d56Sopenharmony_ci sourceFiles = parse_dsp(dsp) 977db96d56Sopenharmony_ci if sourceFiles is None: 987db96d56Sopenharmony_ci return None 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci module = CExtension(moduleName, sourceFiles) 1017db96d56Sopenharmony_ci # Put the path to the DSP into the environment so entries can reference it. 1027db96d56Sopenharmony_ci os.environ['dsp_path'] = os.path.split(dsp)[0] 1037db96d56Sopenharmony_ci os.environ['ini_path'] = os.path.split(mapFileName)[0] 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName) 1067db96d56Sopenharmony_ci if cl_options: 1077db96d56Sopenharmony_ci module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options)) 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName) 1107db96d56Sopenharmony_ci exclude = exclude.split() 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName): 1137db96d56Sopenharmony_ci module.AddCompilerOption('/D UNICODE /D _UNICODE') 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split() 1167db96d56Sopenharmony_ci for lib in libs: 1177db96d56Sopenharmony_ci module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib)) 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci for exc in exclude: 1207db96d56Sopenharmony_ci if exc in module.sourceFiles: 1217db96d56Sopenharmony_ci module.sourceFiles.remove(exc) 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci return module 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci# Given an MSVC DSP file, locate C source files it uses 1267db96d56Sopenharmony_ci# returns a list of source files. 1277db96d56Sopenharmony_cidef parse_dsp(dsp): 1287db96d56Sopenharmony_ci# print "Processing", dsp 1297db96d56Sopenharmony_ci # For now, only support 1307db96d56Sopenharmony_ci ret = [] 1317db96d56Sopenharmony_ci dsp_path, dsp_name = os.path.split(dsp) 1327db96d56Sopenharmony_ci try: 1337db96d56Sopenharmony_ci with open(dsp, "r") as fp: 1347db96d56Sopenharmony_ci lines = fp.readlines() 1357db96d56Sopenharmony_ci except IOError as msg: 1367db96d56Sopenharmony_ci sys.stderr.write("%s: %s\n" % (dsp, msg)) 1377db96d56Sopenharmony_ci return None 1387db96d56Sopenharmony_ci for line in lines: 1397db96d56Sopenharmony_ci fields = line.strip().split("=", 2) 1407db96d56Sopenharmony_ci if fields[0]=="SOURCE": 1417db96d56Sopenharmony_ci if os.path.splitext(fields[1])[1].lower() in ['.cpp', '.c']: 1427db96d56Sopenharmony_ci ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) ) 1437db96d56Sopenharmony_ci return ret 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_cidef write_extension_table(fname, modules): 1467db96d56Sopenharmony_ci fp = open(fname, "w") 1477db96d56Sopenharmony_ci try: 1487db96d56Sopenharmony_ci fp.write (ext_src_header) 1497db96d56Sopenharmony_ci # Write fn protos 1507db96d56Sopenharmony_ci for module in modules: 1517db96d56Sopenharmony_ci # bit of a hack for .pyd's as part of packages. 1527db96d56Sopenharmony_ci name = module.name.split('.')[-1] 1537db96d56Sopenharmony_ci fp.write('extern void init%s(void);\n' % (name) ) 1547db96d56Sopenharmony_ci # Write the table 1557db96d56Sopenharmony_ci fp.write (ext_tab_header) 1567db96d56Sopenharmony_ci for module in modules: 1577db96d56Sopenharmony_ci name = module.name.split('.')[-1] 1587db96d56Sopenharmony_ci fp.write('\t{"%s", init%s},\n' % (name, name) ) 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci fp.write (ext_tab_footer) 1617db96d56Sopenharmony_ci fp.write(ext_src_footer) 1627db96d56Sopenharmony_ci finally: 1637db96d56Sopenharmony_ci fp.close() 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ciext_src_header = """\ 1677db96d56Sopenharmony_ci#include "Python.h" 1687db96d56Sopenharmony_ci""" 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ciext_tab_header = """\ 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_cistatic struct _inittab extensions[] = { 1737db96d56Sopenharmony_ci""" 1747db96d56Sopenharmony_ci 1757db96d56Sopenharmony_ciext_tab_footer = """\ 1767db96d56Sopenharmony_ci /* Sentinel */ 1777db96d56Sopenharmony_ci {0, 0} 1787db96d56Sopenharmony_ci}; 1797db96d56Sopenharmony_ci""" 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ciext_src_footer = """\ 1827db96d56Sopenharmony_ciextern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab); 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ciint PyInitFrozenExtensions() 1857db96d56Sopenharmony_ci{ 1867db96d56Sopenharmony_ci return PyImport_ExtendInittab(extensions); 1877db96d56Sopenharmony_ci} 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci""" 190