py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Mac / Tools / macfreeze / macgen_bin.py
blob42aaf40d33fc08f2a42085864e68af2618b74d3d
1 """macgen_bin - Generate application from shared libraries"""
3 import os
4 import sys
5 import string
6 import types
7 import macfs
8 from MACFS import *
9 import MacOS
10 import Res
11 import py_resource
12 import cfmfile
13 import buildtools
16 def generate(input, output, module_dict=None, architecture='fat', debug=0):
17 # try to remove old file
18 try:
19 os.remove(output)
20 except:
21 pass
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)
35 applettemplatepath = buildtools.findtemplate()
36 corepath = findpythoncore()
38 dynamicmodules, dynamicfiles, extraresfiles = findfragments(module_dict, architecture)
40 print 'Adding "__main__"'
41 buildtools.process(applettemplatepath, input, output, 0)
43 outputref = Res.FSpOpenResFile(output, 3)
44 try:
45 Res.UseResFile(outputref)
47 print "Adding Python modules"
48 addpythonmodules(module_dict)
50 print "Adding PythonCore resources"
51 copyres(corepath, outputref, ['cfrg', 'Popt', 'GU\267I'], 1)
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)
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")
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)
88 print "done!"
91 def findfragments(module_dict, architecture):
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"
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_"
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_"
118 dynamicmodules[name] = ppcfrag, cfm68kfrag
119 if (ppcpath, cfm68kpath) not in extraresfiles:
120 extraresfiles.append((ppcpath, cfm68kpath))
121 return dynamicmodules, dynamicfiles, extraresfiles
124 def getfragname(path, dynamicfiles):
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
138 def addpythonmodules(module_dict):
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__
148 if location[-4:] == '.pyc':
149 # Attempt corresponding .py
150 location = location[:-1]
151 if location[-3:] != '.py':
152 print '*** skipping', location
153 continue
155 print 'Adding module "%s"' % name
156 id, name = py_resource.frompyfile(location, name, preload=0,
157 ispackage=mtype=='package')
159 def Pstring(str):
160 if len(str) > 255:
161 raise TypeError, "Str255 must be at most 255 chars long"
162 return chr(len(str)) + str
164 ##def makefilenames(name):
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"
174 def copyres(input, output, *args, **kwargs):
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:
183 apply(buildtools.copyres, (input, output) + args, kwargs)
184 finally:
185 if openedin:
186 Res.CloseResFile(input)
187 if openedout:
188 Res.CloseResFile(output)
190 def findpythoncore():
191 """find the PythonCore shared library, possibly asking the user if we can't find it"""
193 vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kSharedLibrariesFolderType, 0)
194 extpath = macfs.FSSpec((vRefNum, dirID, "")).as_pathname()
195 version = string.split(sys.version)[0]
196 if MacOS.runtimemodel == 'carbon':
197 corename = "PythonCoreCarbon " + version
198 elif MacOS.runtimemodel == 'ppc':
199 corename = "PythonCore " + version
200 else:
201 raise "Unknown MacOS.runtimemodel", MacOS.runtimemodel
202 corepath = os.path.join(extpath, corename)
203 if not os.path.exists(corepath):
204 fss, ok = macfs.PromptGetFile("Please locate PythonCore:", "shlb")
205 if not ok:
206 raise KeyboardInterrupt, "cancelled"
207 corepath = fss.as_pathname()
208 return resolvealiasfile(corepath)
210 def resolvealiasfile(path):
211 try:
212 fss, dummy1, dummy2 = macfs.ResolveAliasFile(path)
213 except macfs.error:
214 pass
215 else:
216 path = fss.as_pathname()
217 return path