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.
47 -i filename: Include a file with additional command line options. Used
48 to prevent command lines growing beyond the capabilities of
49 the shell/OS. All arguments specified in filename
50 are read and the -i option replaced with the parsed
51 params (note - quoting args in this file is NOT supported)
53 -s subsystem: Specify the subsystem (For Windows only.);
54 'console' (default), 'windows', 'service' or 'com_dll'
56 -w: Toggle Windows (NT or 95) behavior.
57 (For debugging only -- on a win32 platform, win32 behavior
60 -r prefix=f: Replace path prefix.
61 Replace prefix with f in the source path references
62 contained in the resulting binary.
66 script: The Python script to be executed by the resulting binary.
68 module ...: Additional Python modules (referenced by pathname)
69 that will be included in the resulting binary. These
70 may be .py or .pyc files. If -m is specified, these are
71 module names that are search in the path instead.
75 In order to use freeze successfully, you must have built Python and
76 installed it ("make install").
78 The script should not use modules provided only as shared libraries;
79 if it does, the resulting binary is not self-contained.
83 # Import standard modules
91 # Import the freeze-private modules
93 import checkextensions
105 # overridable context
106 prefix
= None # settable with -p option
107 exec_prefix
= None # settable with -P option
109 exclude
= [] # settable with -x option
110 addn_link
= [] # settable with -l, but only honored under Windows.
115 win
= sys
.platform
[:3] == 'win'
116 replace_paths
= [] # settable with -r option
118 # default the exclude list for each platform
119 if win
: exclude
= exclude
+ [
120 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix', 'os2', 'ce']
122 # modules that are imported by the Python runtime
123 implicits
= ["site", "exceptions"]
126 frozen_c
= 'frozen.c'
127 config_c
= 'config.c'
128 target
= 'a.out' # normally derived from script name
129 makefile
= 'Makefile'
130 subsystem
= 'console'
132 # parse command line by first replacing any "-i" options with the file contents.
134 while pos
< len(sys
.argv
)-1: # last option can not be "-i", so this ensures "pos+1" is in range!
135 if sys
.argv
[pos
] == '-i':
137 options
= string
.split(open(sys
.argv
[pos
+1]).read())
139 usage("File name '%s' specified with the -i option can not be read - %s" % (sys
.argv
[pos
+1], why
) )
140 # Replace the '-i' and the filename with the read params.
141 sys
.argv
[pos
:pos
+2] = options
142 pos
= pos
+ len(options
) - 1 # Skip the name and the included args.
145 # Now parse the command line with the extras inserted.
147 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'r:a:de:hmo:p:P:qs:wx:l:')
148 except getopt
.error
, msg
:
149 usage('getopt error: ' + str(msg
))
151 # proces option arguments
174 usage("-s subsystem option only on Windows")
181 apply(modulefinder
.AddPackagePath
, tuple(string
.split(a
,"=", 2)))
183 f
,r
= string
.split(a
,"=", 2)
184 replace_paths
.append( (f
,r
) )
186 # default prefix and exec_prefix
191 exec_prefix
= sys
.exec_prefix
195 # determine whether -p points to the Python source tree
196 ishome
= os
.path
.exists(os
.path
.join(prefix
, 'Python', 'ceval.c'))
198 # locations derived from options
199 version
= sys
.version
[:3]
201 extensions_c
= 'frozen_extensions.c'
203 print "(Using Python source directory)"
205 incldir
= os
.path
.join(prefix
, 'Include')
206 config_h_dir
= exec_prefix
207 config_c_in
= os
.path
.join(prefix
, 'Modules', 'config.c.in')
208 frozenmain_c
= os
.path
.join(prefix
, 'Python', 'frozenmain.c')
209 makefile_in
= os
.path
.join(exec_prefix
, 'Modules', 'Makefile')
211 frozendllmain_c
= os
.path
.join(exec_prefix
, 'Pc\\frozen_dllmain.c')
213 binlib
= os
.path
.join(exec_prefix
,
214 'lib', 'python%s' % version
, 'config')
215 incldir
= os
.path
.join(prefix
, 'include', 'python%s' % version
)
216 config_h_dir
= os
.path
.join(exec_prefix
, 'include',
217 'python%s' % version
)
218 config_c_in
= os
.path
.join(binlib
, 'config.c.in')
219 frozenmain_c
= os
.path
.join(binlib
, 'frozenmain.c')
220 makefile_in
= os
.path
.join(binlib
, 'Makefile')
221 frozendllmain_c
= os
.path
.join(binlib
, 'frozen_dllmain.c')
224 includes
= ['-I' + incldir
, '-I' + config_h_dir
]
226 # sanity check of directories and files
227 check_dirs
= [prefix
, exec_prefix
, binlib
, incldir
]
228 if not win
: check_dirs
= check_dirs
+ extensions
# These are not directories on Windows.
229 for dir in check_dirs
:
230 if not os
.path
.exists(dir):
231 usage('needed directory %s not found' % dir)
232 if not os
.path
.isdir(dir):
233 usage('%s: not a directory' % dir)
235 files
= supp_sources
+ extensions
# extensions are files on Windows.
237 files
= [config_c_in
, makefile_in
] + supp_sources
238 for file in supp_sources
:
239 if not os
.path
.exists(file):
240 usage('needed file %s not found' % file)
241 if not os
.path
.isfile(file):
242 usage('%s: not a plain file' % file)
244 for dir in extensions
:
245 setup
= os
.path
.join(dir, 'Setup')
246 if not os
.path
.exists(setup
):
247 usage('needed file %s not found' % setup
)
248 if not os
.path
.isfile(setup
):
249 usage('%s: not a plain file' % setup
)
251 # check that enough arguments are passed
253 usage('at least one filename argument required')
255 # check that file arguments exist
259 # if user specified -m on the command line before _any_
260 # file names, then nothing should be checked (as the
261 # very first file should be a module name)
264 if not os
.path
.exists(arg
):
265 usage('argument %s not found' % arg
)
266 if not os
.path
.isfile(arg
):
267 usage('%s: not a plain file' % arg
)
269 # process non-option arguments
273 # derive target name from script name
274 base
= os
.path
.basename(scriptfile
)
275 base
, ext
= os
.path
.splitext(base
)
277 if base
!= scriptfile
:
280 target
= base
+ '.bin'
283 base_frozen_c
= frozen_c
284 base_config_c
= config_c
286 if odir
and not os
.path
.isdir(odir
):
289 print "Created output directory", odir
290 except os
.error
, msg
:
291 usage('%s: mkdir failed (%s)' % (odir
, str(msg
)))
294 base
= os
.path
.join(odir
, '')
295 frozen_c
= os
.path
.join(odir
, frozen_c
)
296 config_c
= os
.path
.join(odir
, config_c
)
297 target
= os
.path
.join(odir
, target
)
298 makefile
= os
.path
.join(odir
, makefile
)
299 if win
: extensions_c
= os
.path
.join(odir
, extensions_c
)
301 # Handle special entry point requirements
302 # (on Windows, some frozen programs do not use __main__, but
303 # import the module directly. Eg, DLLs, Services, etc
304 custom_entry_point
= None # Currently only used on Windows
305 python_entry_is_main
= 1 # Is the entry point called __main__?
306 # handle -s option on Windows
308 import winmakemakefile
310 custom_entry_point
, python_entry_is_main
= \
311 winmakemakefile
.get_custom_entry_point(subsystem
)
312 except ValueError, why
:
316 # Actual work starts here...
318 # collect all modules of the program
319 dir = os
.path
.dirname(scriptfile
)
321 mf
= modulefinder
.ModuleFinder(path
, debug
, exclude
, replace_paths
)
323 if win
and subsystem
=='service':
324 # If a Windows service, then add the "built-in" module.
325 mod
= mf
.add_module("servicemanager")
326 mod
.__file
__="dummy.pyd" # really built-in to the resulting EXE
328 for mod
in implicits
:
336 mf
.import_hook(mod
[:-2], None, ["*"])
342 # Add the main script as either __main__, or the actual module name.
343 if python_entry_is_main
:
344 mf
.run_script(scriptfile
)
346 mf
.load_file(scriptfile
)
353 # generate output for frozen modules
354 files
= makefreeze
.makefreeze(base
, dict, debug
, custom_entry_point
)
356 # look for unfrozen modules (builtin and of unknown origin)
362 if dict[mod
].__code
__:
364 if not dict[mod
].__file
__:
369 # search for unknown modules in extensions directories (not on Windows)
371 frozen_extensions
= [] # Windows list of modules.
372 if unknown
or (not win
and builtins
):
374 addfiles
, addmods
= \
375 checkextensions
.checkextensions(unknown
+builtins
,
382 # Do the windows thang...
383 import checkextensions_win32
384 # Get a list of CExtension instances, each describing a module
385 # (including its source files)
386 frozen_extensions
= checkextensions_win32
.checkextensions(
387 unknown
, extensions
, prefix
)
388 for mod
in frozen_extensions
:
389 unknown
.remove(mod
.name
)
391 # report unknown modules
393 sys
.stderr
.write('Warning: unknown modules remain: %s\n' %
394 string
.join(unknown
))
396 # windows gets different treatment
398 # Taking a shortcut here...
399 import winmakemakefile
, checkextensions_win32
400 checkextensions_win32
.write_extension_table(extensions_c
,
402 # Create a module definition for the bootstrap C code.
403 xtras
= [frozenmain_c
, os
.path
.basename(frozen_c
),
404 frozendllmain_c
, os
.path
.basename(extensions_c
)] + files
405 maindefn
= checkextensions_win32
.CExtension( '__main__', xtras
)
406 frozen_extensions
.append( maindefn
)
407 outfp
= open(makefile
, 'w')
409 winmakemakefile
.makemakefile(outfp
,
412 os
.path
.basename(target
))
417 # generate config.c and Makefile
419 infp
= open(config_c_in
)
420 outfp
= bkfile
.open(config_c
, 'w')
422 makeconfig
.makeconfig(infp
, outfp
, builtins
)
427 cflags
= defines
+ includes
+ ['$(OPT)']
428 libs
= [os
.path
.join(binlib
, 'libpython$(VERSION).a')]
431 if os
.path
.exists(makefile_in
):
432 makevars
= parsesetup
.getmakevars(makefile_in
)
433 for key
in makevars
.keys():
434 somevars
[key
] = makevars
[key
]
436 somevars
['CFLAGS'] = string
.join(cflags
) # override
437 files
= ['$(OPT)', '$(LDFLAGS)', base_config_c
, base_frozen_c
] + \
438 files
+ supp_sources
+ addfiles
+ libs
+ \
439 ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
441 outfp
= bkfile
.open(makefile
, 'w')
443 makemakefile
.makemakefile(outfp
, somevars
, files
, base_target
)
450 print 'Now run "make" in', odir
,
451 print 'to build the target:', base_target
453 print 'Now run "make" to build the target:', base_target
456 # Print usage message and exit
459 sys
.stdout
= sys
.stderr
461 print "Use ``%s -h'' for help" % sys
.argv
[0]