From 61ab941edbfbaf979fcde36807c01d259d629abf Mon Sep 17 00:00:00 2001 From: Frederick Lee Date: Sat, 30 Nov 2002 05:43:14 +0000 Subject: [PATCH] Autotools-specific freeze_ac.py and makemakefile_ac.py. Original makemakefile.py reverted for sake of original build system. Makefile.am modified accordingly. --- intern/python/freeze/freeze_ac.py | 461 ++++++++++++++++++++++++ intern/python/freeze/makemakefile.py | 7 +- intern/python/freeze/makemakefile_ac.py | 56 +++ 3 files changed, 520 insertions(+), 4 deletions(-) create mode 100755 intern/python/freeze/freeze_ac.py create mode 100644 intern/python/freeze/makemakefile_ac.py diff --git a/intern/python/freeze/freeze_ac.py b/intern/python/freeze/freeze_ac.py new file mode 100755 index 00000000000..c714cf1ae69 --- /dev/null +++ b/intern/python/freeze/freeze_ac.py @@ -0,0 +1,461 @@ +#! /usr/bin/env python + +# changes made by strubi@blender.nl + +"""Freeze a Python script into a binary. + +usage: freeze [options...] script [module]... + +Options: +-p prefix: This is the prefix used when you ran ``make install'' + in the Python build directory. + (If you never ran this, freeze won't work.) + The default is whatever sys.prefix evaluates to. + It can also be the top directory of the Python source + tree; then -P must point to the build tree. + +-P exec_prefix: Like -p but this is the 'exec_prefix', used to + install objects etc. The default is whatever sys.exec_prefix + evaluates to, or the -p argument if given. + If -p points to the Python source tree, -P must point + to the build tree, if different. + +-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. + On Windows, the name of a .INI file describing one + or more extensions is passed. + More than one -e option may be given. + +-o dir: Directory where the output files are created; default '.'. + +-m: Additional arguments are module names instead of filenames. + +-a package=dir: Additional directories to be added to the package's + __path__. Used to simulate directories added by the + package at runtime (eg, by OpenGL and win32com). + More than one -a option may be given for each package. + +-l file: Pass the file to the linker (windows only) + +-d: Debugging mode for the module finder. + +-q: Make the module finder totally quiet. + +-h: Print this help message. + +-x module Exclude the specified module. + +-i filename: Include a file with additional command line options. Used + to prevent command lines growing beyond the capabilities of + the shell/OS. All arguments specified in filename + are read and the -i option replaced with the parsed + params (note - quoting args in this file is NOT supported) + +-s subsystem: Specify the subsystem (For Windows only.); + 'console' (default), 'windows', 'service' or 'com_dll' + +-w: Toggle Windows (NT or 95) behavior. + (For debugging only -- on a win32 platform, win32 behavior + is automatic.) + +Arguments: + +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. If -m is specified, these are + module names that are search in the path instead. + +NOTES: + +In order to use freeze successfully, you must have built Python and +installed it ("make install"). + +The script should not use modules provided only as shared libraries; +if it does, the resulting binary is not self-contained. +""" + + +# Import standard modules + +import getopt +import os +import string +import sys + + +# Import the freeze-private modules + +import checkextensions +import modulefinder +import makeconfig +import makefreeze +import makemakefile_ac as makemakefile +import parsesetup +import bkfile + + +# Main program + +def main(): + # overridable context + prefix = None # settable with -p option + exec_prefix = None # settable with -P option + extensions = [] + exclude = [] # settable with -x option + addn_link = [] # settable with -l, but only honored under Windows. + path = sys.path[:] + modargs = 0 + debug = 1 + odir = '' + win = sys.platform[:3] == 'win' + + # default the exclude list for each platform + if win: exclude = exclude + [ + 'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix', 'os2', 'ce'] + + # modules that are imported by the Python runtime + #implicits = ["site", "exceptions"] + implicits = ["exceptions"] + + # output files + frozen_c = 'frozen.c' + config_c = 'config.c' + target = 'a.out' # normally derived from script name + makefile = 'Makefile' + subsystem = 'console' + + # 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! + 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) ) + # 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. + pos = pos + 1 + + # Now parse the command line with the extras inserted. + try: + opts, args = getopt.getopt(sys.argv[1:], 'a:de:hmo:p:P:I:qs:wx:l:') + except getopt.error, msg: + usage('getopt error: ' + str(msg)) + + # proces option arguments + for o, a in opts: + if o == '-h': + print __doc__ + return + if o == '-d': + debug = debug + 1 + if o == '-e': + extensions.append(a) + if o == '-I': # include path + path.append(a) + if o == '-m': + modargs = 1 + if o == '-o': + odir = a + if o == '-p': + prefix = a + if o == '-P': + exec_prefix = a + if o == '-q': + debug = 0 + if o == '-w': + win = not win + if o == '-s': + if not win: + usage("-s subsystem option only on Windows") + subsystem = a + if o == '-x': + exclude.append(a) + if o == '-l': + addn_link.append(a) + if o == '-a': + apply(modulefinder.AddPackagePath, tuple(string.split(a,"=", 2))) + + # default prefix and exec_prefix + if not exec_prefix: + if prefix: + exec_prefix = prefix + else: + exec_prefix = sys.exec_prefix + if not prefix: + prefix = sys.prefix + + # determine whether -p points to the Python source tree + ishome = os.path.exists(os.path.join(prefix, 'Python', 'ceval.c')) + + # locations derived from options + version = sys.version[:3] + if win: + extensions_c = 'frozen_extensions.c' + if ishome: + print "(Using Python source directory)" + binlib = exec_prefix + incldir = os.path.join(prefix, 'Include') + config_h_dir = exec_prefix + config_c_in = os.path.join(prefix, 'Modules', 'config.c.in') + frozenmain_c = os.path.join(prefix, 'Python', 'frozenmain.c') + makefile_in = os.path.join(exec_prefix, 'Modules', 'Makefile') + if win: + frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c') + else: + binlib = os.path.join(exec_prefix, + 'lib', 'python%s' % version, 'config') + incldir = os.path.join(prefix, 'include', 'python%s' % version) + config_h_dir = os.path.join(exec_prefix, 'include', + 'python%s' % version) + 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') + frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c') + supp_sources = [] + defines = [] + includes = ['-I' + incldir, '-I' + config_h_dir] + + # 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. + for dir in check_dirs: + if not os.path.exists(dir): + usage('needed directory %s not found' % dir) + if not os.path.isdir(dir): + usage('%s: not a directory' % dir) + if win: + files = supp_sources + extensions # extensions are files on Windows. + else: + files = [config_c_in, makefile_in] + supp_sources + for file in supp_sources: + 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) + if not win: + 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') + + # check that file arguments exist + for arg in args: + if arg == '-m': + break + # if user specified -m on the command line before _any_ + # file names, then nothing should be checked (as the + # very first file should be a module name) + if modargs: + break + 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 + else: + target = base + '.bin' + + # handle -o option + base_frozen_c = frozen_c + base_config_c = config_c + base_target = target + if odir and not os.path.isdir(odir): + try: + os.mkdir(odir) + print "Created output directory", odir + except os.error, msg: + usage('%s: mkdir failed (%s)' % (odir, str(msg))) + base = '' + if odir: + base = os.path.join(odir, '') + frozen_c = os.path.join(odir, frozen_c) + config_c = os.path.join(odir, config_c) + target = os.path.join(odir, target) + makefile = os.path.join(odir, makefile) + if win: extensions_c = os.path.join(odir, extensions_c) + + # Handle special entry point requirements + # (on Windows, some frozen programs do not use __main__, but + # import the module directly. Eg, DLLs, Services, etc + custom_entry_point = None # Currently only used on Windows + python_entry_is_main = 1 # Is the entry point called __main__? + # handle -s option on Windows + if win: + import winmakemakefile + try: + custom_entry_point, python_entry_is_main = \ + winmakemakefile.get_custom_entry_point(subsystem) + except ValueError, why: + usage(why) + + + # Actual work starts here... + + # collect all modules of the program + dir = os.path.dirname(scriptfile) + path[0] = dir + mf = modulefinder.ModuleFinder(path, debug, exclude) + + if win and subsystem=='service': + # If a Windows service, then add the "built-in" module. + mod = mf.add_module("servicemanager") + mod.__file__="dummy.pyd" # really built-in to the resulting EXE + + for mod in implicits: + mf.import_hook(mod) + for mod in modules: + if mod == '-m': + modargs = 1 + continue + if modargs: + if mod[-2:] == '.*': + mf.import_hook(mod[:-2], None, ["*"]) + else: + mf.import_hook(mod) + else: + mf.load_file(mod) + + # Add the main script as either __main__, or the actual module name. + if python_entry_is_main: + mf.run_script(scriptfile) + else: + mf.load_file(scriptfile) + + if debug > 0: + mf.report() + print + dict = mf.modules + + # generate output for frozen modules + files = makefreeze.makefreeze(base, dict, debug, custom_entry_point, 1) + # look for unfrozen modules (builtin and of unknown origin) + builtins = [] + unknown = [] + mods = dict.keys() + mods.sort() + for mod in mods: + if dict[mod].__code__: + continue + if not dict[mod].__file__: + builtins.append(mod) + else: + unknown.append(mod) + + # search for unknown modules in extensions directories (not on Windows) + addfiles = [] + frozen_extensions = [] # Windows list of modules. + if unknown or (not win and builtins): + if not win: + addfiles, addmods = \ + checkextensions.checkextensions(unknown+builtins, + extensions) + for mod in addmods: + if mod in unknown: + unknown.remove(mod) + builtins.append(mod) + else: + # Do the windows thang... + import checkextensions_win32 + # Get a list of CExtension instances, each describing a module + # (including its source files) + frozen_extensions = checkextensions_win32.checkextensions( + unknown, extensions, prefix) + for mod in frozen_extensions: + unknown.remove(mod.name) + + # report unknown modules + if unknown: + sys.stderr.write('Warning: unknown modules remain: %s\n' % + string.join(unknown)) + + # windows gets different treatment + if win: + # Taking a shortcut here... + import winmakemakefile, checkextensions_win32 + checkextensions_win32.write_extension_table(extensions_c, + frozen_extensions) + # Create a module definition for the bootstrap C code. + xtras = [frozenmain_c, os.path.basename(frozen_c), + frozendllmain_c, os.path.basename(extensions_c)] + files + maindefn = checkextensions_win32.CExtension( '__main__', xtras ) + frozen_extensions.append( maindefn ) + outfp = open(makefile, 'w') + try: + winmakemakefile.makemakefile(outfp, + locals(), + frozen_extensions, + os.path.basename(target)) + finally: + outfp.close() + return + + # generate config.c and Makefile + builtins.sort() + infp = open(config_c_in) + outfp = bkfile.open(config_c, 'w') + try: + makeconfig.makeconfig(infp, outfp, builtins) + finally: + outfp.close() + infp.close() + + cflags = defines + includes + ['$(OPT)'] + libs = [os.path.join(binlib, 'libpython$(VERSION).a')] + + somevars = {} + if os.path.exists(makefile_in): + makevars = parsesetup.getmakevars(makefile_in) + for key in makevars.keys(): + somevars[key] = makevars[key] + + somevars['CFLAGS'] = string.join(cflags) # override + files = ['$(OPT)', '$(LDFLAGS)', base_config_c, base_frozen_c] + \ + files + supp_sources + addfiles + libs + \ + ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)'] + + outfp = bkfile.open(makefile, 'w') + try: + makemakefile.makemakefile(outfp, somevars, files, base_target) + finally: + outfp.close() + + # Done! + + if odir: + print 'Now run "make" in', odir, + print 'to build the target:', base_target + else: + print 'Now run "make" to build the target:', base_target + + +# Print usage message and exit + +def usage(msg): + sys.stdout = sys.stderr + print "Error:", msg + print "Use ``%s -h'' for help" % sys.argv[0] + sys.exit(2) + + +main() diff --git a/intern/python/freeze/makemakefile.py b/intern/python/freeze/makemakefile.py index ab57b08d01e..64a98992ae8 100644 --- a/intern/python/freeze/makemakefile.py +++ b/intern/python/freeze/makemakefile.py @@ -25,7 +25,7 @@ def makemakefile(outfp, makevars, files, target): for key in keys: outfp.write("%s=%s\n" % (key, makevars[key])) -# outfp.write("\n\ninclude nan_definitions.mk\n") + outfp.write("\n\ninclude nan_definitions.mk\n") outfp.write("\nall: %s\n\n" % libtarget) deps = [] @@ -50,9 +50,8 @@ def makemakefile(outfp, makevars, files, target): # libfiles.remove('M___main__.o') # don't link with __main__ outfp.write("\n%s: $(OBJS)\n" % (libtarget)) -# outfp.write("\t$(AR) ruv %s%s $(OBJS)\n" % -# ("$(OCGDIR)/blender/bpython/$(DEBUG_DIR)", targetlib)) - outfp.write("\t$(AR) ruv %s $(OBJS)\n" % targetlib) + outfp.write("\t$(AR) ruv %s%s $(OBJS)\n" % + ("$(OCGDIR)/blender/bpython/$(DEBUG_DIR)", targetlib)) outfp.write("\n%s: %s $(OBJS)\n" % (target, mainfile)) outfp.write("\t$(CC) %s %s -o %s $(LDLAST)\n" % diff --git a/intern/python/freeze/makemakefile_ac.py b/intern/python/freeze/makemakefile_ac.py new file mode 100644 index 00000000000..13859aaf86d --- /dev/null +++ b/intern/python/freeze/makemakefile_ac.py @@ -0,0 +1,56 @@ +# Write the actual Makefile. +## +## Modified makemakefile for autotools Blender build +## + + +import os +import string + +def makemakefile(outfp, makevars, files, target): + outfp.write("# Makefile generated by freeze.py script\n\n") + + target = "frozen" + libtarget = "lib" + target + targetlib = libtarget + ".a" + #targetlib = "libpyfrozen.a" + + keys = makevars.keys() + keys.sort() + for key in keys: + outfp.write("%s=%s\n" % (key, makevars[key])) + +# outfp.write("\n\ninclude nan_definitions.mk\n") + outfp.write("\nall: %s\n\n" % libtarget) + + deps = [] + for i in range(len(files)): + file = files[i] + if file[-2:] == '.c': + base = os.path.basename(file) + dest = base[:-2] + '.o' + # outfp.write("%s: %s\n" % (dest, file)) + # outfp.write("\t$(CC) $(CFLAGS) -c %s\n" % file) + files[i] = dest + deps.append(dest) + + mainfile = 'M___main__.o' + + try: + deps.remove(mainfile) + except: + pass + outfp.write("OBJS = %s\n" % string.join(deps)) + +# libfiles.remove('M___main__.o') # don't link with __main__ + + outfp.write("\n%s: $(OBJS)\n" % (libtarget)) +# outfp.write("\t$(AR) ruv %s%s $(OBJS)\n" % +# ("$(OCGDIR)/blender/bpython/$(DEBUG_DIR)", targetlib)) + outfp.write("\t$(AR) ruv %s $(OBJS)\n" % targetlib) + + outfp.write("\n%s: %s $(OBJS)\n" % (target, mainfile)) + outfp.write("\t$(CC) %s %s -o %s $(LDLAST)\n" % + (mainfile, " ".join(deps), target)) + + outfp.write("\nclean:\n\t-rm -f *.o *.a %s\n" % target)