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',
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()
148
except IOError as 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.
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 as 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
modulefinder.AddPackagePath(*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 as 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 as 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)
389
mods = sorted(dict.keys())
391
if dict[mod].__code__:
393
if not dict[mod].__file__:
398
# search for unknown modules in extensions directories (not on Windows)
400
frozen_extensions = [] # Windows list of modules.
401
if unknown or (not win and builtins):
403
addfiles, addmods = \
404
checkextensions.checkextensions(unknown+builtins,
411
# Do the windows thang...
412
import checkextensions_win32
413
# Get a list of CExtension instances, each describing a module
414
# (including its source files)
415
frozen_extensions = checkextensions_win32.checkextensions(
416
unknown, extensions, prefix)
417
for mod in frozen_extensions:
418
unknown.remove(mod.name)
420
# report unknown modules
422
sys.stderr.write('Warning: unknown modules remain: %s\n' %
425
# windows gets different treatment
427
# Taking a shortcut here...
428
import winmakemakefile, checkextensions_win32
429
checkextensions_win32.write_extension_table(extensions_c,
431
# Create a module definition for the bootstrap C code.
432
xtras = [frozenmain_c, os.path.basename(frozen_c),
433
frozendllmain_c, os.path.basename(extensions_c)] + files
434
maindefn = checkextensions_win32.CExtension( '__main__', xtras )
435
frozen_extensions.append( maindefn )
436
outfp = open(makefile, 'w')
438
winmakemakefile.makemakefile(outfp,
441
os.path.basename(target))
446
# generate config.c and Makefile
448
infp = open(config_c_in)
449
outfp = bkfile.open(config_c, 'w')
451
makeconfig.makeconfig(infp, outfp, builtins)
457
cppflags = defines + includes
458
libs = [os.path.join(binlib, 'libpython$(VERSION).a')]
461
if os.path.exists(makefile_in):
462
makevars = parsesetup.getmakevars(makefile_in)
464
somevars[key] = makevars[key]
466
somevars['CFLAGS'] = ' '.join(cflags) # override
467
somevars['CPPFLAGS'] = ' '.join(cppflags) # override
468
files = [base_config_c, base_frozen_c] + \
469
files + supp_sources + addfiles + libs + \
470
['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
472
outfp = bkfile.open(makefile, 'w')
474
makemakefile.makemakefile(outfp, somevars, files, base_target)
481
print('Now run "make" in', odir, end=' ')
482
print('to build the target:', base_target)
484
print('Now run "make" to build the target:', base_target)
487
# Print usage message and exit
490
sys.stdout = sys.stderr
492
print("Use ``%s -h'' for help" % sys.argv[0])