|
1 #! /usr/bin/env python |
|
2 # Configure PyInstaller for the current Python installation. |
|
3 # Copyright (C) 2005, Giovanni Bajo |
|
4 # Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc. |
|
5 # |
|
6 # This program is free software; you can redistribute it and/or |
|
7 # modify it under the terms of the GNU General Public License |
|
8 # as published by the Free Software Foundation; either version 2 |
|
9 # of the License, or (at your option) any later version. |
|
10 # |
|
11 # This program is distributed in the hope that it will be useful, |
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 # GNU General Public License for more details. |
|
15 # |
|
16 # You should have received a copy of the GNU General Public License |
|
17 # along with this program; if not, write to the Free Software |
|
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|
19 |
|
20 import os, sys, string, shutil |
|
21 HOME = os.path.dirname(sys.argv[0]) |
|
22 iswin = sys.platform[:3] == 'win' |
|
23 is24 = hasattr(sys, "version_info") and sys.version_info[:2] >= (2,4) |
|
24 cygwin = sys.platform == 'cygwin' |
|
25 configfile = os.path.join(HOME, 'config.dat') |
|
26 try: |
|
27 config = eval(open(configfile, 'r').read()) |
|
28 except IOError: |
|
29 config = {'useELFEXE':1} # if not set by Make.py we can assume Windows |
|
30 |
|
31 # Save Python version, to detect and avoid conflicts |
|
32 config["pythonVersion"] = sys.version |
|
33 |
|
34 import mf, bindepend |
|
35 |
|
36 # EXE_dependencies |
|
37 print "I: computing EXE_dependencies" |
|
38 python = sys.executable |
|
39 if not iswin: |
|
40 while os.path.islink(python): |
|
41 python = os.readlink(python) |
|
42 if not os.path.isabs(python): |
|
43 for dir in string.split(os.environ['PATH'], os.pathsep): |
|
44 test = os.path.join(dir, python) |
|
45 if os.path.exists(test): |
|
46 python = test |
|
47 break |
|
48 toc = bindepend.Dependencies([('', python, '')]) |
|
49 if iswin and sys.version[:3] == '1.5': |
|
50 import exceptions |
|
51 toc.append((os.path.basename(exceptions.__file__), exceptions.__file__, 'BINARY')) |
|
52 config['EXE_dependencies'] = toc[1:] |
|
53 |
|
54 _useTK = """\ |
|
55 # Generated by Configure.py |
|
56 # This file is public domain |
|
57 import os, sys |
|
58 try: |
|
59 basedir = os.environ['_MEIPASS2'] |
|
60 except KeyError: |
|
61 basedir = sys.path[0] |
|
62 tcldir = os.path.join(basedir, '_MEI', 'tcl%s') |
|
63 tkdir = os.path.join(basedir, '_MEI', 'tk%s') |
|
64 os.environ["TCL_LIBRARY"] = tcldir |
|
65 os.environ["TK_LIBRARY"] = tkdir |
|
66 os.putenv("TCL_LIBRARY", tcldir) |
|
67 os.putenv("TK_LIBRARY", tkdir) |
|
68 """ |
|
69 |
|
70 # TCL_root, TK_root and support/useTK.py |
|
71 print "I: Finding TCL/TK..." |
|
72 if not iswin: |
|
73 saveexcludes = bindepend.excludes |
|
74 bindepend.excludes = {} |
|
75 import re |
|
76 pattern = [r'libtcl(\d\.\d)?\.so', r'(?i)tcl(\d\d)\.dll'][iswin] |
|
77 a = mf.ImportTracker() |
|
78 a.analyze_r('Tkinter') |
|
79 binaries = [] |
|
80 for modnm, mod in a.modules.items(): |
|
81 if isinstance(mod, mf.ExtensionModule): |
|
82 binaries.append((mod.__name__, mod.__file__, 'EXTENSION')) |
|
83 binaries.extend(bindepend.Dependencies(binaries)) |
|
84 binaries.extend(bindepend.Dependencies([('', sys.executable, '')])) |
|
85 for nm, fnm, typ in binaries: |
|
86 mo = re.match(pattern, nm) |
|
87 if mo: |
|
88 ver = mo.group(1) |
|
89 tclbindir = os.path.dirname(fnm) |
|
90 if iswin: |
|
91 ver = ver[0] + '.' + ver[1:] |
|
92 elif ver is None: |
|
93 # we found "libtcl.so.0" so we need to get the version from the lib directory |
|
94 for name in os.listdir(tclbindir): |
|
95 mo = re.match(r'tcl(\d.\d)', name) |
|
96 if mo: |
|
97 ver = mo.group(1) |
|
98 print "I: found TCL/TK version %s" % ver |
|
99 open(os.path.join(HOME, 'support/useTK.py'), 'w').write(_useTK % (ver, ver)) |
|
100 tclnm = 'tcl%s' % ver |
|
101 tknm = 'tk%s' % ver |
|
102 # Linux: /usr/lib with the .tcl files in /usr/lib/tcl8.3 and /usr/lib/tk8.3 |
|
103 # Windows: Python21/DLLs with the .tcl files in Python21/tcl/tcl8.3 and Python21/tcl/tk8.3 |
|
104 # or D:/Programs/Tcl/bin with the .tcl files in D:/Programs/Tcl/lib/tcl8.0 and D:/Programs/Tcl/lib/tk8.0 |
|
105 if iswin: |
|
106 for attempt in ['../tcl', '../lib']: |
|
107 if os.path.exists(os.path.join(tclbindir, attempt, tclnm)): |
|
108 config['TCL_root'] = os.path.join(tclbindir, attempt, tclnm) |
|
109 config['TK_root'] = os.path.join(tclbindir, attempt, tknm) |
|
110 break |
|
111 else: |
|
112 config['TCL_root'] = os.path.join(tclbindir, tclnm) |
|
113 config['TK_root'] = os.path.join(tclbindir, tknm) |
|
114 break |
|
115 else: |
|
116 print "I: could not find TCL/TK" |
|
117 if not iswin: |
|
118 bindepend.excludes = saveexcludes |
|
119 |
|
120 #useZLIB |
|
121 print "I: testing for Zlib..." |
|
122 try: |
|
123 import zlib |
|
124 except ImportError: |
|
125 config['useZLIB'] = 0 |
|
126 print 'I: ... Zlib unavailable' |
|
127 else: |
|
128 config['useZLIB'] = 1 |
|
129 print 'I: ... Zlib available' |
|
130 |
|
131 #hasRsrcUpdate |
|
132 if iswin: |
|
133 # only available on windows |
|
134 print "I: Testing for ability to set icons, version resources..." |
|
135 try: |
|
136 import win32api, icon, versionInfo |
|
137 except ImportError, detail: |
|
138 config['hasRsrcUpdate'] = 0 |
|
139 print 'I: ... resource update unavailable -', detail |
|
140 else: |
|
141 test_exe = os.path.join(HOME, r'support\loader\run_7rw.exe') |
|
142 if not os.path.exists( test_exe ): |
|
143 config['hasRsrcUpdate'] = 0 |
|
144 print 'E: ... resource update unavailable - %s not found' % test_exe |
|
145 else: |
|
146 # The test_exe may be read-only |
|
147 # make a writable copy and test using that |
|
148 rw_test_exe = os.path.join( os.environ['TEMP'], 'me_test_exe.tmp' ) |
|
149 shutil.copyfile( test_exe, rw_test_exe ) |
|
150 try: |
|
151 hexe = win32api.BeginUpdateResource(rw_test_exe,0) |
|
152 except: |
|
153 config['hasRsrcUpdate'] = 0 |
|
154 print 'I: ... resource update unavailable - win32api.BeginUpdateResource failed' |
|
155 else: |
|
156 win32api.EndUpdateResource(hexe, 1) |
|
157 config['hasRsrcUpdate'] = 1 |
|
158 print 'I: ... resource update available' |
|
159 os.remove(rw_test_exe) |
|
160 else: |
|
161 config['hasRsrcUpdate'] = 0 |
|
162 |
|
163 _useUnicode = """\ |
|
164 # Generated by Configure.py |
|
165 # This file is public domain |
|
166 import %s |
|
167 """ |
|
168 |
|
169 _useUnicodeFN = os.path.join(HOME, 'support', 'useUnicode.py') |
|
170 |
|
171 #hasUnicode |
|
172 print 'I: Testing for Unicode support...' |
|
173 try: |
|
174 import codecs |
|
175 config['hasUnicode'] = 1 |
|
176 try: |
|
177 import encodings |
|
178 except ImportError: |
|
179 module = "codecs" |
|
180 else: |
|
181 module = "encodings" |
|
182 open(_useUnicodeFN, 'w').write(_useUnicode % module) |
|
183 print 'I: ... Unicode available' |
|
184 except ImportError: |
|
185 try: |
|
186 os.remove(_useUnicodeFN) |
|
187 except OSError: |
|
188 pass |
|
189 config['hasUnicode'] = 0 |
|
190 print 'I: ... Unicode NOT available' |
|
191 |
|
192 #hasUPX |
|
193 print 'I: testing for UPX...' |
|
194 hasUPX = 0 |
|
195 try: |
|
196 vers = os.popen("upx -V").readlines() |
|
197 if not vers: |
|
198 hasUPX = 0 |
|
199 else: |
|
200 v = string.split(vers[0])[1] |
|
201 hasUPX = tuple(map(int, string.split(v, "."))) |
|
202 if iswin and is24 and hasUPX < (1,92): |
|
203 print 'E: UPX is too old! Python 2.4 under Windows requires UPX 1.92+' |
|
204 hasUPX = 0 |
|
205 print 'I: ...UPX %s' % (('unavailable','available')[hasUPX != 0]) |
|
206 except Exception, e: |
|
207 print 'I: ...exception result in testing for UPX' |
|
208 print e, e.args |
|
209 config['hasUPX'] = hasUPX |
|
210 |
|
211 # now write out config, so Build can load |
|
212 outf = open(configfile, 'w') |
|
213 import pprint |
|
214 pprint.pprint(config, outf) |
|
215 outf.close() |
|
216 |
|
217 import Build |
|
218 |
|
219 # PYZ_dependencies |
|
220 print "I: computing PYZ dependencies..." |
|
221 a = mf.ImportTracker([os.path.join(HOME, 'support')]) |
|
222 a.analyze_r('archive') |
|
223 mod = a.modules['archive'] |
|
224 toc = Build.TOC([(mod.__name__, mod.__file__, 'PYMODULE')]) |
|
225 for i in range(len(toc)): |
|
226 nm, fnm, typ = toc[i] |
|
227 mod = a.modules[nm] |
|
228 tmp = [] |
|
229 for importednm, isdelayed, isconditional in mod.imports: |
|
230 if not isconditional: |
|
231 realnms = a.analyze_one(importednm, nm) |
|
232 for realnm in realnms: |
|
233 imported = a.modules[realnm] |
|
234 if not isinstance(imported, mf.BuiltinModule): |
|
235 tmp.append((imported.__name__, imported.__file__, imported.typ)) |
|
236 toc.extend(tmp) |
|
237 toc.reverse() |
|
238 config['PYZ_dependencies'] = toc.data |
|
239 |
|
240 outf = open(configfile, 'w') |
|
241 import pprint |
|
242 pprint.pprint(config, outf) |
|
243 outf.close() |
|
244 |