Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/python/freeze')
-rw-r--r--intern/python/freeze/Makefile14
-rw-r--r--intern/python/freeze/README173
-rw-r--r--intern/python/freeze/README.NaN12
-rw-r--r--intern/python/freeze/bkfile.py47
-rw-r--r--intern/python/freeze/checkextensions.py91
-rw-r--r--intern/python/freeze/checkextensions_win32.py190
-rwxr-xr-xintern/python/freeze/freeze.py461
-rw-r--r--intern/python/freeze/hello.py1
-rw-r--r--intern/python/freeze/makeconfig.py61
-rw-r--r--intern/python/freeze/makefreeze.py115
-rw-r--r--intern/python/freeze/makemakefile.py57
-rw-r--r--intern/python/freeze/modulefinder.py444
-rw-r--r--intern/python/freeze/parsesetup.py98
-rw-r--r--intern/python/freeze/winmakemakefile.py146
14 files changed, 1910 insertions, 0 deletions
diff --git a/intern/python/freeze/Makefile b/intern/python/freeze/Makefile
new file mode 100644
index 00000000000..3c344029b3e
--- /dev/null
+++ b/intern/python/freeze/Makefile
@@ -0,0 +1,14 @@
+# $Id$
+# This is the makefile for the bytecode freezing of all modules which
+# the main file depends on (last argument in importer rule)
+
+SRCDIR = ../modules
+
+TARGETDIR = ../../../source/blender/bpython/frozen
+
+PYFLAGS = -S -O
+
+default: importer
+
+importer:
+ python $(PYFLAGS) freeze.py -d -x os -x pprint -x Blender -I $(SRCDIR) -o $(TARGETDIR) $(SRCDIR)/VRMLmain.py
diff --git a/intern/python/freeze/README b/intern/python/freeze/README
new file mode 100644
index 00000000000..fcdd67029a5
--- /dev/null
+++ b/intern/python/freeze/README
@@ -0,0 +1,173 @@
+THE FREEZE SCRIPT
+=================
+
+(Directions for Windows are at the end of this file.)
+
+
+What is Freeze?
+---------------
+
+Freeze make it possible to ship arbitrary Python programs to people
+who don't have Python. The shipped file (called a "frozen" version of
+your Python program) is an executable, so this only works if your
+platform is compatible with that on the receiving end (this is usually
+a matter of having the same major operating system revision and CPU
+type).
+
+The shipped file contains a Python interpreter and large portions of
+the Python run-time. Some measures have been taken to avoid linking
+unneeded modules, but the resulting binary is usually not small.
+
+The Python source code of your program (and of the library modules
+written in Python that it uses) is not included in the binary --
+instead, the compiled byte-code (the instruction stream used
+internally by the interpreter) is incorporated. This gives some
+protection of your Python source code, though not much -- a
+disassembler for Python byte-code is available in the standard Python
+library. At least someone running "strings" on your binary won't see
+the source.
+
+
+How does Freeze know which modules to include?
+----------------------------------------------
+
+Previous versions of Freeze used a pretty simple-minded algorithm to
+find the modules that your program uses, essentially searching for
+lines starting with the word "import". It was pretty easy to trick it
+into making mistakes, either missing valid import statements, or
+mistaking string literals (e.g. doc strings) for import statements.
+
+This has been remedied: Freeze now uses the regular Python parser to
+parse the program (and all its modules) and scans the generated byte
+code for IMPORT instructions. It may still be confused -- it will not
+know about calls to the __import__ built-in function, or about import
+statements constructed on the fly and executed using the 'exec'
+statement, and it will consider import statements even when they are
+unreachable (e.g. "if 0: import foobar").
+
+This new version of Freeze also knows about Python's new package
+import mechanism, and uses exactly the same rules to find imported
+modules and packages. One exception: if you write 'from package
+import *', Python will look into the __all__ variable of the package
+to determine which modules are to be imported, while Freeze will do a
+directory listing.
+
+One tricky issue: Freeze assumes that the Python interpreter and
+environment you're using to run Freeze is the same one that would be
+used to run your program, which should also be the same whose sources
+and installed files you will learn about in the next section. In
+particular, your PYTHONPATH setting should be the same as for running
+your program locally. (Tip: if the program doesn't run when you type
+"python hello.py" there's little chance of getting the frozen version
+to run.)
+
+
+How do I use Freeze?
+--------------------
+
+Normally, you should be able to use it as follows:
+
+ python freeze.py hello.py
+
+where hello.py is your program and freeze.py is the main file of
+Freeze (in actuality, you'll probably specify an absolute pathname
+such as /usr/joe/python/Tools/freeze/freeze.py).
+
+
+What do I do next?
+------------------
+
+Freeze creates a number of files: frozen.c, config.c and Makefile,
+plus one file for each Python module that gets included named
+M_<module>.c. To produce the frozen version of your program, you can
+simply type "make". This should produce a binary file. If the
+filename argument to Freeze was "hello.py", the binary will be called
+"hello".
+
+Note: you can use the -o option to freeze to specify an alternative
+directory where these files are created. This makes it easier to
+clean up after you've shipped the frozen binary. You should invoke
+"make" in the given directory.
+
+
+Freezing Tkinter programs
+-------------------------
+
+Unfortunately, it is currently not possible to freeze programs that
+use Tkinter. It *seems* to work, but when you ship the frozen program
+to a site without a Tcl/Tk installation, it will fail with a complaint
+about missing Tcl/Tk initialization files.
+
+A workaround would be possible, in which the Tcl/Tk library files are
+incorporated in a frozen Python module as string literals and written
+to a temporary location when the program runs; this is currently left
+as an exercise for the reader. (If you implement this, please post to
+the Python newsgroup!)
+
+Of course, you can also simply require that Tcl/Tk is required on the
+target installation.
+
+
+A warning against shared library modules
+----------------------------------------
+
+When your Python installation uses shared library modules, these will
+not be incorporated in the frozen program. Again, the frozen program
+will work when you test it, but it won't work when you ship it to a
+site without a Python installation.
+
+Freeze prints a warning when this is the case at the end of the
+freezing process:
+
+ Warning: unknown modules remain: ...
+
+When this occurs, the best thing to do is usually to rebuild Python
+using static linking only.
+
+
+Troubleshooting
+---------------
+
+If you have trouble using Freeze for a large program, it's probably
+best to start playing with a really simple program first (like the file
+hello.py). If you can't get that to work there's something
+fundamentally wrong -- perhaps you haven't installed Python. To do a
+proper install, you should do "make install" in the Python root
+directory.
+
+
+Usage under Windows 95 or NT
+----------------------------
+
+Under Windows 95 or NT, you *must* use the -p option and point it to
+the top of the Python source tree.
+
+WARNING: the resulting executable is not self-contained; it requires
+the Python DLL, currently PYTHON20.DLL (it does not require the
+standard library of .py files though). It may also require one or
+more extension modules loaded from .DLL or .PYD files; the module
+names are printed in the warning message about remaining unknown
+modules.
+
+The driver script generates a Makefile that works with the Microsoft
+command line C compiler (CL). To compile, run "nmake"; this will
+build a target "hello.exe" if the source was "hello.py". Only the
+files frozenmain.c and frozen.c are used; no config.c is generated or
+used, since the standard DLL is used.
+
+In order for this to work, you must have built Python using the VC++
+(Developer Studio) 5.0 compiler. The provided project builds
+python20.lib in the subdirectory pcbuild\Release of thje Python source
+tree, and this is where the generated Makefile expects it to be. If
+this is not the case, you can edit the Makefile or (probably better)
+winmakemakefile.py (e.g., if you are using the 4.2 compiler, the
+python20.lib file is generated in the subdirectory vc40 of the Python
+source tree).
+
+You can freeze programs that use Tkinter, but Tcl/Tk must be installed
+on the target system.
+
+It is possible to create frozen programs that don't have a console
+window, by specifying the option '-s windows'.
+
+--Guido van Rossum (home page: http://www.python.org/~guido/)
diff --git a/intern/python/freeze/README.NaN b/intern/python/freeze/README.NaN
new file mode 100644
index 00000000000..93892543c4f
--- /dev/null
+++ b/intern/python/freeze/README.NaN
@@ -0,0 +1,12 @@
+$Id$
+
+This is a modification of the freeze.py script used to freeze python
+modules as byte code in Blender.
+
+To create this byte code, simply type 'make'. Freeze will then generate
+the C source files in the TARGETDIR (specified in the Makefile), provided
+that you have a valid python installation.
+
+Be warned: testing of the module dependencies is needed, as these are
+resolved AT RUNTIME!
+
diff --git a/intern/python/freeze/bkfile.py b/intern/python/freeze/bkfile.py
new file mode 100644
index 00000000000..d29716a93c9
--- /dev/null
+++ b/intern/python/freeze/bkfile.py
@@ -0,0 +1,47 @@
+_orig_open = open
+
+class _BkFile:
+ def __init__(self, file, mode, bufsize):
+ import os
+ self.__filename = file
+ self.__backup = file + '~'
+ try:
+ os.unlink(self.__backup)
+ except os.error:
+ pass
+ try:
+ os.rename(file, self.__backup)
+ except os.error:
+ self.__backup = None
+ self.__file = _orig_open(file, mode, bufsize)
+ self.closed = self.__file.closed
+ self.fileno = self.__file.fileno
+ self.flush = self.__file.flush
+ self.isatty = self.__file.isatty
+ self.mode = self.__file.mode
+ self.name = self.__file.name
+ self.read = self.__file.read
+ self.readinto = self.__file.readinto
+ self.readline = self.__file.readline
+ self.readlines = self.__file.readlines
+ self.seek = self.__file.seek
+ self.softspace = self.__file.softspace
+ self.tell = self.__file.tell
+ self.truncate = self.__file.truncate
+ self.write = self.__file.write
+ self.writelines = self.__file.writelines
+
+ def close(self):
+ self.__file.close()
+ if self.__backup is None:
+ return
+ import filecmp
+ if filecmp.cmp(self.__backup, self.__filename, shallow = 0):
+ import os
+ os.unlink(self.__filename)
+ os.rename(self.__backup, self.__filename)
+
+def open(file, mode = 'r', bufsize = -1):
+ if 'w' not in mode:
+ return _orig_open(file, mode, bufsize)
+ return _BkFile(file, mode, bufsize)
diff --git a/intern/python/freeze/checkextensions.py b/intern/python/freeze/checkextensions.py
new file mode 100644
index 00000000000..8d597bfae96
--- /dev/null
+++ b/intern/python/freeze/checkextensions.py
@@ -0,0 +1,91 @@
+# Check for a module in a set of extension directories.
+# An extension directory should contain a Setup file
+# and one or more .o files or a lib.a file.
+
+import os
+import string
+import parsesetup
+
+def checkextensions(unknown, extensions):
+ files = []
+ modules = []
+ edict = {}
+ for e in extensions:
+ setup = os.path.join(e, 'Setup')
+ liba = os.path.join(e, 'lib.a')
+ if not os.path.isfile(liba):
+ liba = None
+ edict[e] = parsesetup.getsetupinfo(setup), liba
+ for mod in unknown:
+ for e in extensions:
+ (mods, vars), liba = edict[e]
+ if not mods.has_key(mod):
+ continue
+ modules.append(mod)
+ if liba:
+ # If we find a lib.a, use it, ignore the
+ # .o files, and use *all* libraries for
+ # *all* modules in the Setup file
+ if liba in files:
+ break
+ files.append(liba)
+ for m in mods.keys():
+ files = files + select(e, mods, vars,
+ m, 1)
+ break
+ files = files + select(e, mods, vars, mod, 0)
+ break
+ return files, modules
+
+def select(e, mods, vars, mod, skipofiles):
+ files = []
+ for w in mods[mod]:
+ w = treatword(w)
+ if not w:
+ continue
+ w = expandvars(w, vars)
+ for w in string.split(w):
+ if skipofiles and w[-2:] == '.o':
+ continue
+ # Assume $var expands to absolute pathname
+ if w[0] not in ('-', '$') and w[-2:] in ('.o', '.a'):
+ w = os.path.join(e, w)
+ if w[:2] in ('-L', '-R') and w[2:3] != '$':
+ w = w[:2] + os.path.join(e, w[2:])
+ files.append(w)
+ return files
+
+cc_flags = ['-I', '-D', '-U']
+cc_exts = ['.c', '.C', '.cc', '.c++']
+
+def treatword(w):
+ if w[:2] in cc_flags:
+ return None
+ if w[:1] == '-':
+ return w # Assume loader flag
+ head, tail = os.path.split(w)
+ base, ext = os.path.splitext(tail)
+ if ext in cc_exts:
+ tail = base + '.o'
+ w = os.path.join(head, tail)
+ return w
+
+def expandvars(str, vars):
+ i = 0
+ while i < len(str):
+ i = k = string.find(str, '$', i)
+ if i < 0:
+ break
+ i = i+1
+ var = str[i:i+1]
+ i = i+1
+ if var == '(':
+ j = string.find(str, ')', i)
+ if j < 0:
+ break
+ var = str[i:j]
+ i = j+1
+ if vars.has_key(var):
+ str = str[:k] + vars[var] + str[i:]
+ i = k
+ return str
diff --git a/intern/python/freeze/checkextensions_win32.py b/intern/python/freeze/checkextensions_win32.py
new file mode 100644
index 00000000000..85c3a3c0cdd
--- /dev/null
+++ b/intern/python/freeze/checkextensions_win32.py
@@ -0,0 +1,190 @@
+"""Extension management for Windows.
+
+Under Windows it is unlikely the .obj files are of use, as special compiler options
+are needed (primarily to toggle the behavior of "public" symbols.
+
+I dont consider it worth parsing the MSVC makefiles for compiler options. Even if
+we get it just right, a specific freeze application may have specific compiler
+options anyway (eg, to enable or disable specific functionality)
+
+So my basic stragtegy is:
+
+* Have some Windows INI files which "describe" one or more extension modules.
+ (Freeze comes with a default one for all known modules - but you can specify
+ your own).
+* This description can include:
+ - The MSVC .dsp file for the extension. The .c source file names
+ are extraced from there.
+ - Specific compiler/linker options
+ - Flag to indicate if Unicode compilation is expected.
+
+At the moment the name and location of this INI file is hardcoded,
+but an obvious enhancement would be to provide command line options.
+"""
+
+import os, string, sys
+try:
+ import win32api
+except ImportError:
+ win32api = None # User has already been warned
+
+class CExtension:
+ """An abstraction of an extension implemented in C/C++
+ """
+ def __init__(self, name, sourceFiles):
+ self.name = name
+ # A list of strings defining additional compiler options.
+ self.sourceFiles = sourceFiles
+ # A list of special compiler options to be applied to
+ # all source modules in this extension.
+ self.compilerOptions = []
+ # A list of .lib files the final .EXE will need.
+ self.linkerLibs = []
+
+ def GetSourceFiles(self):
+ return self.sourceFiles
+
+ def AddCompilerOption(self, option):
+ self.compilerOptions.append(option)
+ def GetCompilerOptions(self):
+ return self.compilerOptions
+
+ def AddLinkerLib(self, lib):
+ self.linkerLibs.append(lib)
+ def GetLinkerLibs(self):
+ return self.linkerLibs
+
+def checkextensions(unknown, extra_inis, prefix):
+ # Create a table of frozen extensions
+
+ defaultMapName = os.path.join( os.path.split(sys.argv[0])[0], "extensions_win32.ini")
+ if not os.path.isfile(defaultMapName):
+ sys.stderr.write("WARNING: %s can not be found - standard extensions may not be found" % mapFileName)
+ else:
+ # must go on end, so other inis can override.
+ extra_inis.append(defaultMapName)
+
+ ret = []
+ for mod in unknown:
+ for ini in extra_inis:
+# print "Looking for", mod, "in", win32api.GetFullPathName(ini),"...",
+ defn = get_extension_defn( mod, ini, prefix )
+ if defn is not None:
+# print "Yay - found it!"
+ ret.append( defn )
+ break
+# print "Nope!"
+ else: # For not broken!
+ sys.stderr.write("No definition of module %s in any specified map file.\n" % (mod))
+
+ return ret
+
+def get_extension_defn(moduleName, mapFileName, prefix):
+ if win32api is None: return None
+ os.environ['PYTHONPREFIX'] = prefix
+ dsp = win32api.GetProfileVal(moduleName, "dsp", "", mapFileName)
+ if dsp=="":
+ return None
+
+ # We allow environment variables in the file name
+ dsp = win32api.ExpandEnvironmentStrings(dsp)
+ # If the path to the .DSP file is not absolute, assume it is relative
+ # to the description file.
+ if not os.path.isabs(dsp):
+ dsp = os.path.join( os.path.split(mapFileName)[0], dsp)
+ # Parse it to extract the source files.
+ sourceFiles = parse_dsp(dsp)
+ if sourceFiles is None:
+ return None
+
+ module = CExtension(moduleName, sourceFiles)
+ # Put the path to the DSP into the environment so entries can reference it.
+ os.environ['dsp_path'] = os.path.split(dsp)[0]
+ os.environ['ini_path'] = os.path.split(mapFileName)[0]
+
+ cl_options = win32api.GetProfileVal(moduleName, "cl", "", mapFileName)
+ if cl_options:
+ module.AddCompilerOption(win32api.ExpandEnvironmentStrings(cl_options))
+
+ exclude = win32api.GetProfileVal(moduleName, "exclude", "", mapFileName)
+ exclude = string.split(exclude)
+
+ if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
+ module.AddCompilerOption('/D UNICODE /D _UNICODE')
+
+ libs = string.split(win32api.GetProfileVal(moduleName, "libs", "", mapFileName))
+ for lib in libs:
+ module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))
+
+ for exc in exclude:
+ if exc in module.sourceFiles:
+ modules.sourceFiles.remove(exc)
+
+ return module
+
+# Given an MSVC DSP file, locate C source files it uses
+# returns a list of source files.
+def parse_dsp(dsp):
+# print "Processing", dsp
+ # For now, only support
+ ret = []
+ dsp_path, dsp_name = os.path.split(dsp)
+ try:
+ lines = open(dsp, "r").readlines()
+ except IOError, msg:
+ sys.stderr.write("%s: %s\n" % (dsp, msg))
+ return None
+ for line in lines:
+ fields = string.split(string.strip(line), "=", 2)
+ if fields[0]=="SOURCE":
+ if string.lower(os.path.splitext(fields[1])[1]) in ['.cpp', '.c']:
+ ret.append( win32api.GetFullPathName(os.path.join(dsp_path, fields[1] ) ) )
+ return ret
+
+def write_extension_table(fname, modules):
+ fp = open(fname, "w")
+ try:
+ fp.write (ext_src_header)
+ # Write fn protos
+ for module in modules:
+ # bit of a hack for .pyd's as part of packages.
+ name = string.split(module.name,'.')[-1]
+ fp.write('extern void init%s(void);\n' % (name) )
+ # Write the table
+ fp.write (ext_tab_header)
+ for module in modules:
+ name = string.split(module.name,'.')[-1]
+ fp.write('\t{"%s", init%s},\n' % (name, name) )
+
+ fp.write (ext_tab_footer)
+ fp.write(ext_src_footer)
+ finally:
+ fp.close()
+
+
+ext_src_header = """\
+#include "Python.h"
+"""
+
+ext_tab_header = """\
+
+static struct _inittab extensions[] = {
+"""
+
+ext_tab_footer = """\
+ /* Sentinel */
+ {0, 0}
+};
+"""
+
+ext_src_footer = """\
+extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
+
+int PyInitFrozenExtensions()
+{
+ return PyImport_ExtendInittab(extensions);
+}
+
+"""
+
+
diff --git a/intern/python/freeze/freeze.py b/intern/python/freeze/freeze.py
new file mode 100755
index 00000000000..e6f4ead15d5
--- /dev/null
+++ b/intern/python/freeze/freeze.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
+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.freeze'
+ 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/hello.py b/intern/python/freeze/hello.py
new file mode 100644
index 00000000000..f978acc883c
--- /dev/null
+++ b/intern/python/freeze/hello.py
@@ -0,0 +1 @@
+print 'Hello world...'
diff --git a/intern/python/freeze/makeconfig.py b/intern/python/freeze/makeconfig.py
new file mode 100644
index 00000000000..5d1ba2c333c
--- /dev/null
+++ b/intern/python/freeze/makeconfig.py
@@ -0,0 +1,61 @@
+import regex
+
+
+# Write the config.c file
+
+never = ['marshal', '__main__', '__builtin__', 'sys', 'exceptions']
+
+def makeconfig(infp, outfp, modules, with_ifdef=0):
+ m1 = regex.compile('-- ADDMODULE MARKER 1 --')
+ m2 = regex.compile('-- ADDMODULE MARKER 2 --')
+ while 1:
+ line = infp.readline()
+ if not line: break
+ outfp.write(line)
+ if m1 and m1.search(line) >= 0:
+ m1 = None
+ for mod in modules:
+ if mod in never:
+ continue
+ if with_ifdef:
+ outfp.write("#ifndef init%s\n"%mod)
+ outfp.write('extern void init%s();\n' % mod)
+ if with_ifdef:
+ outfp.write("#endif\n")
+ elif m2 and m2.search(line) >= 0:
+ m2 = None
+ for mod in modules:
+ if mod in never:
+ continue
+ outfp.write('\t{"%s", init%s},\n' %
+ (mod, mod))
+ if m1:
+ sys.stderr.write('MARKER 1 never found\n')
+ elif m2:
+ sys.stderr.write('MARKER 2 never found\n')
+
+
+# Test program.
+
+def test():
+ import sys
+ if not sys.argv[3:]:
+ print 'usage: python makeconfig.py config.c.in outputfile',
+ print 'modulename ...'
+ sys.exit(2)
+ if sys.argv[1] == '-':
+ infp = sys.stdin
+ else:
+ infp = open(sys.argv[1])
+ if sys.argv[2] == '-':
+ outfp = sys.stdout
+ else:
+ outfp = open(sys.argv[2], 'w')
+ makeconfig(infp, outfp, sys.argv[3:])
+ if outfp != sys.stdout:
+ outfp.close()
+ if infp != sys.stdin:
+ infp.close()
+
+if __name__ == '__main__':
+ test()
diff --git a/intern/python/freeze/makefreeze.py b/intern/python/freeze/makefreeze.py
new file mode 100644
index 00000000000..8bd9ce1a2e2
--- /dev/null
+++ b/intern/python/freeze/makefreeze.py
@@ -0,0 +1,115 @@
+##
+##
+## Customized makefreeze for NaN
+##
+##
+## 1.11.2001, strubi@blender.nl
+##
+##
+import marshal
+import string
+import bkfile
+
+
+# Write a file containing frozen code for the modules in the dictionary.
+
+header = """
+#include "Python.h"
+
+static struct _frozen _PyImport_FrozenModules[] = {
+"""
+trailer = """\
+ {0, 0, 0} /* sentinel */
+};
+"""
+
+# if __debug__ == 0 (i.e. -O option given), set Py_OptimizeFlag in frozen app.
+main_entry_point = """
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int Py_FrozenMain(int, char **);
+ init_frozen_modules();
+ return Py_FrozenMain(argc, argv);
+}
+
+"""
+
+default_entry_point = """
+void
+init_frozenmodules(void)
+{
+""" + ((not __debug__ and """
+ Py_OptimizeFlag++;
+""") or "") + """
+ PyImport_FrozenModules = _PyImport_FrozenModules;
+}
+"""
+
+HEADER = """
+/* This is a generated file, containing frozen bytecode.
+ * Check $(HOME)/develop/intern/python/freeze/README for more information.
+ */
+
+"""
+
+def makefreeze(base, dict, debug=0, entry_point = None, exclude_main = 0):
+ if entry_point is None: entry_point = default_entry_point
+ done = []
+ files = []
+ mods = dict.keys()
+ if exclude_main:
+ mods.remove("__main__")
+ mods.sort()
+ for mod in mods:
+ m = dict[mod]
+ mangled = string.join(string.split(mod, "."), "__")
+ if m.__code__:
+ file = 'M_' + mangled + '.c'
+ outfp = bkfile.open(base + file, 'w')
+ outfp.write(HEADER)
+ files.append(file)
+ if debug:
+ print "freezing", mod, "..."
+ str = marshal.dumps(m.__code__)
+ size = len(str)
+ if m.__path__:
+ # Indicate package by negative size
+ size = -size
+ done.append((mod, mangled, size))
+ writecode(outfp, mangled, str)
+ outfp.close()
+ if debug:
+ print "generating table of frozen modules"
+ outfp = bkfile.open(base + 'frozen.c', 'w')
+ for mod, mangled, size in done:
+ outfp.write('extern unsigned char M_%s[];\n' % mangled)
+ outfp.write(header)
+ for mod, mangled, size in done:
+ outfp.write('\t{"%s", M_%s, %d},\n' % (mod, mangled, size))
+ outfp.write(trailer)
+ outfp.write(entry_point)
+ outfp.close()
+ #outfp = bkfile.open(base + 'main.c', 'w')
+ #outfp.write(main_entry_point)
+ #outfp.close()
+ return files
+
+
+
+# Write a C initializer for a module containing the frozen python code.
+# The array is called M_<mod>.
+
+def writecode(outfp, mod, str):
+ outfp.write('unsigned char M_%s[] = {' % mod)
+ for i in range(0, len(str), 16):
+ outfp.write('\n\t')
+ for c in str[i:i+16]:
+ outfp.write('%d,' % ord(c))
+ outfp.write('\n};\n')
+
+## def writecode(outfp, mod, str):
+## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str),
+## string.join(map(lambda s: `s`[1:-1], string.split(str, '"')), '\\"')))
diff --git a/intern/python/freeze/makemakefile.py b/intern/python/freeze/makemakefile.py
new file mode 100644
index 00000000000..bb2ed43430d
--- /dev/null
+++ b/intern/python/freeze/makemakefile.py
@@ -0,0 +1,57 @@
+# Write the actual Makefile.
+##
+##
+## Customized makemakefile for NaN
+##
+##
+## 1.11.2001, strubi@blender.nl
+##
+##
+
+
+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("\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 $(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)
diff --git a/intern/python/freeze/modulefinder.py b/intern/python/freeze/modulefinder.py
new file mode 100644
index 00000000000..e84a54128f6
--- /dev/null
+++ b/intern/python/freeze/modulefinder.py
@@ -0,0 +1,444 @@
+"""Find modules used by a script, using introspection."""
+
+import dis
+import imp
+import marshal
+import os
+import re
+import string
+import sys
+
+if sys.platform=="win32":
+ # On Windows, we can locate modules in the registry with
+ # the help of the win32api package.
+ try:
+ import win32api
+ except ImportError:
+ print "The win32api module is not available - modules listed"
+ print "in the registry will not be found."
+ win32api = None
+
+
+IMPORT_NAME = dis.opname.index('IMPORT_NAME')
+IMPORT_FROM = dis.opname.index('IMPORT_FROM')
+STORE_NAME = dis.opname.index('STORE_NAME')
+STORE_FAST = dis.opname.index('STORE_FAST')
+STORE_GLOBAL = dis.opname.index('STORE_GLOBAL')
+STORE_OPS = [STORE_NAME, STORE_FAST, STORE_GLOBAL]
+
+# Modulefinder does a good job at simulating Python's, but it can not
+# handle __path__ modifications packages make at runtime. Therefore there
+# is a mechanism whereby you can register extra paths in this map for a
+# package, and it will be honored.
+
+# Note this is a mapping is lists of paths.
+packagePathMap = {}
+
+# A Public interface
+def AddPackagePath(packagename, path):
+ paths = packagePathMap.get(packagename, [])
+ paths.append(path)
+ packagePathMap[packagename] = paths
+
+class Module:
+
+ def __init__(self, name, file=None, path=None):
+ self.__name__ = name
+ self.__file__ = file
+ self.__path__ = path
+ self.__code__ = None
+
+ def __repr__(self):
+ s = "Module(%s" % `self.__name__`
+ if self.__file__ is not None:
+ s = s + ", %s" % `self.__file__`
+ if self.__path__ is not None:
+ s = s + ", %s" % `self.__path__`
+ s = s + ")"
+ return s
+
+
+class ModuleFinder:
+
+ def __init__(self, path=None, debug=0, excludes = []):
+ if path is None:
+ path = sys.path
+ self.path = path
+ self.modules = {}
+ self.badmodules = {}
+ self.debug = debug
+ self.indent = 0
+ self.excludes = excludes
+
+ def msg(self, level, str, *args):
+ if level <= self.debug:
+ for i in range(self.indent):
+ print " ",
+ print str,
+ for arg in args:
+ print repr(arg),
+ print
+
+ def msgin(self, *args):
+ level = args[0]
+ if level <= self.debug:
+ self.indent = self.indent + 1
+ apply(self.msg, args)
+
+ def msgout(self, *args):
+ level = args[0]
+ if level <= self.debug:
+ self.indent = self.indent - 1
+ apply(self.msg, args)
+
+ def run_script(self, pathname):
+ self.msg(2, "run_script", pathname)
+ fp = open(pathname)
+ stuff = ("", "r", imp.PY_SOURCE)
+ self.load_module('__main__', fp, pathname, stuff)
+
+ def load_file(self, pathname):
+ dir, name = os.path.split(pathname)
+ name, ext = os.path.splitext(name)
+ fp = open(pathname)
+ stuff = (ext, "r", imp.PY_SOURCE)
+ self.load_module(name, fp, pathname, stuff)
+
+ def import_hook(self, name, caller=None, fromlist=None):
+ self.msg(3, "import_hook", name, caller, fromlist)
+ parent = self.determine_parent(caller)
+ q, tail = self.find_head_package(parent, name)
+ m = self.load_tail(q, tail)
+ if not fromlist:
+ return q
+ if m.__path__:
+ self.ensure_fromlist(m, fromlist)
+
+ def determine_parent(self, caller):
+ self.msgin(4, "determine_parent", caller)
+ if not caller:
+ self.msgout(4, "determine_parent -> None")
+ return None
+ pname = caller.__name__
+ if caller.__path__:
+ parent = self.modules[pname]
+ assert caller is parent
+ self.msgout(4, "determine_parent ->", parent)
+ return parent
+ if '.' in pname:
+ i = string.rfind(pname, '.')
+ pname = pname[:i]
+ parent = self.modules[pname]
+ assert parent.__name__ == pname
+ self.msgout(4, "determine_parent ->", parent)
+ return parent
+ self.msgout(4, "determine_parent -> None")
+ return None
+
+ def find_head_package(self, parent, name):
+ self.msgin(4, "find_head_package", parent, name)
+ if '.' in name:
+ i = string.find(name, '.')
+ head = name[:i]
+ tail = name[i+1:]
+ else:
+ head = name
+ tail = ""
+ if parent:
+ qname = "%s.%s" % (parent.__name__, head)
+ else:
+ qname = head
+ q = self.import_module(head, qname, parent)
+ if q:
+ self.msgout(4, "find_head_package ->", (q, tail))
+ return q, tail
+ if parent:
+ qname = head
+ parent = None
+ q = self.import_module(head, qname, parent)
+ if q:
+ self.msgout(4, "find_head_package ->", (q, tail))
+ return q, tail
+ self.msgout(4, "raise ImportError: No module named", qname)
+ raise ImportError, "No module named " + qname
+
+ def load_tail(self, q, tail):
+ self.msgin(4, "load_tail", q, tail)
+ m = q
+ while tail:
+ i = string.find(tail, '.')
+ if i < 0: i = len(tail)
+ head, tail = tail[:i], tail[i+1:]
+ mname = "%s.%s" % (m.__name__, head)
+ m = self.import_module(head, mname, m)
+ if not m:
+ self.msgout(4, "raise ImportError: No module named", mname)
+ raise ImportError, "No module named " + mname
+ self.msgout(4, "load_tail ->", m)
+ return m
+
+ def ensure_fromlist(self, m, fromlist, recursive=0):
+ self.msg(4, "ensure_fromlist", m, fromlist, recursive)
+ for sub in fromlist:
+ if sub == "*":
+ if not recursive:
+ all = self.find_all_submodules(m)
+ if all:
+ self.ensure_fromlist(m, all, 1)
+ elif not hasattr(m, sub):
+ subname = "%s.%s" % (m.__name__, sub)
+ submod = self.import_module(sub, subname, m)
+ if not submod:
+ raise ImportError, "No module named " + subname
+
+ def find_all_submodules(self, m):
+ if not m.__path__:
+ return
+ modules = {}
+ suffixes = [".py", ".pyc", ".pyo"]
+ for dir in m.__path__:
+ try:
+ names = os.listdir(dir)
+ except os.error:
+ self.msg(2, "can't list directory", dir)
+ continue
+ for name in names:
+ mod = None
+ for suff in suffixes:
+ n = len(suff)
+ if name[-n:] == suff:
+ mod = name[:-n]
+ break
+ if mod and mod != "__init__":
+ modules[mod] = mod
+ return modules.keys()
+
+ def import_module(self, partname, fqname, parent):
+ self.msgin(3, "import_module", partname, fqname, parent)
+ try:
+ m = self.modules[fqname]
+ except KeyError:
+ pass
+ else:
+ self.msgout(3, "import_module ->", m)
+ return m
+ if self.badmodules.has_key(fqname):
+ self.msgout(3, "import_module -> None")
+ if parent:
+ self.badmodules[fqname][parent.__name__] = None
+ return None
+ try:
+ fp, pathname, stuff = self.find_module(partname,
+ parent and parent.__path__)
+ except ImportError:
+ self.msgout(3, "import_module ->", None)
+ return None
+ try:
+ m = self.load_module(fqname, fp, pathname, stuff)
+ finally:
+ if fp: fp.close()
+ if parent:
+ setattr(parent, partname, m)
+ self.msgout(3, "import_module ->", m)
+ return m
+
+ def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
+ self.msgin(2, "load_module", fqname, fp and "fp", pathname)
+ if type == imp.PKG_DIRECTORY:
+ m = self.load_package(fqname, pathname)
+ self.msgout(2, "load_module ->", m)
+ return m
+ if type == imp.PY_SOURCE:
+ co = compile(fp.read()+'\n', pathname, 'exec')
+ elif type == imp.PY_COMPILED:
+ if fp.read(4) != imp.get_magic():
+ self.msgout(2, "raise ImportError: Bad magic number", pathname)
+ raise ImportError, "Bad magic number in %s" % pathname
+ fp.read(4)
+ co = marshal.load(fp)
+ else:
+ co = None
+ m = self.add_module(fqname)
+ m.__file__ = pathname
+ if co:
+ m.__code__ = co
+ self.scan_code(co, m)
+ self.msgout(2, "load_module ->", m)
+ return m
+
+ def scan_code(self, co, m):
+ code = co.co_code
+ n = len(code)
+ i = 0
+ lastname = None
+ while i < n:
+ c = code[i]
+ i = i+1
+ op = ord(c)
+ if op >= dis.HAVE_ARGUMENT:
+ oparg = ord(code[i]) + ord(code[i+1])*256
+ i = i+2
+ if op == IMPORT_NAME:
+ name = lastname = co.co_names[oparg]
+ if not self.badmodules.has_key(lastname):
+ try:
+ self.import_hook(name, m)
+ except ImportError, msg:
+ self.msg(2, "ImportError:", str(msg))
+ if not self.badmodules.has_key(name):
+ self.badmodules[name] = {}
+ self.badmodules[name][m.__name__] = None
+ elif op == IMPORT_FROM:
+ name = co.co_names[oparg]
+ assert lastname is not None
+ if not self.badmodules.has_key(lastname):
+ try:
+ self.import_hook(lastname, m, [name])
+ except ImportError, msg:
+ self.msg(2, "ImportError:", str(msg))
+ fullname = lastname + "." + name
+ if not self.badmodules.has_key(fullname):
+ self.badmodules[fullname] = {}
+ self.badmodules[fullname][m.__name__] = None
+ elif op in STORE_OPS:
+ # Skip; each IMPORT_FROM is followed by a STORE_* opcode
+ pass
+ else:
+ lastname = None
+ for c in co.co_consts:
+ if isinstance(c, type(co)):
+ self.scan_code(c, m)
+
+ def load_package(self, fqname, pathname):
+ self.msgin(2, "load_package", fqname, pathname)
+ m = self.add_module(fqname)
+ m.__file__ = pathname
+ m.__path__ = [pathname]
+
+ # As per comment at top of file, simulate runtime __path__ additions.
+ m.__path__ = m.__path__ + packagePathMap.get(fqname, [])
+
+ fp, buf, stuff = self.find_module("__init__", m.__path__)
+ self.load_module(fqname, fp, buf, stuff)
+ self.msgout(2, "load_package ->", m)
+ return m
+
+ def add_module(self, fqname):
+ if self.modules.has_key(fqname):
+ return self.modules[fqname]
+ self.modules[fqname] = m = Module(fqname)
+ return m
+
+ def find_module(self, name, path):
+ if name in self.excludes:
+ self.msgout(3, "find_module -> Excluded")
+ raise ImportError, name
+
+ if path is None:
+ if name in sys.builtin_module_names:
+ return (None, None, ("", "", imp.C_BUILTIN))
+
+ # Emulate the Registered Module support on Windows.
+ if sys.platform=="win32" and win32api is not None:
+ HKEY_LOCAL_MACHINE = 0x80000002
+ try:
+ pathname = win32api.RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore\\%s\\Modules\\%s" % (sys.winver, name))
+ fp = open(pathname, "rb")
+ # XXX - To do - remove the hard code of C_EXTENSION.
+ stuff = "", "rb", imp.C_EXTENSION
+ return fp, pathname, stuff
+ except win32api.error:
+ pass
+
+ path = self.path
+ return imp.find_module(name, path)
+
+ def report(self):
+ print
+ print " %-25s %s" % ("Name", "File")
+ print " %-25s %s" % ("----", "----")
+ # Print modules found
+ keys = self.modules.keys()
+ keys.sort()
+ for key in keys:
+ m = self.modules[key]
+ if m.__path__:
+ print "P",
+ else:
+ print "m",
+ print "%-25s" % key, m.__file__ or ""
+
+ # Print missing modules
+ keys = self.badmodules.keys()
+ keys.sort()
+ for key in keys:
+ # ... but not if they were explicitly excluded.
+ if key not in self.excludes:
+ mods = self.badmodules[key].keys()
+ mods.sort()
+ print "?", key, "from", string.join(mods, ', ')
+
+
+def test():
+ # Parse command line
+ import getopt
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")
+ except getopt.error, msg:
+ print msg
+ return
+
+ # Process options
+ debug = 1
+ domods = 0
+ addpath = []
+ exclude = []
+ for o, a in opts:
+ if o == '-d':
+ debug = debug + 1
+ if o == '-m':
+ domods = 1
+ if o == '-p':
+ addpath = addpath + string.split(a, os.pathsep)
+ if o == '-q':
+ debug = 0
+ if o == '-x':
+ exclude.append(a)
+
+ # Provide default arguments
+ if not args:
+ script = "hello.py"
+ else:
+ script = args[0]
+
+ # Set the path based on sys.path and the script directory
+ path = sys.path[:]
+ path[0] = os.path.dirname(script)
+ path = addpath + path
+ if debug > 1:
+ print "path:"
+ for item in path:
+ print " ", `item`
+
+ # Create the module finder and turn its crank
+ mf = ModuleFinder(path, debug, exclude)
+ for arg in args[1:]:
+ if arg == '-m':
+ domods = 1
+ continue
+ if domods:
+ if arg[-2:] == '.*':
+ mf.import_hook(arg[:-2], None, ["*"])
+ else:
+ mf.import_hook(arg)
+ else:
+ mf.load_file(arg)
+ mf.run_script(script)
+ mf.report()
+
+
+if __name__ == '__main__':
+ try:
+ test()
+ except KeyboardInterrupt:
+ print "\n[interrupt]"
diff --git a/intern/python/freeze/parsesetup.py b/intern/python/freeze/parsesetup.py
new file mode 100644
index 00000000000..1795671e946
--- /dev/null
+++ b/intern/python/freeze/parsesetup.py
@@ -0,0 +1,98 @@
+# Parse Makefiles and Python Setup(.in) files.
+
+import regex
+import string
+
+
+# Extract variable definitions from a Makefile.
+# Return a dictionary mapping names to values.
+# May raise IOError.
+
+makevardef = regex.compile('^\([a-zA-Z0-9_]+\)[ \t]*=\(.*\)')
+
+def getmakevars(filename):
+ variables = {}
+ fp = open(filename)
+ try:
+ while 1:
+ line = fp.readline()
+ if not line:
+ break
+ if makevardef.match(line) < 0:
+ continue
+ name, value = makevardef.group(1, 2)
+ # Strip trailing comment
+ i = string.find(value, '#')
+ if i >= 0:
+ value = value[:i]
+ value = string.strip(value)
+ variables[name] = value
+ finally:
+ fp.close()
+ return variables
+
+
+# Parse a Python Setup(.in) file.
+# Return two dictionaries, the first mapping modules to their
+# definitions, the second mapping variable names to their values.
+# May raise IOError.
+
+setupvardef = regex.compile('^\([a-zA-Z0-9_]+\)=\(.*\)')
+
+def getsetupinfo(filename):
+ modules = {}
+ variables = {}
+ fp = open(filename)
+ try:
+ while 1:
+ line = fp.readline()
+ if not line:
+ break
+ # Strip comments
+ i = string.find(line, '#')
+ if i >= 0:
+ line = line[:i]
+ if setupvardef.match(line) >= 0:
+ name, value = setupvardef.group(1, 2)
+ variables[name] = string.strip(value)
+ else:
+ words = string.split(line)
+ if words:
+ modules[words[0]] = words[1:]
+ finally:
+ fp.close()
+ return modules, variables
+
+
+# Test the above functions.
+
+def test():
+ import sys
+ import os
+ if not sys.argv[1:]:
+ print 'usage: python parsesetup.py Makefile*|Setup* ...'
+ sys.exit(2)
+ for arg in sys.argv[1:]:
+ base = os.path.basename(arg)
+ if base[:8] == 'Makefile':
+ print 'Make style parsing:', arg
+ v = getmakevars(arg)
+ prdict(v)
+ elif base[:5] == 'Setup':
+ print 'Setup style parsing:', arg
+ m, v = getsetupinfo(arg)
+ prdict(m)
+ prdict(v)
+ else:
+ print arg, 'is neither a Makefile nor a Setup file'
+ print '(name must begin with "Makefile" or "Setup")'
+
+def prdict(d):
+ keys = d.keys()
+ keys.sort()
+ for key in keys:
+ value = d[key]
+ print "%-15s" % key, str(value)
+
+if __name__ == '__main__':
+ test()
diff --git a/intern/python/freeze/winmakemakefile.py b/intern/python/freeze/winmakemakefile.py
new file mode 100644
index 00000000000..d668a6e8273
--- /dev/null
+++ b/intern/python/freeze/winmakemakefile.py
@@ -0,0 +1,146 @@
+import sys, os, string
+
+# Template used then the program is a GUI program
+WINMAINTEMPLATE = """
+#include <windows.h>
+
+int WINAPI WinMain(
+ HINSTANCE hInstance, // handle to current instance
+ HINSTANCE hPrevInstance, // handle to previous instance
+ LPSTR lpCmdLine, // pointer to command line
+ int nCmdShow // show state of window
+ )
+{
+ extern int Py_FrozenMain(int, char **);
+ PyImport_FrozenModules = _PyImport_FrozenModules;
+ return Py_FrozenMain(__argc, __argv);
+}
+"""
+
+SERVICETEMPLATE = """
+extern int PythonService_main(int, char **);
+
+int main( int argc, char **argv)
+{
+ PyImport_FrozenModules = _PyImport_FrozenModules;
+ return PythonService_main(argc, argv);
+}
+"""
+
+subsystem_details = {
+ # -s flag : (C entry point template), (is it __main__?), (is it a DLL?)
+ 'console' : (None, 1, 0),
+ 'windows' : (WINMAINTEMPLATE, 1, 0),
+ 'service' : (SERVICETEMPLATE, 0, 0),
+ 'com_dll' : ("", 0, 1),
+}
+
+def get_custom_entry_point(subsystem):
+ try:
+ return subsystem_details[subsystem][:2]
+ except KeyError:
+ raise ValueError, "The subsystem %s is not known" % subsystem
+
+
+def makemakefile(outfp, vars, files, target):
+ save = sys.stdout
+ try:
+ sys.stdout = outfp
+ realwork(vars, files, target)
+ finally:
+ sys.stdout = save
+
+def realwork(vars, moddefns, target):
+ version_suffix = `sys.version_info[0]`+`sys.version_info[1]`
+ print "# Makefile for Microsoft Visual C++ generated by freeze.py script"
+ print
+ print 'target = %s' % target
+ print 'pythonhome = %s' % vars['prefix']
+ print
+ print 'DEBUG=0 # Set to 1 to use the _d versions of Python.'
+ print '!IF $(DEBUG)'
+ print 'debug_suffix=_d'
+ print 'c_debug=/Zi /Od /DDEBUG /D_DEBUG'
+ print 'l_debug=/DEBUG'
+ print 'temp_dir=Build\\Debug'
+ print '!ELSE'
+ print 'debug_suffix='
+ print 'c_debug=/Ox'
+ print 'l_debug='
+ print 'temp_dir=Build\\Release'
+ print '!ENDIF'
+ print
+
+ print '# The following line assumes you have built Python using the standard instructions'
+ print '# Otherwise fix the following line to point to the library.'
+ print 'pythonlib = "$(pythonhome)/pcbuild/python%s$(debug_suffix).lib"' % version_suffix
+ print
+
+ # We only ever write one "entry point" symbol - either
+ # "main" or "WinMain". Therefore, there is no need to
+ # pass a subsystem switch to the linker as it works it
+ # out all by itself. However, the subsystem _does_ determine
+ # the file extension and additional linker flags.
+ target_link_flags = ""
+ target_ext = ".exe"
+ if subsystem_details[vars['subsystem']][2]:
+ target_link_flags = "-dll"
+ target_ext = ".dll"
+
+
+ print "# As the target uses Python%s.dll, we must use this compiler option!" % version_suffix
+ print "cdl = /MD"
+ print
+ print "all: $(target)$(debug_suffix)%s" % (target_ext)
+ print
+
+ print '$(temp_dir):'
+ print ' if not exist $(temp_dir)\. mkdir $(temp_dir)'
+ print
+
+ objects = []
+ libs = ["shell32.lib", "comdlg32.lib", "wsock32.lib", "user32.lib", "oleaut32.lib"]
+ for moddefn in moddefns:
+ print "# Module", moddefn.name
+ for file in moddefn.sourceFiles:
+ base = os.path.basename(file)
+ base, ext = os.path.splitext(base)
+ objects.append(base + ".obj")
+ print '$(temp_dir)\%s.obj: "%s"' % (base, file)
+ print "\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE",
+ print '"-I$(pythonhome)/Include" "-I$(pythonhome)/PC" \\'
+ print "\t\t$(cflags) $(cdebug) $(cinclude) \\"
+ extra = moddefn.GetCompilerOptions()
+ if extra:
+ print "\t\t%s \\" % (string.join(extra),)
+ print '\t\t"%s"' % file
+ print
+
+ # Add .lib files this module needs
+ for modlib in moddefn.GetLinkerLibs():
+ if modlib not in libs:
+ libs.append(modlib)
+
+ print "ADDN_LINK_FILES=",
+ for addn in vars['addn_link']: print '"%s"' % (addn),
+ print ; print
+
+ print "OBJS=",
+ for obj in objects: print '"$(temp_dir)\%s"' % (obj),
+ print ; print
+
+ print "LIBS=",
+ for lib in libs: print '"%s"' % (lib),
+ print ; print
+
+ print "$(target)$(debug_suffix)%s: $(temp_dir) $(OBJS)" % (target_ext)
+ print "\tlink -out:$(target)$(debug_suffix)%s %s" % (target_ext, target_link_flags),
+ print "\t$(OBJS) \\"
+ print "\t$(LIBS) \\"
+ print "\t$(ADDN_LINK_FILES) \\"
+ print "\t$(pythonlib) $(lcustom) $(l_debug)\\"
+ print "\t$(resources)"
+ print
+ print "clean:"
+ print "\t-rm -f *.obj"
+ print "\t-rm -f $(target).exe"