1 """macgen_bin - Generate application from shared libraries"""
10 from Carbon
import Res
16 def generate(input, output
, module_dict
=None, architecture
='fat', debug
=0):
17 # try to remove old file
23 if module_dict
is None:
24 import macmodulefinder
25 print "Searching for modules..."
26 module_dict
, missing
= macmodulefinder
.process(input, [], [], 1)
30 answer
= EasyDialogs
.AskYesNoCancel("Some modules could not be found; continue anyway?\n(%s)"
31 % string
.join(missing
, ", "))
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)
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
)
63 res
= Res
.Get1Resource('STR#', 228) # from PythonCore
64 except Res
.Error
: pass
67 # setting pref file name to empty string
68 res
= Res
.Get1NamedResource('STR ', "PythonPreferenceFileName")
69 res
.data
= Pstring("")
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
))
80 id = Res
.Unique1ID('PYD ')
81 res
.AddResource('PYD ', id, modname
)
83 Res
.CloseResFile(outputref
)
84 print "Merging code fragments"
85 cfmfile
.mergecfmfiles([applettemplatepath
, corepath
] + dynamicfiles
.keys(),
91 def findfragments(module_dict
, architecture
):
95 for name
, module
in module_dict
.items():
96 if module
.gettype() <> 'dynamic':
98 path
= resolvealiasfile(module
.__file
__)
99 dir, filename
= os
.path
.split(path
)
100 ## ppcfile, cfm68kfile = makefilenames(filename)
102 cfm68kfile
= "dummy.cfm68k.slb"
105 ppcpath
= os
.path
.join(dir, ppcfile
)
106 if architecture
<> 'm68k':
107 ppcfrag
, dynamicfiles
= getfragname(ppcpath
, dynamicfiles
)
109 ppcfrag
= "_no_fragment_"
112 cfm68kpath
= os
.path
.join(dir, cfm68kfile
)
113 if architecture
<> 'pwpc':
114 cfm68kfrag
, dynamicfiles
= getfragname(cfm68kpath
, dynamicfiles
)
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
130 print "shared lib not found:", path
131 fragname
= "_no_fragment_"
132 dynamicfiles
[path
] = fragname
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()
142 for name
, module
in items
:
143 mtype
= module
.gettype()
144 if mtype
not in ['module', 'package'] or name
== "__main__":
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
155 print 'Adding module "%s"' % name
156 id, name
= py_resource
.frompyfile(location
, name
, preload
=0,
157 ispackage
=mtype
=='package')
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.")
168 ## return name, name[:pos] + '.CFM68K.' + name[pos+5:]
169 ## pos = string.find(lname, ".cfm68k.")
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)
179 if type(output
) == types
.StringType
:
180 output
= Res
.FSpOpenResFile(output
, 3)
183 apply(buildtools
.copyres
, (input, output
) + args
, kwargs
)
186 Res
.CloseResFile(input)
188 Res
.CloseResFile(output
)
190 def findpythoncore():
191 """find the PythonCore shared library, possibly asking the user if we can't find it"""
194 vRefNum
, dirID
= macfs
.FindFolder(kOnSystemDisk
, kSharedLibrariesFolderType
, 0)
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
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:",
211 raise KeyboardInterrupt, "cancelled"
212 return resolvealiasfile(corepath
)
214 def resolvealiasfile(path
):
216 fss
, dummy1
, dummy2
= macfs
.ResolveAliasFile(path
)
220 path
= fss
.as_pathname()