162 lines
4.8 KiB
Python
162 lines
4.8 KiB
Python
|
#! /usr/bin/env python
|
||
|
|
||
|
"""
|
||
|
|
||
|
This script can be used to produce a standalone executable from
|
||
|
arbitrary Python code. You supply the name of the starting Python
|
||
|
file to import, and this script attempts to generate an executable
|
||
|
that will produce the same results as "python startfile.py".
|
||
|
|
||
|
This script is actually a wrapper around Panda's FreezeTool.py, which
|
||
|
is itself a tool to use Python's built-in "freeze" utility to compile
|
||
|
Python code into a standalone executable. It also uses Python's
|
||
|
built-in modulefinder module, which it uses to find all of the modules
|
||
|
imported directly or indirectly by the original startfile.py.
|
||
|
|
||
|
Usage::
|
||
|
|
||
|
pfreeze.py [opts] [startfile]
|
||
|
|
||
|
Options::
|
||
|
|
||
|
-o output
|
||
|
Specifies the name of the resulting executable file to produce.
|
||
|
If this ends in ".mf", a multifile is written instead of a frozen
|
||
|
binary. If it ends in ".dll", ".pyd", or ".so", a shared library
|
||
|
is written.
|
||
|
|
||
|
-x module[,module...]
|
||
|
Specifies a comma-separated list of Python modules to exclude from
|
||
|
the resulting file, even if they appear to be referenced. You
|
||
|
may also repeat the -x command for each module.
|
||
|
|
||
|
-i module[,module...]
|
||
|
Specifies a comma-separated list of Python modules to include in
|
||
|
the resulting file, even if they do not appear to be referenced.
|
||
|
You may also repeat the -i command for each module.
|
||
|
|
||
|
-p module[,module...]
|
||
|
Specifies a list of Python modules that do run-time manipulation
|
||
|
of the __path__ variable, and thus must be actually imported to
|
||
|
determine the true value of __path__.
|
||
|
|
||
|
-P path
|
||
|
Specifies an additional directory in which we should search for
|
||
|
Python modules. This is equivalent to setting the PYTHONPATH
|
||
|
environment variable. May be repeated.
|
||
|
|
||
|
-s
|
||
|
Adds the standard set of modules that are necessary for embedding
|
||
|
the Python interpreter. Implicitly set if an executable is
|
||
|
generated.
|
||
|
|
||
|
-k
|
||
|
Keeps temporary files generated by pfreeze. Useful when debugging
|
||
|
FreezeTool itself.
|
||
|
|
||
|
"""
|
||
|
|
||
|
import getopt
|
||
|
import sys
|
||
|
import os
|
||
|
from . import FreezeTool
|
||
|
|
||
|
def usage(code, msg = ''):
|
||
|
if __doc__:
|
||
|
sys.stderr.write(__doc__ + '\n')
|
||
|
sys.stderr.write(str(msg) + '\n')
|
||
|
sys.exit(code)
|
||
|
|
||
|
|
||
|
def main(args=None):
|
||
|
if args is None:
|
||
|
args = sys.argv[1:]
|
||
|
|
||
|
freezer = FreezeTool.Freezer()
|
||
|
|
||
|
basename = None
|
||
|
addStartupModules = False
|
||
|
|
||
|
try:
|
||
|
opts, args = getopt.getopt(args, 'o:i:x:p:P:slkh')
|
||
|
except getopt.error as msg:
|
||
|
usage(1, msg)
|
||
|
|
||
|
for opt, arg in opts:
|
||
|
if opt == '-o':
|
||
|
basename = arg
|
||
|
elif opt == '-i':
|
||
|
for module in arg.split(','):
|
||
|
freezer.addModule(module)
|
||
|
elif opt == '-x':
|
||
|
for module in arg.split(','):
|
||
|
freezer.excludeModule(module)
|
||
|
elif opt == '-p':
|
||
|
for module in arg.split(','):
|
||
|
freezer.handleCustomPath(module)
|
||
|
elif opt == '-P':
|
||
|
sys.path.append(arg)
|
||
|
elif opt == '-s':
|
||
|
addStartupModules = True
|
||
|
elif opt == '-l':
|
||
|
freezer.linkExtensionModules = True
|
||
|
elif opt == '-k':
|
||
|
freezer.keepTemporaryFiles = True
|
||
|
elif opt == '-h':
|
||
|
usage(0)
|
||
|
else:
|
||
|
print('illegal option: ' + flag)
|
||
|
sys.exit(1)
|
||
|
|
||
|
if not basename:
|
||
|
usage(1, 'You did not specify an output file.')
|
||
|
|
||
|
if len(args) > 1:
|
||
|
usage(1, 'Only one main file may be specified.')
|
||
|
|
||
|
outputType = 'exe'
|
||
|
bl = basename.lower()
|
||
|
if bl.endswith('.mf'):
|
||
|
outputType = 'mf'
|
||
|
elif bl.endswith('.c'):
|
||
|
outputType = 'c'
|
||
|
elif bl.endswith('.dll') or bl.endswith('.pyd') or bl.endswith('.so'):
|
||
|
basename = os.path.splitext(basename)[0]
|
||
|
outputType = 'dll'
|
||
|
elif bl.endswith('.exe'):
|
||
|
basename = os.path.splitext(basename)[0]
|
||
|
|
||
|
compileToExe = False
|
||
|
if args:
|
||
|
startfile = args[0]
|
||
|
startmod = startfile
|
||
|
if startfile.endswith('.py') or startfile.endswith('.pyw') or \
|
||
|
startfile.endswith('.pyc') or startfile.endswith('.pyo'):
|
||
|
startmod = os.path.splitext(startfile)[0]
|
||
|
|
||
|
if outputType == 'dll' or outputType == 'c':
|
||
|
freezer.addModule(startmod, filename = startfile)
|
||
|
else:
|
||
|
freezer.addModule('__main__', filename = startfile)
|
||
|
compileToExe = True
|
||
|
addStartupModules = True
|
||
|
|
||
|
elif outputType == 'exe':
|
||
|
# We must have a main module when making an executable.
|
||
|
usage(1, 'A main file needs to be specified when creating an executable.')
|
||
|
|
||
|
freezer.done(addStartupModules = addStartupModules)
|
||
|
|
||
|
if outputType == 'mf':
|
||
|
freezer.writeMultifile(basename)
|
||
|
elif outputType == 'c':
|
||
|
freezer.writeCode(basename)
|
||
|
else:
|
||
|
freezer.generateCode(basename, compileToExe = compileToExe)
|
||
|
|
||
|
return 0
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
sys.exit(main())
|