| """macgen_bin - Generate application from shared libraries""" |
| |
| import os |
| import sys |
| import string |
| import types |
| import macfs |
| from MACFS import * |
| import MacOS |
| from Carbon import Res |
| import py_resource |
| import cfmfile |
| import buildtools |
| |
| |
| def generate(input, output, module_dict=None, architecture='fat', debug=0): |
| # try to remove old file |
| try: |
| os.remove(output) |
| except: |
| pass |
| |
| if module_dict is None: |
| import macmodulefinder |
| print "Searching for modules..." |
| module_dict, missing = macmodulefinder.process(input, [], [], 1) |
| if missing: |
| import EasyDialogs |
| missing.sort() |
| answer = EasyDialogs.AskYesNoCancel("Some modules could not be found; continue anyway?\n(%s)" |
| % string.join(missing, ", ")) |
| if answer <> 1: |
| sys.exit(0) |
| |
| applettemplatepath = buildtools.findtemplate() |
| corepath = findpythoncore() |
| |
| dynamicmodules, dynamicfiles, extraresfiles = findfragments(module_dict, architecture) |
| |
| print 'Adding "__main__"' |
| buildtools.process(applettemplatepath, input, output, 0) |
| |
| outputref = Res.FSpOpenResFile(output, 3) |
| try: |
| Res.UseResFile(outputref) |
| |
| print "Adding Python modules" |
| addpythonmodules(module_dict) |
| |
| print "Adding PythonCore resources" |
| copyres(corepath, outputref, ['cfrg', 'Popt', 'GU\267I'], 1) |
| |
| print "Adding resources from shared libraries" |
| for ppcpath, cfm68kpath in extraresfiles: |
| if os.path.exists(ppcpath): |
| copyres(ppcpath, outputref, ['cfrg'], 1) |
| elif os.path.exists(cfm68kpath): |
| copyres(cfm68kpath, outputref, ['cfrg'], 1) |
| |
| print "Fixing sys.path prefs" |
| Res.UseResFile(outputref) |
| try: |
| res = Res.Get1Resource('STR#', 228) # from PythonCore |
| except Res.Error: pass |
| else: |
| res.RemoveResource() |
| # setting pref file name to empty string |
| res = Res.Get1NamedResource('STR ', "PythonPreferenceFileName") |
| res.data = Pstring("") |
| res.ChangedResource() |
| syspathpref = "$(APPLICATION)" |
| res = Res.Resource("\000\001" + Pstring(syspathpref)) |
| res.AddResource("STR#", 229, "sys.path preference") |
| |
| print "Creating 'PYD ' resources" |
| for modname, (ppcfrag, cfm68kfrag) in dynamicmodules.items(): |
| res = Res.Resource(Pstring(ppcfrag) + Pstring(cfm68kfrag)) |
| id = 0 |
| while id < 128: |
| id = Res.Unique1ID('PYD ') |
| res.AddResource('PYD ', id, modname) |
| finally: |
| Res.CloseResFile(outputref) |
| print "Merging code fragments" |
| cfmfile.mergecfmfiles([applettemplatepath, corepath] + dynamicfiles.keys(), |
| output, architecture) |
| |
| print "done!" |
| |
| |
| def findfragments(module_dict, architecture): |
| dynamicmodules = {} |
| dynamicfiles = {} |
| extraresfiles = [] |
| for name, module in module_dict.items(): |
| if module.gettype() <> 'dynamic': |
| continue |
| path = resolvealiasfile(module.__file__) |
| dir, filename = os.path.split(path) |
| ## ppcfile, cfm68kfile = makefilenames(filename) |
| ppcfile = filename |
| cfm68kfile = "dummy.cfm68k.slb" |
| |
| # ppc stuff |
| ppcpath = os.path.join(dir, ppcfile) |
| if architecture <> 'm68k': |
| ppcfrag, dynamicfiles = getfragname(ppcpath, dynamicfiles) |
| else: |
| ppcfrag = "_no_fragment_" |
| |
| # 68k stuff |
| cfm68kpath = os.path.join(dir, cfm68kfile) |
| if architecture <> 'pwpc': |
| cfm68kfrag, dynamicfiles = getfragname(cfm68kpath, dynamicfiles) |
| else: |
| cfm68kfrag = "_no_fragment_" |
| |
| dynamicmodules[name] = ppcfrag, cfm68kfrag |
| if (ppcpath, cfm68kpath) not in extraresfiles: |
| extraresfiles.append((ppcpath, cfm68kpath)) |
| return dynamicmodules, dynamicfiles, extraresfiles |
| |
| |
| def getfragname(path, dynamicfiles): |
| if not dynamicfiles.has_key(path): |
| if os.path.exists(path): |
| lib = cfmfile.CfrgResource(path) |
| fragname = lib.fragments[0].name |
| else: |
| print "shared lib not found:", path |
| fragname = "_no_fragment_" |
| dynamicfiles[path] = fragname |
| else: |
| fragname = dynamicfiles[path] |
| return fragname, dynamicfiles |
| |
| |
| def addpythonmodules(module_dict): |
| # XXX should really use macgen_rsrc.generate(), this does the same, but skips __main__ |
| items = module_dict.items() |
| items.sort() |
| for name, module in items: |
| mtype = module.gettype() |
| if mtype not in ['module', 'package'] or name == "__main__": |
| continue |
| location = module.__file__ |
| |
| if location[-4:] == '.pyc': |
| # Attempt corresponding .py |
| location = location[:-1] |
| if location[-3:] != '.py': |
| print '*** skipping', location |
| continue |
| |
| print 'Adding module "%s"' % name |
| id, name = py_resource.frompyfile(location, name, preload=0, |
| ispackage=mtype=='package') |
| |
| def Pstring(str): |
| if len(str) > 255: |
| raise TypeError, "Str255 must be at most 255 chars long" |
| return chr(len(str)) + str |
| |
| ##def makefilenames(name): |
| ## lname = string.lower(name) |
| ## pos = string.find(lname, ".ppc.") |
| ## if pos > 0: |
| ## return name, name[:pos] + '.CFM68K.' + name[pos+5:] |
| ## pos = string.find(lname, ".cfm68k.") |
| ## if pos > 0: |
| ## return name[:pos] + '.ppc.' + name[pos+8:], name |
| ## raise ValueError, "can't make ppc/cfm68k filenames" |
| |
| def copyres(input, output, *args, **kwargs): |
| openedin = openedout = 0 |
| if type(input) == types.StringType: |
| input = Res.FSpOpenResFile(input, 1) |
| openedin = 1 |
| if type(output) == types.StringType: |
| output = Res.FSpOpenResFile(output, 3) |
| openedout = 1 |
| try: |
| buildtools.copyres(input, output, *args, **kwargs) |
| finally: |
| if openedin: |
| Res.CloseResFile(input) |
| if openedout: |
| Res.CloseResFile(output) |
| |
| def findpythoncore(): |
| """find the PythonCore shared library, possibly asking the user if we can't find it""" |
| |
| try: |
| vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kSharedLibrariesFolderType, 0) |
| except macfs.error: |
| extpath = ":" |
| else: |
| extpath = macfs.FSSpec((vRefNum, dirID, "")).as_pathname() |
| version = string.split(sys.version)[0] |
| if MacOS.runtimemodel == 'carbon': |
| corename = "PythonCoreCarbon " + version |
| elif MacOS.runtimemodel == 'ppc': |
| corename = "PythonCore " + version |
| else: |
| raise "Unknown MacOS.runtimemodel", MacOS.runtimemodel |
| corepath = os.path.join(extpath, corename) |
| if not os.path.exists(corepath): |
| corepath = EasyDialogs.AskFileForOpen(message="Please locate PythonCore:", |
| typeList=("shlb",)) |
| if not corepath: |
| raise KeyboardInterrupt, "cancelled" |
| return resolvealiasfile(corepath) |
| |
| def resolvealiasfile(path): |
| try: |
| fss, dummy1, dummy2 = macfs.ResolveAliasFile(path) |
| except macfs.error: |
| pass |
| else: |
| path = fss.as_pathname() |
| return path |