| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | #! /usr/local/bin/python | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | # "Freeze" a Python script into a binary. | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | # Usage: see variable usage_msg below (before the imports!) | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # HINTS: | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | # - Edit the lines marked XXX below to localize. | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | # - You must have done "make inclinstall libainstall" in the Python | 
					
						
							|  |  |  | #   build directory. | 
					
						
							|  |  |  | # - The script should not use dynamically loaded modules | 
					
						
							|  |  |  | #   (*.so on most systems). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | # Usage message | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | usage_msg = """
 | 
					
						
							|  |  |  | usage: freeze [-p prefix] [-e extension] ... script [module] ... | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | -p prefix:    This is the prefix used when you ran | 
					
						
							|  |  |  |               'Make inclinstall libainstall' in the Python build directory. | 
					
						
							|  |  |  |               (If you never ran this, freeze won't work.) | 
					
						
							|  |  |  |                The default is /usr/local. | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | -e extension: A directory containing additional .o files that | 
					
						
							|  |  |  |               may be used to resolve modules.  This directory | 
					
						
							|  |  |  |               should also have a Setup file describing the .o files. | 
					
						
							|  |  |  |               More than one -e option may be given. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | script:       The Python script to be executed by the resulting binary. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module ...:   Additional Python modules (referenced by pathname) | 
					
						
							|  |  |  |               that will be included in the resulting binary.  These | 
					
						
							|  |  |  |               may be .py or .pyc files. | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-03-02 15:54:21 +00:00
										 |  |  | # XXX Change the following line to point to your Tools/freeze directory | 
					
						
							|  |  |  | PACK = '/ufs/guido/src/python/Tools/freeze' | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # XXX Change the following line to point to your install prefix | 
					
						
							|  |  |  | PREFIX = '/usr/local' | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Import standard modules | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | import cmp | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | import getopt | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | import string | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | import sys | 
					
						
							|  |  |  | import addpack | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Set the directory to look for the freeze-private modules | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dir = os.path.dirname(sys.argv[0]) | 
					
						
							|  |  |  | if dir: | 
					
						
							|  |  |  | 	pack = dir | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | else: | 
					
						
							|  |  |  | 	pack = PACK | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | addpack.addpack(pack) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Import the freeze-private modules | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | import checkextensions | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | import findmodules | 
					
						
							|  |  |  | import makeconfig | 
					
						
							|  |  |  | import makefreeze | 
					
						
							|  |  |  | import makemakefile | 
					
						
							|  |  |  | import parsesetup | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Main program | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 	# overridable context | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	prefix = PREFIX			# settable with -p option | 
					
						
							|  |  |  | 	extensions = [] | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 	path = sys.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# output files | 
					
						
							|  |  |  | 	frozen_c = 'frozen.c' | 
					
						
							|  |  |  | 	config_c = 'config.c' | 
					
						
							|  |  |  | 	target = 'a.out'		# normally derived from script name | 
					
						
							|  |  |  | 	makefile = 'Makefile' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# parse command line | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 		opts, args = getopt.getopt(sys.argv[1:], 'e:p:') | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 	except getopt.error, msg: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		usage('getopt error: ' + str(msg)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# proces option arguments | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 	for o, a in opts: | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 		if o == '-e': | 
					
						
							|  |  |  | 			extensions.append(a) | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		if o == '-p': | 
					
						
							|  |  |  | 			prefix = a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# locations derived from options | 
					
						
							|  |  |  | 	binlib = os.path.join(prefix, 'lib/python/lib') | 
					
						
							|  |  |  | 	incldir = os.path.join(prefix, 'include/Py') | 
					
						
							|  |  |  | 	config_c_in = os.path.join(binlib, 'config.c.in') | 
					
						
							|  |  |  | 	frozenmain_c = os.path.join(binlib, 'frozenmain.c') | 
					
						
							|  |  |  | 	makefile_in = os.path.join(binlib, 'Makefile') | 
					
						
							|  |  |  | 	defines = ['-DHAVE_CONFIG_H', '-DUSE_FROZEN', '-DNO_MAIN', | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 		   '-DPYTHONPATH=\\"$(PYTHONPATH)\\"'] | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 	includes = ['-I' + incldir, '-I' + binlib] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	# sanity check of directories and files | 
					
						
							|  |  |  | 	for dir in [prefix, binlib, incldir] + extensions: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		if not os.path.exists(dir): | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 			usage('needed directory %s not found' % dir) | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		if not os.path.isdir(dir): | 
					
						
							|  |  |  | 			usage('%s: not a directory' % dir) | 
					
						
							|  |  |  | 	for file in config_c_in, makefile_in, frozenmain_c: | 
					
						
							|  |  |  | 		if not os.path.exists(file): | 
					
						
							|  |  |  | 			usage('needed file %s not found' % file) | 
					
						
							|  |  |  | 		if not os.path.isfile(file): | 
					
						
							|  |  |  | 			usage('%s: not a plain file' % file) | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	for dir in extensions: | 
					
						
							|  |  |  | 		setup = os.path.join(dir, 'Setup') | 
					
						
							|  |  |  | 		if not os.path.exists(setup): | 
					
						
							|  |  |  | 			usage('needed file %s not found' % setup) | 
					
						
							|  |  |  | 		if not os.path.isfile(setup): | 
					
						
							|  |  |  | 			usage('%s: not a plain file' % setup) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# check that enough arguments are passed | 
					
						
							|  |  |  | 	if not args: | 
					
						
							|  |  |  | 		usage('at least one filename argument required') | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	# check that file arguments exist | 
					
						
							|  |  |  | 	for arg in args: | 
					
						
							|  |  |  | 		if not os.path.exists(arg): | 
					
						
							|  |  |  | 			usage('argument %s not found' % arg) | 
					
						
							|  |  |  | 		if not os.path.isfile(arg): | 
					
						
							|  |  |  | 			usage('%s: not a plain file' % arg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# process non-option arguments | 
					
						
							|  |  |  | 	scriptfile = args[0] | 
					
						
							|  |  |  | 	modules = args[1:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# derive target name from script name | 
					
						
							|  |  |  | 	base = os.path.basename(scriptfile) | 
					
						
							|  |  |  | 	base, ext = os.path.splitext(base) | 
					
						
							|  |  |  | 	if base: | 
					
						
							|  |  |  | 		if base != scriptfile: | 
					
						
							|  |  |  | 			target = base | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 		else: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 			target = base + '.bin' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Actual work starts here... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dict = findmodules.findmodules(scriptfile, modules, path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	backup = frozen_c + '~' | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		os.rename(frozen_c, backup) | 
					
						
							|  |  |  | 	except os.error: | 
					
						
							|  |  |  | 		backup = None | 
					
						
							|  |  |  | 	outfp = open(frozen_c, 'w') | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		makefreeze.makefreeze(outfp, dict) | 
					
						
							|  |  |  | 	finally: | 
					
						
							|  |  |  | 		outfp.close() | 
					
						
							|  |  |  | 	if backup: | 
					
						
							|  |  |  | 		if cmp.cmp(backup, frozen_c): | 
					
						
							|  |  |  | 			sys.stderr.write('%s not changed, not written\n' % | 
					
						
							|  |  |  | 					 frozen_c) | 
					
						
							|  |  |  | 			os.rename(backup, frozen_c) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 	builtins = [] | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	unknown = [] | 
					
						
							| 
									
										
										
										
											1994-10-03 16:37:36 +00:00
										 |  |  | 	mods = dict.keys() | 
					
						
							|  |  |  | 	mods.sort() | 
					
						
							|  |  |  | 	for mod in mods: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		if dict[mod] == '<builtin>': | 
					
						
							|  |  |  | 			builtins.append(mod) | 
					
						
							| 
									
										
										
										
											1994-10-03 16:37:36 +00:00
										 |  |  | 		elif dict[mod] == '<unknown>': | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 			unknown.append(mod) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	addfiles = [] | 
					
						
							|  |  |  | 	if unknown: | 
					
						
							|  |  |  | 		addfiles, addmods = \ | 
					
						
							|  |  |  | 			  checkextensions.checkextensions(unknown, extensions) | 
					
						
							|  |  |  | 		for mod in addmods: | 
					
						
							|  |  |  | 			unknown.remove(mod) | 
					
						
							|  |  |  | 		builtins = builtins + addmods | 
					
						
							|  |  |  | 	if unknown: | 
					
						
							|  |  |  | 		sys.stderr.write('Warning: unknown modules remain: %s\n' % | 
					
						
							|  |  |  | 				 string.join(unknown)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	builtins.sort() | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 	infp = open(config_c_in) | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	backup = config_c + '~' | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		os.rename(config_c, backup) | 
					
						
							|  |  |  | 	except os.error: | 
					
						
							|  |  |  | 		backup = None | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 	outfp = open(config_c, 'w') | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		makeconfig.makeconfig(infp, outfp, builtins) | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 	finally: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		outfp.close() | 
					
						
							|  |  |  | 	infp.close() | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	if backup: | 
					
						
							|  |  |  | 		if cmp.cmp(backup, config_c): | 
					
						
							|  |  |  | 			sys.stderr.write('%s not changed, not written\n' % | 
					
						
							|  |  |  | 					 config_c) | 
					
						
							|  |  |  | 			os.rename(backup, config_c) | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cflags = defines + includes + ['$(OPT)'] | 
					
						
							|  |  |  | 	libs = [] | 
					
						
							|  |  |  | 	for n in 'Modules', 'Python', 'Objects', 'Parser': | 
					
						
							|  |  |  | 		n = 'lib%s.a' % n | 
					
						
							|  |  |  | 		n = os.path.join(binlib, n) | 
					
						
							|  |  |  | 		libs.append(n) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	makevars = parsesetup.getmakevars(makefile_in) | 
					
						
							|  |  |  | 	somevars = {} | 
					
						
							|  |  |  | 	for key in makevars.keys(): | 
					
						
							|  |  |  | 		somevars[key] = makevars[key] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	somevars['CFLAGS'] = string.join(cflags) # override | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 	files = ['$(OPT)', config_c, frozen_c, frozenmain_c] + \ | 
					
						
							|  |  |  | 		addfiles + libs + \ | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	outfp = open(makefile, 'w') | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1994-10-03 16:33:08 +00:00
										 |  |  | 		makemakefile.makemakefile(outfp, somevars, files, target) | 
					
						
							|  |  |  | 	finally: | 
					
						
							|  |  |  | 		outfp.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Done! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	print 'Now run make to build the target:', target | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-05 16:13:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Print usage message and exit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def usage(msg = None): | 
					
						
							|  |  |  | 	if msg: | 
					
						
							|  |  |  | 		sys.stderr.write(str(msg) + '\n') | 
					
						
							|  |  |  | 	sys.stderr.write(usage_msg) | 
					
						
							|  |  |  | 	sys.exit(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 10:25:54 +00:00
										 |  |  | main() |