| 
									
										
										
										
											1994-01-07 11:43:11 +00:00
										 |  |  | #! /usr/local/bin/python | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Given a Python script, create a binary that runs the script. | 
					
						
							|  |  |  | # The binary is 100% independent of Python libraries and binaries. | 
					
						
							|  |  |  | # It will not contain any Python source code -- only "compiled" Python | 
					
						
							|  |  |  | # (as initialized static variables containing marshalled code objects). | 
					
						
							|  |  |  | # It even does the right thing for dynamically loaded modules! | 
					
						
							|  |  |  | # The module search path of the binary is set to the current directory. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Some problems remain: | 
					
						
							|  |  |  | # - It's highly non-portable, since it knows about paths and libraries | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | #   (there's a customization section though, and it knows how to | 
					
						
							|  |  |  | #   distinguish an SGI from a Sun SPARC system -- adding knowledge | 
					
						
							|  |  |  | #   about more systems is left as an exercise for the reader). | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | # - You need to have the Python source tree lying around as well as | 
					
						
							|  |  |  | #   the "libpython.a" used to generate the Python binary. | 
					
						
							|  |  |  | # - For scripts that use many modules it generates absurdly large | 
					
						
							|  |  |  | #   files (frozen.c and config.o as well as the final binary), | 
					
						
							|  |  |  | #   and is consequently rather slow. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Caveats: | 
					
						
							|  |  |  | # - The search for modules sometimes finds modules that are never | 
					
						
							|  |  |  | #   actually imported since the code importing them is never executed. | 
					
						
							|  |  |  | # - If an imported module isn't found, you get a warning but the | 
					
						
							|  |  |  | #   process of freezing continues.  The binary will fail if it | 
					
						
							|  |  |  | #   actually tries to import one of these modules. | 
					
						
							|  |  |  | # - This often happens with the module 'mac', which module 'os' tries | 
					
						
							|  |  |  | #   to import (to determine whether it is running on a Macintosh). | 
					
						
							|  |  |  | #   You can ignore the warning about this. | 
					
						
							|  |  |  | # - If the program dynamically reads or generates Python code and | 
					
						
							|  |  |  | #   executes it, this code may reference built-in or library modules | 
					
						
							|  |  |  | #   that aren't present in the frozen binary, and this will fail. | 
					
						
							|  |  |  | # - Your program may be using external data files, e.g. compiled | 
					
						
							|  |  |  | #   forms definitions (*.fd).  These aren't incorporated.  Since | 
					
						
							|  |  |  | #   sys.path in the resulting binary only contains '.', if your | 
					
						
							|  |  |  | #   program searches its data files along sys.path (as the 'flp' | 
					
						
							|  |  |  | #   modules does to find its forms definitions), you may need to | 
					
						
							|  |  |  | #   change the program to extend the search path or instruct its users | 
					
						
							|  |  |  | #   to set the environment variable PYTHONPATH to point to your data | 
					
						
							|  |  |  | #   files. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Usage hints: | 
					
						
							|  |  |  | # - If you have a bunch of scripts that you want to freeze, instead | 
					
						
							|  |  |  | #   of freezing each of them separately, you might consider writing | 
					
						
							|  |  |  | #   a tiny main script that looks at sys.argv[0] and then imports | 
					
						
							|  |  |  | #   the corresponding module.  You can then make links to the | 
					
						
							|  |  |  | #   frozen binary named after the various scripts you support. | 
					
						
							|  |  |  | #   Pass the additional scripts as arguments after the main script. | 
					
						
							|  |  |  | #   A minimal script to do this is the following. | 
					
						
							|  |  |  | #       import sys, posixpath | 
					
						
							|  |  |  | #       exec('import ' + posixpath.basename(sys.argv[0]) + '\n') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import regex | 
					
						
							|  |  |  | import getopt | 
					
						
							|  |  |  | import regsub | 
					
						
							|  |  |  | import string | 
					
						
							|  |  |  | import marshal | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Function to join two pathnames with a slash in between | 
					
						
							|  |  |  | j = os.path.join | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ################################## | 
					
						
							|  |  |  | # START OF CONFIGURATION SECTION # | 
					
						
							|  |  |  | ################################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Attempt to guess machine architecture | 
					
						
							|  |  |  | if os.path.exists('/usr/lib/libgl_s'): ARCH = 'sgi' | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | elif os.path.exists('/etc/issue'): ARCH = 'sequent' | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | else: ARCH = 'sun4' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Site parametrizations (change to match your site) | 
					
						
							|  |  |  | CC = 'cc'				# C compiler | 
					
						
							|  |  |  | TOP = '/ufs/guido/src'			# Parent of all source trees | 
					
						
							|  |  |  | PYTHON = j(TOP, 'python')		# Top of the Python source tree | 
					
						
							|  |  |  | SRC = j(PYTHON, 'src')			# Python source directory | 
					
						
							|  |  |  | BLD = j(PYTHON, 'build.' + ARCH)	# Python build directory | 
					
						
							|  |  |  | #BLD = SRC				# Use this if you build in SRC | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | LIBINST = '/ufs/guido/src/python/irix4/tmp/lib/python/lib' # installed libraries | 
					
						
							|  |  |  | INCLINST = '/ufs/guido/src/python/irix4/tmp/include/Py' # installed include files | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | # Other packages (change to match your site) | 
					
						
							|  |  |  | DL = j(TOP, 'dl')			# Top of the dl source tree | 
					
						
							|  |  |  | DL_DLD = j(TOP, 'dl-dld')		# The dl-dld source directory | 
					
						
							|  |  |  | DLD = j(TOP, 'dld-3.2.3')		# The dld source directory | 
					
						
							|  |  |  | FORMS = j(TOP, 'forms')			# Top of the FORMS source tree | 
					
						
							|  |  |  | STDWIN = j(TOP, 'stdwin')		# Top of the STDWIN source tree | 
					
						
							|  |  |  | READLINE = j(TOP, 'readline.' + ARCH)	# Top of the GNU Readline source tree | 
					
						
							|  |  |  | SUN_X11 = '/usr/local/X11R5/lib/libX11.a' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # File names (usually no need to change) | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | LIBP = [				# Main Python libraries | 
					
						
							|  |  |  |         j(LIBINST, 'libPython.a'), | 
					
						
							|  |  |  |         j(LIBINST, 'libParser.a'), | 
					
						
							|  |  |  |         j(LIBINST, 'libObjects.a'), | 
					
						
							|  |  |  |         j(LIBINST, 'libModules.a') | 
					
						
							|  |  |  |        ] | 
					
						
							|  |  |  | CONFIG_IN = j(LIBINST, 'config.c.in')	# Configuration source file | 
					
						
							|  |  |  | FMAIN = j(LIBINST, 'frozenmain.c')	# Special main source file | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Libraries needed when linking.  First tuple item is built-in module | 
					
						
							|  |  |  | # for which it is needed (or '*' for always), rest are ld arguments. | 
					
						
							|  |  |  | # There is a separate list per architecture. | 
					
						
							|  |  |  | libdeps_sgi = [ \ | 
					
						
							|  |  |  | 	  ('stdwin',	j(STDWIN, 'Build/' + ARCH + '/x11/lib/lib.a')), \ | 
					
						
							|  |  |  | 	  ('fl',	j(FORMS, 'FORMS/libforms.a'), '-lfm_s'), \ | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 	  ('*',		j(READLINE, 'libreadline.a'), '-ltermcap'), \ | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	  ('al',	'-laudio'), \ | 
					
						
							|  |  |  | 	  ('sv',	'-lsvideo', '-lXext'), \ | 
					
						
							|  |  |  | 	  ('cd',	'-lcdaudio', '-lds'), \ | 
					
						
							|  |  |  | 	  ('cl',	'-lcl'), \ | 
					
						
							|  |  |  | 	  ('imgfile',	'-limage', '-lgutil', '-lm'), \ | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 	  ('mpz',	'/ufs/guido/src/gmp/libgmp.a'), \ | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 	  ('*',		'-lsun'), \ | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	  ('*',		j(DL, 'libdl.a'), '-lmld'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lmpc'), \ | 
					
						
							|  |  |  | 	  ('fm',	'-lfm_s'), \ | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 	  ('gl',	'-lgl_s', '-lX11_s'), \ | 
					
						
							|  |  |  | 	  ('stdwin',	'-lX11_s'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lm'), \ | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	  ('*',		'-lc_s'), \ | 
					
						
							|  |  |  | 	  ] | 
					
						
							|  |  |  | libdeps_sun4 = [ \ | 
					
						
							|  |  |  | 	  ('*',		'-Bstatic'), \ | 
					
						
							|  |  |  | 	  ('stdwin',	j(STDWIN, 'Build/' + ARCH + '/x11/lib/lib.a')), \ | 
					
						
							|  |  |  | 	  ('*',		j(READLINE, 'libreadline.a')), \ | 
					
						
							|  |  |  | 	  ('*',		'-lm'), \ | 
					
						
							|  |  |  | 	  ('*',		j(DL_DLD,'libdl.a'), j(DLD,'libdld.a')), \ | 
					
						
							|  |  |  | 	  ('*',		SUN_X11), \ | 
					
						
							|  |  |  | 	  ('*',		'-ltermcap'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lc'), \ | 
					
						
							|  |  |  | 	  ] | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | libdeps_sequent = [ \ | 
					
						
							|  |  |  | 	  ('*',		j(LIBINST, 'libreadline.a'), '-ltermcap'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lsocket'), \ | 
					
						
							|  |  |  | 	  ('*',		'-linet'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lnsl'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lm'), \ | 
					
						
							|  |  |  | 	  ('*',		'-lc'), \ | 
					
						
							|  |  |  | 	  ] | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | libdeps = eval('libdeps_' + ARCH) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ################################ | 
					
						
							|  |  |  | # END OF CONFIGURATION SECTION # | 
					
						
							|  |  |  | ################################ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Exception used when scanfile fails | 
					
						
							|  |  |  | NoSuchFile = 'NoSuchFile' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Global options | 
					
						
							|  |  |  | quiet = 0				# -q | 
					
						
							|  |  |  | verbose = 0				# -v | 
					
						
							|  |  |  | noexec = 0				# -n | 
					
						
							|  |  |  | nowrite = 0				# -N | 
					
						
							|  |  |  | ofile = 'a.out'				# -o file | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Main program -- argument parsing etc. | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  | 	global quiet, verbose, noexec, nowrite, ofile | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		opts, args = getopt.getopt(sys.argv[1:], 'nNo:qv') | 
					
						
							|  |  |  | 	except getopt.error, msg: | 
					
						
							|  |  |  | 		usage(str(msg)) | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 	for o, a in opts: | 
					
						
							|  |  |  | 		if o == '-n': noexec = 1 | 
					
						
							|  |  |  | 		if o == '-N': nowrite = 1 | 
					
						
							|  |  |  | 		if o == '-o': ofile = a | 
					
						
							|  |  |  | 		if o == '-q': verbose = 0; quiet = 1 | 
					
						
							|  |  |  | 		if o == '-v': verbose = verbose + 1; quiet = 0 | 
					
						
							|  |  |  | 	if len(args) < 1: | 
					
						
							|  |  |  | 		usage('please pass at least one file argument') | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 	process(args[0], args[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Print usage message to stderr | 
					
						
							|  |  |  | def usage(*msgs): | 
					
						
							|  |  |  | 	sys.stdout = sys.stderr | 
					
						
							|  |  |  | 	for msg in msgs: print msg | 
					
						
							|  |  |  | 	print 'Usage: freeze [options] scriptfile [modulefile ...]' | 
					
						
							|  |  |  | 	print '-n      : generate the files but don\'t compile and link' | 
					
						
							|  |  |  | 	print '-N      : don\'t write frozen.c (do compile unless -n given)' | 
					
						
							|  |  |  | 	print '-o file : binary output file (default a.out)' | 
					
						
							|  |  |  | 	print '-q      : quiet (no messages at all except errors)' | 
					
						
							|  |  |  | 	print '-v      : verbose (lots of extra messages)' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Process the script file | 
					
						
							|  |  |  | def process(filename, addmodules): | 
					
						
							|  |  |  | 	global noexec | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	if not quiet: print 'Computing needed modules ...' | 
					
						
							|  |  |  | 	todo = {} | 
					
						
							|  |  |  | 	todo['__main__'] = filename | 
					
						
							|  |  |  | 	for name in addmodules: | 
					
						
							|  |  |  | 		mod = os.path.basename(name) | 
					
						
							|  |  |  | 		if mod[-3:] == '.py': mod = mod[:-3] | 
					
						
							|  |  |  | 		todo[mod] = name | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		dict = closure(todo) | 
					
						
							|  |  |  | 	except NoSuchFile, filename: | 
					
						
							|  |  |  | 		sys.stderr.write('Can\'t open file %s\n' % filename) | 
					
						
							|  |  |  | 		sys.exit(1) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	mods = dict.keys() | 
					
						
							|  |  |  | 	mods.sort() | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	if verbose: | 
					
						
							|  |  |  | 		print '%-15s %s' % ('Module', 'Filename') | 
					
						
							|  |  |  | 		for mod in mods: | 
					
						
							|  |  |  | 			print '%-15s %s' % (`mod`, dict[mod]) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	if not quiet: print 'Looking for dynamically linked modules ...' | 
					
						
							|  |  |  | 	dlmodules = [] | 
					
						
							|  |  |  | 	objs = [] | 
					
						
							|  |  |  | 	libs = [] | 
					
						
							|  |  |  | 	for mod in mods: | 
					
						
							|  |  |  | 		if dict[mod][-2:] == '.o': | 
					
						
							|  |  |  | 			if verbose: print 'Found', mod, dict[mod] | 
					
						
							|  |  |  | 			dlmodules.append(mod) | 
					
						
							|  |  |  | 			objs.append(dict[mod]) | 
					
						
							|  |  |  | 			libsname = dict[mod][:-2] + '.libs' | 
					
						
							|  |  |  | 			try: | 
					
						
							|  |  |  | 				f = open(libsname, 'r') | 
					
						
							|  |  |  | 			except IOError: | 
					
						
							|  |  |  | 				f = None | 
					
						
							|  |  |  | 			if f: | 
					
						
							|  |  |  | 				libtext = f.read() | 
					
						
							|  |  |  | 				f.close() | 
					
						
							|  |  |  | 				for lib in string.split(libtext): | 
					
						
							|  |  |  | 					if lib in libs: libs.remove(lib) | 
					
						
							|  |  |  | 					libs.append(lib) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	if not nowrite: | 
					
						
							|  |  |  | 		if not quiet: print 'Writing frozen.c ...' | 
					
						
							|  |  |  | 		writefrozen('frozen.c', dict) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		if not quiet: print 'NOT writing frozen.c ...' | 
					
						
							|  |  |  | 	# | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | ##	if not dlmodules: | 
					
						
							|  |  |  | 	if 0: | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 		config = CONFIG | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 		if not quiet: print 'Using existing', config, '...' | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	else: | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 		config = 'tmpconfig.c' | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 		if nowrite: | 
					
						
							|  |  |  | 			if not quiet: print 'NOT writing config.c ...' | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			if not quiet: | 
					
						
							|  |  |  | 				print 'Writing config.c with dl modules ...' | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 			f = open(CONFIG_IN, 'r') | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 			g = open(config, 'w') | 
					
						
							|  |  |  | 			m1 = regex.compile('-- ADDMODULE MARKER 1 --') | 
					
						
							|  |  |  | 			m2 = regex.compile('-- ADDMODULE MARKER 2 --') | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 			builtinmodules = [] | 
					
						
							|  |  |  | 			stdmodules = ('sys', '__main__', '__builtin__', | 
					
						
							|  |  |  | 				      'marshal') | 
					
						
							|  |  |  | 			todomodules = builtinmodules + dlmodules | 
					
						
							|  |  |  | 			for mod in dict.keys(): | 
					
						
							|  |  |  | 				if dict[mod] == '<builtin>' and \ | 
					
						
							|  |  |  | 					  mod not in stdmodules: | 
					
						
							|  |  |  | 					builtinmodules.append(mod) | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 			while 1: | 
					
						
							|  |  |  | 				line = f.readline() | 
					
						
							|  |  |  | 				if not line: break | 
					
						
							|  |  |  | 				g.write(line) | 
					
						
							|  |  |  | 				if m1.search(line) >= 0: | 
					
						
							|  |  |  | 					if verbose: print 'Marker 1 ...' | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 					for mod in todomodules: | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 						g.write('extern void init' + \ | 
					
						
							|  |  |  | 						  mod + '();\n') | 
					
						
							|  |  |  | 				if m2.search(line) >= 0: | 
					
						
							|  |  |  | 					if verbose: print 'Marker 2 ...' | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 					for mod in todomodules: | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 						g.write('{"' + mod + \ | 
					
						
							|  |  |  | 						  '", init' + mod + '},\n') | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 			g.close() | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	# | 
					
						
							| 
									
										
										
										
											1993-06-05 18:03:53 +00:00
										 |  |  | 	if not quiet: | 
					
						
							|  |  |  | 		if noexec: print 'Generating compilation commands ...' | 
					
						
							|  |  |  | 		else: print 'Starting compilation ...' | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 	defs = ['-DNO_MAIN', '-DUSE_FROZEN', '-DPYTHONPATH=\'"."\''] | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	# | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 	incs = ['-I.', '-I' + INCLINST] | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	if dict.has_key('stdwin'): | 
					
						
							|  |  |  | 		incs.append('-I' + j(STDWIN, 'H')) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	srcs = [config, FMAIN] | 
					
						
							|  |  |  | 	# | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 	if type(LIBP) == type(''): | 
					
						
							|  |  |  | 		libs.append(LIBP) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		for lib in LIBP: | 
					
						
							|  |  |  | 			libs.append(lib) | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	for item in libdeps: | 
					
						
							|  |  |  | 		m = item[0] | 
					
						
							|  |  |  | 		if m == '*' or dict.has_key(m): | 
					
						
							|  |  |  | 			for l in item[1:]: | 
					
						
							|  |  |  | 				if l in libs: libs.remove(l) | 
					
						
							|  |  |  | 				libs.append(l) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	sts = 0 | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	cmd = CC + ' -c' | 
					
						
							|  |  |  | 	cmd = cmd + ' ' + string.join(defs) | 
					
						
							|  |  |  | 	cmd = cmd + ' ' + string.join(incs) | 
					
						
							|  |  |  | 	cmd = cmd + ' ' + string.join(srcs) | 
					
						
							|  |  |  | 	print cmd | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	if not noexec: | 
					
						
							|  |  |  | 		sts = os.system(cmd) | 
					
						
							|  |  |  | 		if sts: | 
					
						
							|  |  |  | 			print 'Exit status', sts, '-- turning on -n' | 
					
						
							|  |  |  | 			noexec = 1 | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	for s in srcs: | 
					
						
							|  |  |  | 		s = os.path.basename(s) | 
					
						
							|  |  |  | 		if s[-2:] == '.c': s = s[:-2] | 
					
						
							|  |  |  | 		o = s + '.o' | 
					
						
							|  |  |  | 		objs.insert(0, o) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	cmd = CC | 
					
						
							|  |  |  | 	cmd = cmd + ' ' + string.join(objs) | 
					
						
							|  |  |  | 	cmd = cmd + ' ' + string.join(libs) | 
					
						
							|  |  |  | 	cmd = cmd + ' -o ' + ofile | 
					
						
							|  |  |  | 	print cmd | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	if not noexec: | 
					
						
							|  |  |  | 		sts = os.system(cmd) | 
					
						
							|  |  |  | 		if sts: | 
					
						
							|  |  |  | 			print 'Exit status', sts | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			print 'Done.' | 
					
						
							|  |  |  | 	# | 
					
						
							| 
									
										
										
										
											1994-01-07 10:55:55 +00:00
										 |  |  | 	if not quiet and not noexec and sts == 0: | 
					
						
							|  |  |  | 		print 'Note: consider this:'; print '\tstrip', ofile | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 	# | 
					
						
							|  |  |  | 	sys.exit(sts) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Generate code for a given module | 
					
						
							|  |  |  | def makecode(filename): | 
					
						
							|  |  |  | 	if filename[-2:] == '.o': | 
					
						
							|  |  |  | 		return None | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		f = open(filename, 'r') | 
					
						
							|  |  |  | 	except IOError: | 
					
						
							|  |  |  | 		return None | 
					
						
							|  |  |  | 	if verbose: print 'Making code from', filename, '...' | 
					
						
							|  |  |  | 	text = f.read() | 
					
						
							|  |  |  | 	code = compile(text, filename, 'exec') | 
					
						
							|  |  |  | 	f.close() | 
					
						
							|  |  |  | 	return marshal.dumps(code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Write the C source file containing the frozen Python code | 
					
						
							|  |  |  | def writefrozen(filename, dict): | 
					
						
							|  |  |  | 	f = open(filename, 'w') | 
					
						
							|  |  |  | 	codelist = [] | 
					
						
							|  |  |  | 	for mod in dict.keys(): | 
					
						
							|  |  |  | 		codestring = makecode(dict[mod]) | 
					
						
							|  |  |  | 		if codestring is not None: | 
					
						
							|  |  |  | 			codelist.append((mod, codestring)) | 
					
						
							|  |  |  | 	write = sys.stdout.write | 
					
						
							|  |  |  | 	save_stdout = sys.stdout | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		sys.stdout = f | 
					
						
							|  |  |  | 		for mod, codestring in codelist: | 
					
						
							|  |  |  | 			if verbose: | 
					
						
							|  |  |  | 				write('Writing initializer for %s\n'%mod) | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 			print 'static unsigned char M_' + mod + '[' + \ | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 				  str(len(codestring)) + '+1] = {' | 
					
						
							|  |  |  | 			for i in range(0, len(codestring), 16): | 
					
						
							|  |  |  | 				for c in codestring[i:i+16]: | 
					
						
							|  |  |  | 					print str(ord(c)) + ',', | 
					
						
							|  |  |  | 				print | 
					
						
							|  |  |  | 			print '};' | 
					
						
							|  |  |  | 		print 'struct frozen {' | 
					
						
							|  |  |  | 		print '  char *name;' | 
					
						
							| 
									
										
										
										
											1994-04-14 19:35:47 +00:00
										 |  |  | 		print '  unsigned char *code;' | 
					
						
							| 
									
										
										
										
											1993-04-01 20:45:45 +00:00
										 |  |  | 		print '  int size;' | 
					
						
							|  |  |  | 		print '} frozen_modules[] = {' | 
					
						
							|  |  |  | 		for mod, codestring in codelist: | 
					
						
							|  |  |  | 			print '  {"' + mod + '",', | 
					
						
							|  |  |  | 			print 'M_' + mod + ',', | 
					
						
							|  |  |  | 			print str(len(codestring)) + '},' | 
					
						
							|  |  |  | 		print '  {0, 0, 0} /* sentinel */' | 
					
						
							|  |  |  | 		print '};' | 
					
						
							|  |  |  | 	finally: | 
					
						
							|  |  |  | 		sys.stdout = save_stdout | 
					
						
							|  |  |  | 	f.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Determine the names and filenames of the modules imported by the | 
					
						
							|  |  |  | # script, recursively.  This is done by scanning for lines containing | 
					
						
							|  |  |  | # import statements.  (The scanning has only superficial knowledge of | 
					
						
							|  |  |  | # Python syntax and no knowledge of semantics, so in theory the result | 
					
						
							|  |  |  | # may be incorrect -- however this is quite unlikely if you don't | 
					
						
							|  |  |  | # intentionally obscure your Python code.) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Compute the closure of scanfile() -- special first file because of script | 
					
						
							|  |  |  | def closure(todo): | 
					
						
							|  |  |  | 	done = {} | 
					
						
							|  |  |  | 	while todo: | 
					
						
							|  |  |  | 		newtodo = {} | 
					
						
							|  |  |  | 		for modname in todo.keys(): | 
					
						
							|  |  |  | 			if not done.has_key(modname): | 
					
						
							|  |  |  | 				filename = todo[modname] | 
					
						
							|  |  |  | 				if filename is None: | 
					
						
							|  |  |  | 					filename = findmodule(modname) | 
					
						
							|  |  |  | 				done[modname] = filename | 
					
						
							|  |  |  | 				if filename in ('<builtin>', '<unknown>'): | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				modules = scanfile(filename) | 
					
						
							|  |  |  | 				for m in modules: | 
					
						
							|  |  |  | 					if not done.has_key(m): | 
					
						
							|  |  |  | 						newtodo[m] = None | 
					
						
							|  |  |  | 		todo = newtodo | 
					
						
							|  |  |  | 	return done | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Scan a file looking for import statements | 
					
						
							|  |  |  | importstr = '\(^\|:\)[ \t]*import[ \t]+\([a-zA-Z0-9_, \t]+\)' | 
					
						
							|  |  |  | fromstr   = '\(^\|:\)[ \t]*from[ \t]+\([a-zA-Z0-9_]+\)[ \t]+import[ \t]+' | 
					
						
							|  |  |  | isimport = regex.compile(importstr) | 
					
						
							|  |  |  | isfrom = regex.compile(fromstr) | 
					
						
							|  |  |  | def scanfile(filename): | 
					
						
							|  |  |  | 	allmodules = {} | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		f = open(filename, 'r') | 
					
						
							|  |  |  | 	except IOError, msg: | 
					
						
							|  |  |  | 		raise NoSuchFile, filename | 
					
						
							|  |  |  | 	while 1: | 
					
						
							|  |  |  | 		line = f.readline() | 
					
						
							|  |  |  | 		if not line: break # EOF | 
					
						
							|  |  |  | 		while line[-2:] == '\\\n': # Continuation line | 
					
						
							|  |  |  | 			line = line[:-2] + ' ' | 
					
						
							|  |  |  | 			line = line + f.readline() | 
					
						
							|  |  |  | 		if isimport.search(line) >= 0: | 
					
						
							|  |  |  | 			rawmodules = isimport.group(2) | 
					
						
							|  |  |  | 			modules = string.splitfields(rawmodules, ',') | 
					
						
							|  |  |  | 			for i in range(len(modules)): | 
					
						
							|  |  |  | 				modules[i] = string.strip(modules[i]) | 
					
						
							|  |  |  | 		elif isfrom.search(line) >= 0: | 
					
						
							|  |  |  | 			modules = [isfrom.group(2)] | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		for mod in modules: | 
					
						
							|  |  |  | 			allmodules[mod] = None | 
					
						
							|  |  |  | 	f.close() | 
					
						
							|  |  |  | 	return allmodules.keys() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Find the file containing a module, given its name; None if not found | 
					
						
							|  |  |  | builtins = sys.builtin_module_names + ['sys'] | 
					
						
							|  |  |  | def findmodule(modname): | 
					
						
							|  |  |  | 	if modname in builtins: return '<builtin>' | 
					
						
							|  |  |  | 	for dirname in sys.path: | 
					
						
							|  |  |  | 		dlfullname = os.path.join(dirname, modname + 'module.o') | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			f = open(dlfullname, 'r') | 
					
						
							|  |  |  | 		except IOError: | 
					
						
							|  |  |  | 			f = None | 
					
						
							|  |  |  | 		if f: | 
					
						
							|  |  |  | 			f.close() | 
					
						
							|  |  |  | 			return dlfullname | 
					
						
							|  |  |  | 		fullname = os.path.join(dirname, modname + '.py') | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			f = open(fullname, 'r') | 
					
						
							|  |  |  | 		except IOError: | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		f.close() | 
					
						
							|  |  |  | 		return fullname | 
					
						
							|  |  |  | 	if not quiet: | 
					
						
							|  |  |  | 		sys.stderr.write('Warning: module %s not found\n' % modname) | 
					
						
							|  |  |  | 	return '<unknown>' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Call the main program | 
					
						
							|  |  |  | main() |