The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Mac / Tools / macfreeze / macgen_bin.py
blob04260ed354672f7f4b66ae36db7f497b164b7c4e
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 Res
10 import py_resource
11 import cfmfile
12 import buildtools
15 def generate(input, output, module_dict=None, architecture='fat', debug=0):
16 # try to remove old file
17 try:
18 os.remove(output)
19 except:
20 pass
22 if module_dict is None:
23 import macmodulefinder
24 print "Searching for modules..."
25 module_dict, missing = macmodulefinder.process(input, [], [], 1)
26 if missing:
27 import EasyDialogs
28 missing.sort()
29 answer = EasyDialogs.AskYesNoCancel("Some modules could not be found; continue anyway?\n(%s)"
30 % string.join(missing, ", "))
31 if answer <> 1:
32 sys.exit(0)
34 applettemplatepath = buildtools.findtemplate()
35 corepath = findpythoncore()
37 dynamicmodules, dynamicfiles, extraresfiles = findfragments(module_dict, architecture)
39 print 'Adding "__main__"'
40 buildtools.process(applettemplatepath, input, output, 0)
42 outputref = Res.OpenResFile(output)
43 try:
44 Res.UseResFile(outputref)
46 print "Adding Python modules"
47 addpythonmodules(module_dict)
49 print "Adding PythonCore resources"
50 copyres(corepath, outputref, ['cfrg', 'Popt', 'GU\267I'], 1)
52 print "Adding resources from shared libraries"
53 for ppcpath, cfm68kpath in extraresfiles:
54 if os.path.exists(ppcpath):
55 copyres(ppcpath, outputref, ['cfrg'], 1)
56 elif os.path.exists(cfm68kpath):
57 copyres(cfm68kpath, outputref, ['cfrg'], 1)
59 print "Fixing sys.path prefs"
60 Res.UseResFile(outputref)
61 try:
62 res = Res.Get1Resource('STR#', 228) # from PythonCore
63 except Res.Error: pass
64 else:
65 res.RemoveResource()
66 # setting pref file name to empty string
67 res = Res.Get1NamedResource('STR ', "PythonPreferenceFileName")
68 res.data = Pstring("")
69 res.ChangedResource()
70 syspathpref = "$(APPLICATION)"
71 res = Res.Resource("\000\001" + Pstring(syspathpref))
72 res.AddResource("STR#", 229, "sys.path preference")
74 print "Creating 'PYD ' resources"
75 for modname, (ppcfrag, cfm68kfrag) in dynamicmodules.items():
76 res = Res.Resource(Pstring(ppcfrag) + Pstring(cfm68kfrag))
77 id = 0
78 while id < 128:
79 id = Res.Unique1ID('PYD ')
80 res.AddResource('PYD ', id, modname)
81 finally:
82 Res.CloseResFile(outputref)
83 print "Merging code fragments"
84 cfmfile.mergecfmfiles([applettemplatepath, corepath] + dynamicfiles.keys(),
85 output, architecture)
87 print "done!"
90 def findfragments(module_dict, architecture):
91 dynamicmodules = {}
92 dynamicfiles = {}
93 extraresfiles = []
94 for name, module in module_dict.items():
95 if module.gettype() <> 'dynamic':
96 continue
97 path = resolvealiasfile(module.__file__)
98 dir, filename = os.path.split(path)
99 ppcfile, cfm68kfile = makefilenames(filename)
101 # ppc stuff
102 ppcpath = os.path.join(dir, ppcfile)
103 if architecture <> 'm68k':
104 ppcfrag, dynamicfiles = getfragname(ppcpath, dynamicfiles)
105 else:
106 ppcfrag = "_no_fragment_"
108 # 68k stuff
109 cfm68kpath = os.path.join(dir, cfm68kfile)
110 if architecture <> 'pwpc':
111 cfm68kfrag, dynamicfiles = getfragname(cfm68kpath, dynamicfiles)
112 else:
113 cfm68kfrag = "_no_fragment_"
115 dynamicmodules[name] = ppcfrag, cfm68kfrag
116 if (ppcpath, cfm68kpath) not in extraresfiles:
117 extraresfiles.append((ppcpath, cfm68kpath))
118 return dynamicmodules, dynamicfiles, extraresfiles
121 def getfragname(path, dynamicfiles):
122 if not dynamicfiles.has_key(path):
123 if os.path.exists(path):
124 lib = cfmfile.CfrgResource(path)
125 fragname = lib.fragments[0].name
126 else:
127 print "shared lib not found:", path
128 fragname = "_no_fragment_"
129 dynamicfiles[path] = fragname
130 else:
131 fragname = dynamicfiles[path]
132 return fragname, dynamicfiles
135 def addpythonmodules(module_dict):
136 # XXX should really use macgen_rsrc.generate(), this does the same, but skips __main__
137 items = module_dict.items()
138 items.sort()
139 for name, module in items:
140 mtype = module.gettype()
141 if mtype not in ['module', 'package'] or name == "__main__":
142 continue
143 location = module.__file__
145 if location[-4:] == '.pyc':
146 # Attempt corresponding .py
147 location = location[:-1]
148 if location[-3:] != '.py':
149 print '*** skipping', location
150 continue
152 print 'Adding module "%s"' % name
153 id, name = py_resource.frompyfile(location, name, preload=0,
154 ispackage=mtype=='package')
156 def Pstring(str):
157 if len(str) > 255:
158 raise TypeError, "Str255 must be at most 255 chars long"
159 return chr(len(str)) + str
161 def makefilenames(name):
162 lname = string.lower(name)
163 pos = string.find(lname, ".ppc.")
164 if pos > 0:
165 return name, name[:pos] + '.CFM68K.' + name[pos+5:]
166 pos = string.find(lname, ".cfm68k.")
167 if pos > 0:
168 return name[:pos] + '.ppc.' + name[pos+8:], name
169 raise ValueError, "can't make ppc/cfm68k filenames"
171 def copyres(input, output, *args, **kwargs):
172 openedin = openedout = 0
173 if type(input) == types.StringType:
174 input = Res.OpenResFile(input)
175 openedin = 1
176 if type(output) == types.StringType:
177 output = Res.OpenResFile(output)
178 openedout = 1
179 try:
180 apply(buildtools.copyres, (input, output) + args, kwargs)
181 finally:
182 if openedin:
183 Res.CloseResFile(input)
184 if openedout:
185 Res.CloseResFile(output)
187 def findpythoncore():
188 """find the PythonCore shared library, possibly asking the user if we can't find it"""
190 vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
191 extpath = macfs.FSSpec((vRefNum, dirID, "")).as_pathname()
192 version = string.split(sys.version)[0]
193 corepath = os.path.join(extpath, "PythonCore " + version)
194 if not os.path.exists(corepath):
195 fss, ok = macfs.PromptGetFile("Please locate PythonCore:", "shlb")
196 if not ok:
197 raise KeyboardInterrupt, "cancelled"
198 corepath = fss.as_pathname()
199 return resolvealiasfile(corepath)
201 def resolvealiasfile(path):
202 try:
203 fss, dummy1, dummy2 = macfs.ResolveAliasFile(path)
204 except macfs.error:
205 pass
206 else:
207 path = fss.as_pathname()
208 return path