Jack Jansen | 144fa67 | 1998-06-26 14:56:00 +0000 | [diff] [blame] | 1 | """macgen_bin - Generate application from shared libraries""" |
Jack Jansen | 144fa67 | 1998-06-26 14:56:00 +0000 | [diff] [blame] | 2 | |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 3 | import os |
| 4 | import sys |
| 5 | import string |
| 6 | import types |
| 7 | import macfs |
| 8 | from MACFS import * |
Jack Jansen | fddef43 | 2001-03-20 21:55:51 +0000 | [diff] [blame] | 9 | import MacOS |
Jack Jansen | 5a6fdcd | 2001-08-25 12:15:04 +0000 | [diff] [blame] | 10 | from Carbon import Res |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 11 | import py_resource |
| 12 | import cfmfile |
| 13 | import buildtools |
| 14 | |
| 15 | |
Just van Rossum | 2e5b0f2 | 1999-11-04 10:28:59 +0000 | [diff] [blame] | 16 | def generate(input, output, module_dict=None, architecture='fat', debug=0): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 17 | # try to remove old file |
| 18 | try: |
| 19 | os.remove(output) |
| 20 | except: |
| 21 | pass |
| 22 | |
| 23 | if module_dict is None: |
| 24 | import macmodulefinder |
| 25 | print "Searching for modules..." |
| 26 | module_dict, missing = macmodulefinder.process(input, [], [], 1) |
| 27 | if missing: |
| 28 | import EasyDialogs |
| 29 | missing.sort() |
| 30 | answer = EasyDialogs.AskYesNoCancel("Some modules could not be found; continue anyway?\n(%s)" |
| 31 | % string.join(missing, ", ")) |
| 32 | if answer <> 1: |
| 33 | sys.exit(0) |
| 34 | |
| 35 | applettemplatepath = buildtools.findtemplate() |
| 36 | corepath = findpythoncore() |
| 37 | |
| 38 | dynamicmodules, dynamicfiles, extraresfiles = findfragments(module_dict, architecture) |
| 39 | |
| 40 | print 'Adding "__main__"' |
| 41 | buildtools.process(applettemplatepath, input, output, 0) |
| 42 | |
| 43 | outputref = Res.FSpOpenResFile(output, 3) |
| 44 | try: |
| 45 | Res.UseResFile(outputref) |
| 46 | |
| 47 | print "Adding Python modules" |
| 48 | addpythonmodules(module_dict) |
| 49 | |
| 50 | print "Adding PythonCore resources" |
| 51 | copyres(corepath, outputref, ['cfrg', 'Popt', 'GU\267I'], 1) |
| 52 | |
| 53 | print "Adding resources from shared libraries" |
| 54 | for ppcpath, cfm68kpath in extraresfiles: |
| 55 | if os.path.exists(ppcpath): |
| 56 | copyres(ppcpath, outputref, ['cfrg'], 1) |
| 57 | elif os.path.exists(cfm68kpath): |
| 58 | copyres(cfm68kpath, outputref, ['cfrg'], 1) |
| 59 | |
| 60 | print "Fixing sys.path prefs" |
| 61 | Res.UseResFile(outputref) |
| 62 | try: |
| 63 | res = Res.Get1Resource('STR#', 228) # from PythonCore |
| 64 | except Res.Error: pass |
| 65 | else: |
| 66 | res.RemoveResource() |
| 67 | # setting pref file name to empty string |
| 68 | res = Res.Get1NamedResource('STR ', "PythonPreferenceFileName") |
| 69 | res.data = Pstring("") |
| 70 | res.ChangedResource() |
| 71 | syspathpref = "$(APPLICATION)" |
| 72 | res = Res.Resource("\000\001" + Pstring(syspathpref)) |
| 73 | res.AddResource("STR#", 229, "sys.path preference") |
| 74 | |
| 75 | print "Creating 'PYD ' resources" |
| 76 | for modname, (ppcfrag, cfm68kfrag) in dynamicmodules.items(): |
| 77 | res = Res.Resource(Pstring(ppcfrag) + Pstring(cfm68kfrag)) |
| 78 | id = 0 |
| 79 | while id < 128: |
| 80 | id = Res.Unique1ID('PYD ') |
| 81 | res.AddResource('PYD ', id, modname) |
| 82 | finally: |
| 83 | Res.CloseResFile(outputref) |
| 84 | print "Merging code fragments" |
| 85 | cfmfile.mergecfmfiles([applettemplatepath, corepath] + dynamicfiles.keys(), |
| 86 | output, architecture) |
| 87 | |
| 88 | print "done!" |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 89 | |
| 90 | |
| 91 | def findfragments(module_dict, architecture): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 92 | dynamicmodules = {} |
| 93 | dynamicfiles = {} |
| 94 | extraresfiles = [] |
| 95 | for name, module in module_dict.items(): |
| 96 | if module.gettype() <> 'dynamic': |
| 97 | continue |
| 98 | path = resolvealiasfile(module.__file__) |
| 99 | dir, filename = os.path.split(path) |
| 100 | ## ppcfile, cfm68kfile = makefilenames(filename) |
| 101 | ppcfile = filename |
| 102 | cfm68kfile = "dummy.cfm68k.slb" |
| 103 | |
| 104 | # ppc stuff |
| 105 | ppcpath = os.path.join(dir, ppcfile) |
| 106 | if architecture <> 'm68k': |
| 107 | ppcfrag, dynamicfiles = getfragname(ppcpath, dynamicfiles) |
| 108 | else: |
| 109 | ppcfrag = "_no_fragment_" |
| 110 | |
| 111 | # 68k stuff |
| 112 | cfm68kpath = os.path.join(dir, cfm68kfile) |
| 113 | if architecture <> 'pwpc': |
| 114 | cfm68kfrag, dynamicfiles = getfragname(cfm68kpath, dynamicfiles) |
| 115 | else: |
| 116 | cfm68kfrag = "_no_fragment_" |
| 117 | |
| 118 | dynamicmodules[name] = ppcfrag, cfm68kfrag |
| 119 | if (ppcpath, cfm68kpath) not in extraresfiles: |
| 120 | extraresfiles.append((ppcpath, cfm68kpath)) |
| 121 | return dynamicmodules, dynamicfiles, extraresfiles |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 122 | |
| 123 | |
| 124 | def getfragname(path, dynamicfiles): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 125 | if not dynamicfiles.has_key(path): |
| 126 | if os.path.exists(path): |
| 127 | lib = cfmfile.CfrgResource(path) |
| 128 | fragname = lib.fragments[0].name |
| 129 | else: |
| 130 | print "shared lib not found:", path |
| 131 | fragname = "_no_fragment_" |
| 132 | dynamicfiles[path] = fragname |
| 133 | else: |
| 134 | fragname = dynamicfiles[path] |
| 135 | return fragname, dynamicfiles |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 136 | |
| 137 | |
| 138 | def addpythonmodules(module_dict): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 139 | # XXX should really use macgen_rsrc.generate(), this does the same, but skips __main__ |
| 140 | items = module_dict.items() |
| 141 | items.sort() |
| 142 | for name, module in items: |
| 143 | mtype = module.gettype() |
| 144 | if mtype not in ['module', 'package'] or name == "__main__": |
| 145 | continue |
| 146 | location = module.__file__ |
| 147 | |
| 148 | if location[-4:] == '.pyc': |
| 149 | # Attempt corresponding .py |
| 150 | location = location[:-1] |
| 151 | if location[-3:] != '.py': |
| 152 | print '*** skipping', location |
| 153 | continue |
| 154 | |
| 155 | print 'Adding module "%s"' % name |
| 156 | id, name = py_resource.frompyfile(location, name, preload=0, |
| 157 | ispackage=mtype=='package') |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 158 | |
| 159 | def Pstring(str): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 160 | if len(str) > 255: |
| 161 | raise TypeError, "Str255 must be at most 255 chars long" |
| 162 | return chr(len(str)) + str |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 163 | |
Jack Jansen | fddef43 | 2001-03-20 21:55:51 +0000 | [diff] [blame] | 164 | ##def makefilenames(name): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 165 | ## lname = string.lower(name) |
| 166 | ## pos = string.find(lname, ".ppc.") |
| 167 | ## if pos > 0: |
| 168 | ## return name, name[:pos] + '.CFM68K.' + name[pos+5:] |
| 169 | ## pos = string.find(lname, ".cfm68k.") |
| 170 | ## if pos > 0: |
| 171 | ## return name[:pos] + '.ppc.' + name[pos+8:], name |
| 172 | ## raise ValueError, "can't make ppc/cfm68k filenames" |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 173 | |
| 174 | def copyres(input, output, *args, **kwargs): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 175 | openedin = openedout = 0 |
| 176 | if type(input) == types.StringType: |
| 177 | input = Res.FSpOpenResFile(input, 1) |
| 178 | openedin = 1 |
| 179 | if type(output) == types.StringType: |
| 180 | output = Res.FSpOpenResFile(output, 3) |
| 181 | openedout = 1 |
| 182 | try: |
Neal Norwitz | d910855 | 2006-03-17 08:00:19 +0000 | [diff] [blame] | 183 | buildtools.copyres(input, output, *args, **kwargs) |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 184 | finally: |
| 185 | if openedin: |
| 186 | Res.CloseResFile(input) |
| 187 | if openedout: |
| 188 | Res.CloseResFile(output) |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 189 | |
| 190 | def findpythoncore(): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 191 | """find the PythonCore shared library, possibly asking the user if we can't find it""" |
| 192 | |
| 193 | try: |
| 194 | vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kSharedLibrariesFolderType, 0) |
| 195 | except macfs.error: |
| 196 | extpath = ":" |
| 197 | else: |
| 198 | extpath = macfs.FSSpec((vRefNum, dirID, "")).as_pathname() |
| 199 | version = string.split(sys.version)[0] |
| 200 | if MacOS.runtimemodel == 'carbon': |
| 201 | corename = "PythonCoreCarbon " + version |
| 202 | elif MacOS.runtimemodel == 'ppc': |
| 203 | corename = "PythonCore " + version |
| 204 | else: |
| 205 | raise "Unknown MacOS.runtimemodel", MacOS.runtimemodel |
| 206 | corepath = os.path.join(extpath, corename) |
| 207 | if not os.path.exists(corepath): |
| 208 | corepath = EasyDialogs.AskFileForOpen(message="Please locate PythonCore:", |
| 209 | typeList=("shlb",)) |
| 210 | if not corepath: |
| 211 | raise KeyboardInterrupt, "cancelled" |
| 212 | return resolvealiasfile(corepath) |
Jack Jansen | b5ae378 | 1998-07-31 09:43:36 +0000 | [diff] [blame] | 213 | |
| 214 | def resolvealiasfile(path): |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 215 | try: |
| 216 | fss, dummy1, dummy2 = macfs.ResolveAliasFile(path) |
| 217 | except macfs.error: |
| 218 | pass |
| 219 | else: |
| 220 | path = fss.as_pathname() |
| 221 | return path |