summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-10-18 19:15:32 (GMT)
committerGuido van Rossum <guido@python.org>2001-10-18 19:15:32 (GMT)
commit03f7f088743bbab2dd5aa426670a41fd643112cd (patch)
treeb1427132d21ba0eb5f14120e1d91b6425e9b0826
parentdb7287c0f5b197bbfaf624d181333a92135ec261 (diff)
downloadcpython-03f7f088743bbab2dd5aa426670a41fd643112cd.zip
cpython-03f7f088743bbab2dd5aa426670a41fd643112cd.tar.gz
cpython-03f7f088743bbab2dd5aa426670a41fd643112cd.tar.bz2
Part 2/2 of SF patch #416704: More robust freeze, by Toby Dickenson.
(With slight cosmetic improvements to shorten lines and a grammar fix to a docstring.) This addes -X and -E options to freeze. From the docstring: -X module Like -x, except the module can never be imported by the frozen binary. -E: Freeze will fail if any modules can't be found (that were not excluded using -x or -X).
-rwxr-xr-xTools/freeze/freeze.py44
-rw-r--r--Tools/freeze/makefreeze.py9
-rw-r--r--Tools/freeze/modulefinder.py17
3 files changed, 59 insertions, 11 deletions
diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py
index b534098..c347d53 100755
--- a/Tools/freeze/freeze.py
+++ b/Tools/freeze/freeze.py
@@ -42,7 +42,14 @@ Options:
-h: Print this help message.
--x module Exclude the specified module.
+-x module Exclude the specified module. It will still be imported
+ by the frozen binary if it exists on the host system.
+
+-X module Like -x, except the module can never be imported by
+ the frozen binary.
+
+-E: Freeze will fail if any modules can't be found (that
+ were not excluded using -x or -X).
-i filename: Include a file with additional command line options. Used
to prevent command lines growing beyond the capabilities of
@@ -114,10 +121,15 @@ def main():
odir = ''
win = sys.platform[:3] == 'win'
replace_paths = [] # settable with -r option
+ error_if_any_missing = 0
# default the exclude list for each platform
if win: exclude = exclude + [
- 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix', 'os2', 'ce']
+ 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix',
+ 'os2', 'ce', 'riscos', 'riscosenviron', 'riscospath',
+ ]
+
+ fail_import = exclude[:]
# modules that are imported by the Python runtime
implicits = ["site", "exceptions"]
@@ -129,14 +141,17 @@ def main():
makefile = 'Makefile'
subsystem = 'console'
- # parse command line by first replacing any "-i" options with the file contents.
+ # parse command line by first replacing any "-i" options with the
+ # file contents.
pos = 1
- while pos < len(sys.argv)-1: # last option can not be "-i", so this ensures "pos+1" is in range!
+ while pos < len(sys.argv)-1:
+ # last option can not be "-i", so this ensures "pos+1" is in range!
if sys.argv[pos] == '-i':
try:
options = string.split(open(sys.argv[pos+1]).read())
except IOError, why:
- usage("File name '%s' specified with the -i option can not be read - %s" % (sys.argv[pos+1], why) )
+ usage("File name '%s' specified with the -i option "
+ "can not be read - %s" % (sys.argv[pos+1], why) )
# Replace the '-i' and the filename with the read params.
sys.argv[pos:pos+2] = options
pos = pos + len(options) - 1 # Skip the name and the included args.
@@ -144,7 +159,7 @@ def main():
# Now parse the command line with the extras inserted.
try:
- opts, args = getopt.getopt(sys.argv[1:], 'r:a:de:hmo:p:P:qs:wx:l:')
+ opts, args = getopt.getopt(sys.argv[1:], 'r:a:dEe:hmo:p:P:qs:wX:x:l:')
except getopt.error, msg:
usage('getopt error: ' + str(msg))
@@ -175,6 +190,11 @@ def main():
subsystem = a
if o == '-x':
exclude.append(a)
+ if o == '-X':
+ exclude.append(a)
+ fail_import.append(a)
+ if o == '-E':
+ error_if_any_missing = 1
if o == '-l':
addn_link.append(a)
if o == '-a':
@@ -225,7 +245,9 @@ def main():
# sanity check of directories and files
check_dirs = [prefix, exec_prefix, binlib, incldir]
- if not win: check_dirs = check_dirs + extensions # These are not directories on Windows.
+ if not win:
+ # These are not directories on Windows.
+ check_dirs = check_dirs + extensions
for dir in check_dirs:
if not os.path.exists(dir):
usage('needed directory %s not found' % dir)
@@ -350,8 +372,14 @@ def main():
print
dict = mf.modules
+ if error_if_any_missing:
+ missing = mf.any_missing()
+ if missing:
+ sys.exit("There are some missing modules: %r" % missing)
+
# generate output for frozen modules
- files = makefreeze.makefreeze(base, dict, debug, custom_entry_point)
+ files = makefreeze.makefreeze(base, dict, debug, custom_entry_point,
+ fail_import)
# look for unfrozen modules (builtin and of unknown origin)
builtins = []
diff --git a/Tools/freeze/makefreeze.py b/Tools/freeze/makefreeze.py
index b7bf9fd..ac59a9c 100644
--- a/Tools/freeze/makefreeze.py
+++ b/Tools/freeze/makefreeze.py
@@ -32,7 +32,7 @@ main(argc, argv)
"""
-def makefreeze(base, dict, debug=0, entry_point = None):
+def makefreeze(base, dict, debug=0, entry_point=None, fail_import=()):
if entry_point is None: entry_point = default_entry_point
done = []
files = []
@@ -63,6 +63,13 @@ def makefreeze(base, dict, debug=0, entry_point = None):
outfp.write(header)
for mod, mangled, size in done:
outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size))
+ outfp.write('\n')
+ # The following modules have a NULL code pointer, indicating
+ # that the prozen program should not search for them on the host
+ # system. Importing them will *always* raise an ImportError.
+ # The zero value size is never used.
+ for mod in fail_import:
+ outfp.write('\t{"%s", NULL, 0},\n' % (mod,))
outfp.write(trailer)
outfp.write(entry_point)
outfp.close()
diff --git a/Tools/freeze/modulefinder.py b/Tools/freeze/modulefinder.py
index 015708b..924c3a4 100644
--- a/Tools/freeze/modulefinder.py
+++ b/Tools/freeze/modulefinder.py
@@ -356,8 +356,12 @@ class ModuleFinder:
return m
def find_module(self, name, path):
- if name in self.excludes:
- self.msgout(3, "find_module -> Excluded")
+ if path:
+ fullname = '.'.join(path)+'.'+name
+ else:
+ fullname = name
+ if fullname in self.excludes:
+ self.msgout(3, "find_module -> Excluded", fullname)
raise ImportError, name
if path is None:
@@ -397,6 +401,15 @@ class ModuleFinder:
mods.sort()
print "?", key, "from", string.join(mods, ', ')
+ def any_missing(self):
+ keys = self.badmodules.keys()
+ missing = []
+ for key in keys:
+ if key not in self.excludes:
+ # Missing, and its not supposed to be
+ missing.append(key)
+ return missing
+
def replace_paths_in_code(self, co):
new_filename = original_filename = os.path.normpath(co.co_filename)
for f,r in self.replace_paths: