3 """Freeze a Python script into a binary.
5 usage: freeze [options...] script [module]...
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.
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.
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.
28 -o dir: Directory where the output files are created; default '.'.
30 -m: Additional arguments are module names instead of filenames.
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.
37 -l file: Pass the file to the linker (windows only)
39 -d: Debugging mode for the module finder.
41 -q: Make the module finder totally quiet.
43 -h: Print this help message.
45 -x module Exclude the specified module. It will still be imported
46 by the frozen binary if it exists on the host system.
48 -X module Like -x, except the module can never be imported by
51 -E: Freeze will fail if any modules can't be found (that
52 were not excluded using -x or -X).
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)
60 -s subsystem: Specify the subsystem (For Windows only.);
61 'console' (default), 'windows', 'service' or 'com_dll'
63 -w: Toggle Windows (NT or 95) behavior.
64 (For debugging only -- on a win32 platform, win32 behavior
67 -r prefix=f: Replace path prefix.
68 Replace prefix with f in the source path references
69 contained in the resulting binary.
73 script: The Python script to be executed by the resulting binary.
75 module ...: 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.
82 In order to use freeze successfully, you must have built Python and
83 installed it ("make install").
85 The script should not use modules provided only as shared libraries;
86 if it does, the resulting binary is not self-contained.
90 # Import standard modules
98 # Import the freeze-private modules
100 import checkextensions
111 # overridable context
112 prefix
= None # settable with -p option
113 exec_prefix
= None # settable with -P option
115 exclude
= [] # settable with -x option
116 addn_link
= [] # settable with -l, but only honored under Windows.
121 win
= sys
.platform
[:3] == 'win'
122 replace_paths
= [] # settable with -r option
123 error_if_any_missing
= 0
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',
131 fail_import
= exclude
[:]
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'
140 # parse command line by first replacing any "-i" options with the
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':
147 options
= open(sys
.argv
[pos
+1]).read().split()
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.
156 # Now parse the command line with the extras inserted.
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
))
162 # proces option arguments
185 usage("-s subsystem option only on Windows")
191 fail_import
.append(a
)
193 error_if_any_missing
= 1
197 apply(modulefinder
.AddPackagePath
, tuple(a
.split("=", 2)))
199 f
,r
= a
.split("=", 2)
200 replace_paths
.append( (f
,r
) )
202 # modules that are imported by the Python runtime
204 for module
in ('site', 'warnings',):
205 if module
not in exclude
:
206 implicits
.append(module
)
208 # default prefix and exec_prefix
213 exec_prefix
= sys
.exec_prefix
217 # determine whether -p points to the Python source tree
218 ishome
= os
.path
.exists(os
.path
.join(prefix
, 'Python', 'ceval.c'))
220 # locations derived from options
221 version
= sys
.version
[:3]
223 extensions_c
= 'frozen_extensions.c'
225 print "(Using Python source directory)"
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')
233 frozendllmain_c
= os
.path
.join(exec_prefix
, 'Pc\\frozen_dllmain.c')
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')
246 includes
= ['-I' + incldir
, '-I' + config_h_dir
]
248 # sanity check of directories and files
249 check_dirs
= [prefix
, exec_prefix
, binlib
, incldir
]
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)
259 files
= supp_sources
+ extensions
# extensions are files on Windows.
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)
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
)
275 # check that enough arguments are passed
277 usage('at least one filename argument required')
279 # check that file arguments exist
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)
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
)
293 # process non-option arguments
297 # derive target name from script name
298 base
= os
.path
.basename(scriptfile
)
299 base
, ext
= os
.path
.splitext(base
)
301 if base
!= scriptfile
:
304 target
= base
+ '.bin'
307 base_frozen_c
= frozen_c
308 base_config_c
= config_c
310 if odir
and not os
.path
.isdir(odir
):
313 print "Created output directory", odir
314 except os
.error
, msg
:
315 usage('%s: mkdir failed (%s)' % (odir
, str(msg
)))
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
)
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
332 import winmakemakefile
334 custom_entry_point
, python_entry_is_main
= \
335 winmakemakefile
.get_custom_entry_point(subsystem
)
336 except ValueError, why
:
340 # Actual work starts here...
342 # collect all modules of the program
343 dir = os
.path
.dirname(scriptfile
)
345 mf
= modulefinder
.ModuleFinder(path
, debug
, exclude
, replace_paths
)
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
352 for mod
in implicits
:
360 mf
.import_hook(mod
[:-2], None, ["*"])
366 # Add the main script as either __main__, or the actual module name.
367 if python_entry_is_main
:
368 mf
.run_script(scriptfile
)
370 mf
.load_file(scriptfile
)
377 if error_if_any_missing
:
378 missing
= mf
.any_missing()
380 sys
.exit("There are some missing modules: %r" % missing
)
382 # generate output for frozen modules
383 files
= makefreeze
.makefreeze(base
, dict, debug
, custom_entry_point
,
386 # look for unfrozen modules (builtin and of unknown origin)
392 if dict[mod
].__code
__:
394 if not dict[mod
].__file
__:
399 # search for unknown modules in extensions directories (not on Windows)
401 frozen_extensions
= [] # Windows list of modules.
402 if unknown
or (not win
and builtins
):
404 addfiles
, addmods
= \
405 checkextensions
.checkextensions(unknown
+builtins
,
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
)
421 # report unknown modules
423 sys
.stderr
.write('Warning: unknown modules remain: %s\n' %
426 # windows gets different treatment
428 # Taking a shortcut here...
429 import winmakemakefile
, checkextensions_win32
430 checkextensions_win32
.write_extension_table(extensions_c
,
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')
439 winmakemakefile
.makemakefile(outfp
,
442 os
.path
.basename(target
))
447 # generate config.c and Makefile
449 infp
= open(config_c_in
)
450 outfp
= bkfile
.open(config_c
, 'w')
452 makeconfig
.makeconfig(infp
, outfp
, builtins
)
458 cppflags
= defines
+ includes
459 libs
= [os
.path
.join(binlib
, 'libpython$(VERSION).a')]
462 if os
.path
.exists(makefile_in
):
463 makevars
= parsesetup
.getmakevars(makefile_in
)
464 for key
in makevars
.keys():
465 somevars
[key
] = makevars
[key
]
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)']
473 outfp
= bkfile
.open(makefile
, 'w')
475 makemakefile
.makemakefile(outfp
, somevars
, files
, base_target
)
482 print 'Now run "make" in', odir
,
483 print 'to build the target:', base_target
485 print 'Now run "make" to build the target:', base_target
488 # Print usage message and exit
491 sys
.stdout
= sys
.stderr
493 print "Use ``%s -h'' for help" % sys
.argv
[0]