source: python/vendor/Python-2.6.5/Tools/freeze/freeze.py

Last change on this file was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 16.4 KB
Line 
1#! /usr/bin/env python
2
3"""Freeze a Python script into a binary.
4
5usage: freeze [options...] script [module]...
6
7Options:
8-p prefix: This is the prefix used when you ran ``make install''
9 in the Python build directory.
10 (If you never ran this, freeze won't work.)
11 The default is whatever sys.prefix evaluates to.
12 It can also be the top directory of the Python source
13 tree; then -P must point to the build tree.
14
15-P exec_prefix: Like -p but this is the 'exec_prefix', used to
16 install objects etc. The default is whatever sys.exec_prefix
17 evaluates to, or the -p argument if given.
18 If -p points to the Python source tree, -P must point
19 to the build tree, if different.
20
21-e extension: A directory containing additional .o files that
22 may be used to resolve modules. This directory
23 should also have a Setup file describing the .o files.
24 On Windows, the name of a .INI file describing one
25 or more extensions is passed.
26 More than one -e option may be given.
27
28-o dir: Directory where the output files are created; default '.'.
29
30-m: Additional arguments are module names instead of filenames.
31
32-a package=dir: Additional directories to be added to the package's
33 __path__. Used to simulate directories added by the
34 package at runtime (eg, by OpenGL and win32com).
35 More than one -a option may be given for each package.
36
37-l file: Pass the file to the linker (windows only)
38
39-d: Debugging mode for the module finder.
40
41-q: Make the module finder totally quiet.
42
43-h: Print this help message.
44
45-x module Exclude the specified module. It will still be imported
46 by the frozen binary if it exists on the host system.
47
48-X module Like -x, except the module can never be imported by
49 the frozen binary.
50
51-E: Freeze will fail if any modules can't be found (that
52 were not excluded using -x or -X).
53
54-i filename: Include a file with additional command line options. Used
55 to prevent command lines growing beyond the capabilities of
56 the shell/OS. All arguments specified in filename
57 are read and the -i option replaced with the parsed
58 params (note - quoting args in this file is NOT supported)
59
60-s subsystem: Specify the subsystem (For Windows only.);
61 'console' (default), 'windows', 'service' or 'com_dll'
62
63-w: Toggle Windows (NT or 95) behavior.
64 (For debugging only -- on a win32 platform, win32 behavior
65 is automatic.)
66
67-r prefix=f: Replace path prefix.
68 Replace prefix with f in the source path references
69 contained in the resulting binary.
70
71Arguments:
72
73script: The Python script to be executed by the resulting binary.
74
75module ...: Additional Python modules (referenced by pathname)
76 that will be included in the resulting binary. These
77 may be .py or .pyc files. If -m is specified, these are
78 module names that are search in the path instead.
79
80NOTES:
81
82In order to use freeze successfully, you must have built Python and
83installed it ("make install").
84
85The script should not use modules provided only as shared libraries;
86if it does, the resulting binary is not self-contained.
87"""
88
89
90# Import standard modules
91
92import modulefinder
93import getopt
94import os
95import sys
96
97
98# Import the freeze-private modules
99
100import checkextensions
101import makeconfig
102import makefreeze
103import makemakefile
104import parsesetup
105import bkfile
106
107
108# Main program
109
110def main():
111 # overridable context
112 prefix = None # settable with -p option
113 exec_prefix = None # settable with -P option
114 extensions = []
115 exclude = [] # settable with -x option
116 addn_link = [] # settable with -l, but only honored under Windows.
117 path = sys.path[:]
118 modargs = 0
119 debug = 1
120 odir = ''
121 win = sys.platform[:3] == 'win'
122 replace_paths = [] # settable with -r option
123 error_if_any_missing = 0
124
125 # default the exclude list for each platform
126 if win: exclude = exclude + [
127 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix',
128 'os2', 'ce', 'riscos', 'riscosenviron', 'riscospath',
129 ]
130
131 fail_import = exclude[:]
132
133 # output files
134 frozen_c = 'frozen.c'
135 config_c = 'config.c'
136 target = 'a.out' # normally derived from script name
137 makefile = 'Makefile'
138 subsystem = 'console'
139
140 # parse command line by first replacing any "-i" options with the
141 # file contents.
142 pos = 1
143 while pos < len(sys.argv)-1:
144 # last option can not be "-i", so this ensures "pos+1" is in range!
145 if sys.argv[pos] == '-i':
146 try:
147 options = open(sys.argv[pos+1]).read().split()
148 except IOError, why:
149 usage("File name '%s' specified with the -i option "
150 "can not be read - %s" % (sys.argv[pos+1], why) )
151 # Replace the '-i' and the filename with the read params.
152 sys.argv[pos:pos+2] = options
153 pos = pos + len(options) - 1 # Skip the name and the included args.
154 pos = pos + 1
155
156 # Now parse the command line with the extras inserted.
157 try:
158 opts, args = getopt.getopt(sys.argv[1:], 'r:a:dEe:hmo:p:P:qs:wX:x:l:')
159 except getopt.error, msg:
160 usage('getopt error: ' + str(msg))
161
162 # proces option arguments
163 for o, a in opts:
164 if o == '-h':
165 print __doc__
166 return
167 if o == '-d':
168 debug = debug + 1
169 if o == '-e':
170 extensions.append(a)
171 if o == '-m':
172 modargs = 1
173 if o == '-o':
174 odir = a
175 if o == '-p':
176 prefix = a
177 if o == '-P':
178 exec_prefix = a
179 if o == '-q':
180 debug = 0
181 if o == '-w':
182 win = not win
183 if o == '-s':
184 if not win:
185 usage("-s subsystem option only on Windows")
186 subsystem = a
187 if o == '-x':
188 exclude.append(a)
189 if o == '-X':
190 exclude.append(a)
191 fail_import.append(a)
192 if o == '-E':
193 error_if_any_missing = 1
194 if o == '-l':
195 addn_link.append(a)
196 if o == '-a':
197 apply(modulefinder.AddPackagePath, tuple(a.split("=", 2)))
198 if o == '-r':
199 f,r = a.split("=", 2)
200 replace_paths.append( (f,r) )
201
202 # modules that are imported by the Python runtime
203 implicits = []
204 for module in ('site', 'warnings',):
205 if module not in exclude:
206 implicits.append(module)
207
208 # default prefix and exec_prefix
209 if not exec_prefix:
210 if prefix:
211 exec_prefix = prefix
212 else:
213 exec_prefix = sys.exec_prefix
214 if not prefix:
215 prefix = sys.prefix
216
217 # determine whether -p points to the Python source tree
218 ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c'))
219
220 # locations derived from options
221 version = sys.version[:3]
222 if win:
223 extensions_c = 'frozen_extensions.c'
224 if ishome:
225 print "(Using Python source directory)"
226 binlib = exec_prefix
227 incldir = os.path.join(prefix, 'Include')
228 config_h_dir = exec_prefix
229 config_c_in = os.path.join(prefix, 'Modules', 'config.c.in')
230 frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c')
231 makefile_in = os.path.join(exec_prefix, 'Makefile')
232 if win:
233 frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c')
234 else:
235 binlib = os.path.join(exec_prefix,
236 'lib', 'python%s' % version, 'config')
237 incldir = os.path.join(prefix, 'include', 'python%s' % version)
238 config_h_dir = os.path.join(exec_prefix, 'include',
239 'python%s' % version)
240 config_c_in = os.path.join(binlib, 'config.c.in')
241 frozenmain_c = os.path.join(binlib, 'frozenmain.c')
242 makefile_in = os.path.join(binlib, 'Makefile')
243 frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c')
244 supp_sources = []
245 defines = []
246 includes = ['-I' + incldir, '-I' + config_h_dir]
247
248 # sanity check of directories and files
249 check_dirs = [prefix, exec_prefix, binlib, incldir]
250 if not win:
251 # These are not directories on Windows.
252 check_dirs = check_dirs + extensions
253 for dir in check_dirs:
254 if not os.path.exists(dir):
255 usage('needed directory %s not found' % dir)
256 if not os.path.isdir(dir):
257 usage('%s: not a directory' % dir)
258 if win:
259 files = supp_sources + extensions # extensions are files on Windows.
260 else:
261 files = [config_c_in, makefile_in] + supp_sources
262 for file in supp_sources:
263 if not os.path.exists(file):
264 usage('needed file %s not found' % file)
265 if not os.path.isfile(file):
266 usage('%s: not a plain file' % file)
267 if not win:
268 for dir in extensions:
269 setup = os.path.join(dir, 'Setup')
270 if not os.path.exists(setup):
271 usage('needed file %s not found' % setup)
272 if not os.path.isfile(setup):
273 usage('%s: not a plain file' % setup)
274
275 # check that enough arguments are passed
276 if not args:
277 usage('at least one filename argument required')
278
279 # check that file arguments exist
280 for arg in args:
281 if arg == '-m':
282 break
283 # if user specified -m on the command line before _any_
284 # file names, then nothing should be checked (as the
285 # very first file should be a module name)
286 if modargs:
287 break
288 if not os.path.exists(arg):
289 usage('argument %s not found' % arg)
290 if not os.path.isfile(arg):
291 usage('%s: not a plain file' % arg)
292
293 # process non-option arguments
294 scriptfile = args[0]
295 modules = args[1:]
296
297 # derive target name from script name
298 base = os.path.basename(scriptfile)
299 base, ext = os.path.splitext(base)
300 if base:
301 if base != scriptfile:
302 target = base
303 else:
304 target = base + '.bin'
305
306 # handle -o option
307 base_frozen_c = frozen_c
308 base_config_c = config_c
309 base_target = target
310 if odir and not os.path.isdir(odir):
311 try:
312 os.mkdir(odir)
313 print "Created output directory", odir
314 except os.error, msg:
315 usage('%s: mkdir failed (%s)' % (odir, str(msg)))
316 base = ''
317 if odir:
318 base = os.path.join(odir, '')
319 frozen_c = os.path.join(odir, frozen_c)
320 config_c = os.path.join(odir, config_c)
321 target = os.path.join(odir, target)
322 makefile = os.path.join(odir, makefile)
323 if win: extensions_c = os.path.join(odir, extensions_c)
324
325 # Handle special entry point requirements
326 # (on Windows, some frozen programs do not use __main__, but
327 # import the module directly. Eg, DLLs, Services, etc
328 custom_entry_point = None # Currently only used on Windows
329 python_entry_is_main = 1 # Is the entry point called __main__?
330 # handle -s option on Windows
331 if win:
332 import winmakemakefile
333 try:
334 custom_entry_point, python_entry_is_main = \
335 winmakemakefile.get_custom_entry_point(subsystem)
336 except ValueError, why:
337 usage(why)
338
339
340 # Actual work starts here...
341
342 # collect all modules of the program
343 dir = os.path.dirname(scriptfile)
344 path[0] = dir
345 mf = modulefinder.ModuleFinder(path, debug, exclude, replace_paths)
346
347 if win and subsystem=='service':
348 # If a Windows service, then add the "built-in" module.
349 mod = mf.add_module("servicemanager")
350 mod.__file__="dummy.pyd" # really built-in to the resulting EXE
351
352 for mod in implicits:
353 mf.import_hook(mod)
354 for mod in modules:
355 if mod == '-m':
356 modargs = 1
357 continue
358 if modargs:
359 if mod[-2:] == '.*':
360 mf.import_hook(mod[:-2], None, ["*"])
361 else:
362 mf.import_hook(mod)
363 else:
364 mf.load_file(mod)
365
366 # Add the main script as either __main__, or the actual module name.
367 if python_entry_is_main:
368 mf.run_script(scriptfile)
369 else:
370 mf.load_file(scriptfile)
371
372 if debug > 0:
373 mf.report()
374 print
375 dict = mf.modules
376
377 if error_if_any_missing:
378 missing = mf.any_missing()
379 if missing:
380 sys.exit("There are some missing modules: %r" % missing)
381
382 # generate output for frozen modules
383 files = makefreeze.makefreeze(base, dict, debug, custom_entry_point,
384 fail_import)
385
386 # look for unfrozen modules (builtin and of unknown origin)
387 builtins = []
388 unknown = []
389 mods = dict.keys()
390 mods.sort()
391 for mod in mods:
392 if dict[mod].__code__:
393 continue
394 if not dict[mod].__file__:
395 builtins.append(mod)
396 else:
397 unknown.append(mod)
398
399 # search for unknown modules in extensions directories (not on Windows)
400 addfiles = []
401 frozen_extensions = [] # Windows list of modules.
402 if unknown or (not win and builtins):
403 if not win:
404 addfiles, addmods = \
405 checkextensions.checkextensions(unknown+builtins,
406 extensions)
407 for mod in addmods:
408 if mod in unknown:
409 unknown.remove(mod)
410 builtins.append(mod)
411 else:
412 # Do the windows thang...
413 import checkextensions_win32
414 # Get a list of CExtension instances, each describing a module
415 # (including its source files)
416 frozen_extensions = checkextensions_win32.checkextensions(
417 unknown, extensions, prefix)
418 for mod in frozen_extensions:
419 unknown.remove(mod.name)
420
421 # report unknown modules
422 if unknown:
423 sys.stderr.write('Warning: unknown modules remain: %s\n' %
424 ' '.join(unknown))
425
426 # windows gets different treatment
427 if win:
428 # Taking a shortcut here...
429 import winmakemakefile, checkextensions_win32
430 checkextensions_win32.write_extension_table(extensions_c,
431 frozen_extensions)
432 # Create a module definition for the bootstrap C code.
433 xtras = [frozenmain_c, os.path.basename(frozen_c),
434 frozendllmain_c, os.path.basename(extensions_c)] + files
435 maindefn = checkextensions_win32.CExtension( '__main__', xtras )
436 frozen_extensions.append( maindefn )
437 outfp = open(makefile, 'w')
438 try:
439 winmakemakefile.makemakefile(outfp,
440 locals(),
441 frozen_extensions,
442 os.path.basename(target))
443 finally:
444 outfp.close()
445 return
446
447 # generate config.c and Makefile
448 builtins.sort()
449 infp = open(config_c_in)
450 outfp = bkfile.open(config_c, 'w')
451 try:
452 makeconfig.makeconfig(infp, outfp, builtins)
453 finally:
454 outfp.close()
455 infp.close()
456
457 cflags = ['$(OPT)']
458 cppflags = defines + includes
459 libs = [os.path.join(binlib, 'libpython$(VERSION).a')]
460
461 somevars = {}
462 if os.path.exists(makefile_in):
463 makevars = parsesetup.getmakevars(makefile_in)
464 for key in makevars.keys():
465 somevars[key] = makevars[key]
466
467 somevars['CFLAGS'] = ' '.join(cflags) # override
468 somevars['CPPFLAGS'] = ' '.join(cppflags) # override
469 files = [base_config_c, base_frozen_c] + \
470 files + supp_sources + addfiles + libs + \
471 ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
472
473 outfp = bkfile.open(makefile, 'w')
474 try:
475 makemakefile.makemakefile(outfp, somevars, files, base_target)
476 finally:
477 outfp.close()
478
479 # Done!
480
481 if odir:
482 print 'Now run "make" in', odir,
483 print 'to build the target:', base_target
484 else:
485 print 'Now run "make" to build the target:', base_target
486
487
488# Print usage message and exit
489
490def usage(msg):
491 sys.stdout = sys.stderr
492 print "Error:", msg
493 print "Use ``%s -h'' for help" % sys.argv[0]
494 sys.exit(2)
495
496
497main()
Note: See TracBrowser for help on using the repository browser.