blob: f52e37e4f76a8c751367a5b0d86327bd2b46634d [file] [log] [blame]
Jack Jansen144fa671998-06-26 14:56:00 +00001"""macgen_bin - Generate application from shared libraries"""
Jack Jansen144fa671998-06-26 14:56:00 +00002
Jack Jansenb5ae3781998-07-31 09:43:36 +00003import os
4import sys
5import string
6import types
7import macfs
8from MACFS import *
Jack Jansenfddef432001-03-20 21:55:51 +00009import MacOS
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000010from Carbon import Res
Jack Jansenb5ae3781998-07-31 09:43:36 +000011import py_resource
12import cfmfile
13import buildtools
14
15
Just van Rossum2e5b0f21999-11-04 10:28:59 +000016def generate(input, output, module_dict=None, architecture='fat', debug=0):
Tim Peters182b5ac2004-07-18 06:16:08 +000017 # 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 Jansenb5ae3781998-07-31 09:43:36 +000089
90
91def findfragments(module_dict, architecture):
Tim Peters182b5ac2004-07-18 06:16:08 +000092 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 Jansenb5ae3781998-07-31 09:43:36 +0000122
123
124def getfragname(path, dynamicfiles):
Tim Peters182b5ac2004-07-18 06:16:08 +0000125 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 Jansenb5ae3781998-07-31 09:43:36 +0000136
137
138def addpythonmodules(module_dict):
Tim Peters182b5ac2004-07-18 06:16:08 +0000139 # 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 Jansenb5ae3781998-07-31 09:43:36 +0000158
159def Pstring(str):
Tim Peters182b5ac2004-07-18 06:16:08 +0000160 if len(str) > 255:
161 raise TypeError, "Str255 must be at most 255 chars long"
162 return chr(len(str)) + str
Jack Jansenb5ae3781998-07-31 09:43:36 +0000163
Jack Jansenfddef432001-03-20 21:55:51 +0000164##def makefilenames(name):
Tim Peters182b5ac2004-07-18 06:16:08 +0000165## 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 Jansenb5ae3781998-07-31 09:43:36 +0000173
174def copyres(input, output, *args, **kwargs):
Tim Peters182b5ac2004-07-18 06:16:08 +0000175 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 Norwitzd9108552006-03-17 08:00:19 +0000183 buildtools.copyres(input, output, *args, **kwargs)
Tim Peters182b5ac2004-07-18 06:16:08 +0000184 finally:
185 if openedin:
186 Res.CloseResFile(input)
187 if openedout:
188 Res.CloseResFile(output)
Jack Jansenb5ae3781998-07-31 09:43:36 +0000189
190def findpythoncore():
Tim Peters182b5ac2004-07-18 06:16:08 +0000191 """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 Jansenb5ae3781998-07-31 09:43:36 +0000213
214def resolvealiasfile(path):
Tim Peters182b5ac2004-07-18 06:16:08 +0000215 try:
216 fss, dummy1, dummy2 = macfs.ResolveAliasFile(path)
217 except macfs.error:
218 pass
219 else:
220 path = fss.as_pathname()
221 return path