Initial revision

This commit is contained in:
Hans Lambermont
2002-10-12 11:37:38 +00:00
commit 12315f4d0e
1699 changed files with 444708 additions and 0 deletions

View File

@@ -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

173
intern/python/freeze/README Normal file
View File

@@ -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/)

View File

@@ -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!

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}
"""

461
intern/python/freeze/freeze.py Executable file
View File

@@ -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()

View File

@@ -0,0 +1 @@
print 'Hello world...'

View File

@@ -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()

View File

@@ -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, '"')), '\\"')))

View File

@@ -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)

View File

@@ -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]"

View File

@@ -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()

View File

@@ -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"