python-3.6.zip added from Github

README.cosmo contains the necessary links.
This commit is contained in:
ahgamut 2021-08-08 09:38:33 +05:30 committed by Justine Tunney
parent 75fc601ff5
commit 0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions

296
third_party/python/Tools/freeze/README vendored Normal file
View file

@ -0,0 +1,296 @@
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 without a Tcl/Tk installation. The best way to ship a
frozen Tkinter program is to decide in advance where you are going
to place the Tcl and Tk library files in the distributed setup, and
then declare these directories in your frozen Python program using
the TCL_LIBRARY, TK_LIBRARY and TIX_LIBRARY environment variables.
For example, assume you will ship your frozen program in the directory
<root>/bin/windows-x86 and will place your Tcl library files
in <root>/lib/tcl8.2 and your Tk library files in <root>/lib/tk8.2. Then
placing the following lines in your frozen Python script before importing
Tkinter or Tix would set the environment correctly for Tcl/Tk/Tix:
import os
import os.path
RootDir = os.path.dirname(os.path.dirname(os.getcwd()))
import sys
if sys.platform == "win32":
sys.path = ['', '..\\..\\lib\\python-2.0']
os.environ['TCL_LIBRARY'] = RootDir + '\\lib\\tcl8.2'
os.environ['TK_LIBRARY'] = RootDir + '\\lib\\tk8.2'
os.environ['TIX_LIBRARY'] = RootDir + '\\lib\\tix8.1'
elif sys.platform == "linux2":
sys.path = ['', '../../lib/python-2.0']
os.environ['TCL_LIBRARY'] = RootDir + '/lib/tcl8.2'
os.environ['TK_LIBRARY'] = RootDir + '/lib/tk8.2'
os.environ['TIX_LIBRARY'] = RootDir + '/lib/tix8.1'
elif sys.platform == "solaris":
sys.path = ['', '../../lib/python-2.0']
os.environ['TCL_LIBRARY'] = RootDir + '/lib/tcl8.2'
os.environ['TK_LIBRARY'] = RootDir + '/lib/tk8.2'
os.environ['TIX_LIBRARY'] = RootDir + '/lib/tix8.1'
This also adds <root>/lib/python-2.0 to your Python path
for any Python files such as _tkinter.pyd you may need.
Note that the dynamic libraries (such as tcl82.dll tk82.dll python20.dll
under Windows, or libtcl8.2.so and libtcl8.2.so under Unix) are required
at program load time, and are searched by the operating system loader
before Python can be started. Under Windows, the environment
variable PATH is consulted, and under Unix, it may be the
environment variable LD_LIBRARY_PATH and/or the system
shared library cache (ld.so). An additional preferred directory for
finding the dynamic libraries is built into the .dll or .so files at
compile time - see the LIB_RUNTIME_DIR variable in the Tcl makefile.
The OS must find the dynamic libraries or your frozen program won't start.
Usually I make sure that the .so or .dll files are in the same directory
as the executable, but this may not be foolproof.
A workaround to installing your Tcl library files with your frozen
executable 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. An easier approach is to freeze the
Tcl/Tk/Tix code into the dynamic libraries using the Tcl ET code,
or the Tix Stand-Alone-Module code. Of course, you can also simply
require that Tcl/Tk is required on the target installation, but be
careful that the version corresponds.
There are some caveats using frozen Tkinter applications:
Under Windows if you use the -s windows option, writing
to stdout or stderr is an error.
The Tcl [info nameofexecutable] will be set to where the
program was frozen, not where it is run from.
The global variables argc and argv do not exist.
A warning about shared library modules
--------------------------------------
When your Python installation uses shared library modules such as
_tkinter.pyd, 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. Or use the approach described in the previous
section to declare a library path using sys.path, and place the modules
such as _tkinter.pyd there.
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).
It is possible to create frozen programs that don't have a console
window, by specifying the option '-s windows'. See the Usage below.
Usage
-----
Here is a list of all of the options (taken from freeze.__doc__):
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.
--Guido van Rossum (home page: http://www.python.org/~guido/)

View file

@ -0,0 +1,26 @@
from builtins import open as _orig_open
def open(file, mode='r', bufsize=-1):
if 'w' not in mode:
return _orig_open(file, mode, bufsize)
import os
backup = file + '~'
try:
os.unlink(backup)
except OSError:
pass
try:
os.rename(file, backup)
except OSError:
return _orig_open(file, mode, bufsize)
f = _orig_open(file, mode, bufsize)
_orig_close = f.close
def close():
_orig_close()
import filecmp
if filecmp.cmp(backup, file, shallow=False):
import os
os.unlink(file)
os.rename(backup, file)
f.close = close
return f

View file

@ -0,0 +1,90 @@
# 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 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 mod not in mods:
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 list(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 w.split():
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 = str.find('$', i)
if i < 0:
break
i = i+1
var = str[i:i+1]
i = i+1
if var == '(':
j = str.find(')', i)
if j < 0:
break
var = str[i:j]
i = j+1
if var in vars:
str = str[:k] + vars[var] + str[i:]
i = k
return str

View file

@ -0,0 +1,188 @@
"""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 don't 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 strategy 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 extracted 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, 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\n" % defaultMapName)
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 = exclude.split()
if win32api.GetProfileVal(moduleName, "Unicode", 0, mapFileName):
module.AddCompilerOption('/D UNICODE /D _UNICODE')
libs = win32api.GetProfileVal(moduleName, "libs", "", mapFileName).split()
for lib in libs:
module.AddLinkerLib(win32api.ExpandEnvironmentStrings(lib))
for exc in exclude:
if exc in module.sourceFiles:
module.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 as msg:
sys.stderr.write("%s: %s\n" % (dsp, msg))
return None
for line in lines:
fields = line.strip().split("=", 2)
if fields[0]=="SOURCE":
if os.path.splitext(fields[1])[1].lower() 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 = module.name.split('.')[-1]
fp.write('extern void init%s(void);\n' % (name) )
# Write the table
fp.write (ext_tab_header)
for module in modules:
name = module.name.split('.')[-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);
}
"""

View file

@ -0,0 +1,171 @@
; This is a list of modules generally build as .pyd files.
;
; Each section contains enough information about a module for
; freeze to include the module as a static, built-in module
; in a frozen .EXE/.DLL.
; This is all setup for all the win32 extension modules
; released by Mark Hammond.
; You must ensure that the environment variable PYTHONEX is set
; to point to the root win32 extensions directory
; PYTHONPREFIX must point to the Python build root directory
; (the *parent* of PCbuild); normally the freeze script takes
; care of this.
;--------------------------------------------------------------
;
; Standard Python extension modules
;
; Here are some of the standard Python extensions modules.
; If you need others, add them here
[_socket]
dsp=%PYTHONPREFIX%\PCBuild\_socket.dsp
[_sre]
dsp=%PYTHONPREFIX%\PCBuild\_sre.dsp
[unicodedata]
dsp=%PYTHONPREFIX%\PCBuild\unicodedata.dsp
[mmap]
dsp=%PYTHONPREFIX%\PCBuild\mmap.dsp
[winsound]
dsp=%PYTHONPREFIX%\PCBuild\winsound.dsp
libs=winmm.lib
[parser]
dsp=%PYTHONPREFIX%\PCBuild\parser.dsp
[select]
dsp=%PYTHONPREFIX%\PCBuild\select.dsp
[zlib]
dsp=%PYTHONPREFIX%\PCBuild\zlib.dsp
cl=/I %PYTHONPREFIX%\..\zlib-1.1.4 /D _WINDOWS /D WIN32
libs=%PYTHONPREFIX%\..\zlib-1.1.4\zlib.lib /nodefaultlib:libc
[winreg]
dsp=%PYTHONPREFIX%\PCBuild\winreg.dsp
libs=advapi32.lib
;--------------------------------------------------------------
;
; Win32 Projects.
;
[perfmon]
dsp=%PYTHONEX%\win32\perfmon.dsp
cl=/I %PYTHONEX%\win32\src
Unicode=1
[pywintypes]
dsp=%PYTHONEX%\win32\pywintypes.dsp
cl=/I %PYTHONEX%\win32\src
libs=ole32.lib oleaut32.lib
[win32api]
dsp=%PYTHONEX%\win32\win32api.dsp
cl=/I %PYTHONEX%\win32\src
libs=kernel32.lib user32.lib shell32.lib advapi32.lib
[win32service]
dsp=%PYTHONEX%\win32\win32service.dsp
cl=/I %PYTHONEX%\win32\src
Unicode=1
libs=advapi32.lib
[win32evtlog]
dsp=%PYTHONEX%\win32\win32evtlog.dsp
cl=/I %PYTHONEX%\win32\src
[win32process]
dsp=%PYTHONEX%\win32\win32process.dsp
cl=/I %PYTHONEX%\win32\src
[win32event]
dsp=%PYTHONEX%\win32\win32event.dsp
cl=/I %PYTHONEX%\win32\src
[win32file]
dsp=%PYTHONEX%\win32\win32file.dsp
cl=/I %PYTHONEX%\win32\src
[win32net]
dsp=%PYTHONEX%\win32\win32net.dsp
cl=/I %PYTHONEX%\win32\src
libs=netapi32.lib
[win32pdh]
dsp=%PYTHONEX%\win32\win32pdh.dsp
cl=/I %PYTHONEX%\win32\src
[win32pipe]
dsp=%PYTHONEX%\win32\win32pipe.dsp
cl=/I %PYTHONEX%\win32\src
[win32security]
dsp=%PYTHONEX%\win32\win32security.dsp
cl=/I %PYTHONEX%\win32\src
[win32service]
dsp=%PYTHONEX%\win32\win32service.dsp
cl=/I %PYTHONEX%\win32\src
[win32trace]
dsp=%PYTHONEX%\win32\win32trace.dsp
cl=/I %PYTHONEX%\win32\src
;--------------------------------------------------------------
;
; COM Projects.
;
[pythoncom]
dsp=%PYTHONEX%\com\win32com.dsp
cl=/I %PYTHONEX%\com\win32com\src\include /I %PYTHONEX%\win32\src
libs=uuid.lib
[win32com.axcontrol.axcontrol]
dsp=%PYTHONEX%\com\axcontrol.dsp
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
[win32com.axscript.axscript]
dsp=%PYTHONEX%\com\Active Scripting.dsp
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
[win32com.axdebug.axdebug]
dsp=%PYTHONEX%\com\Active Debugging.dsp
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
[win32com.mapi.mapi]
dsp=%PYTHONEX%\com\mapi.dsp
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
libs=MBLOGON.lib ADDRLKUP.LIB mapi32.lib version.lib
[win32com.mapi.exchange]
dsp=%PYTHONEX%\com\exchange.dsp
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
libs=MBLOGON.lib ADDRLKUP.LIB exchinst.lib EDKCFG.LIB EDKUTILS.LIB EDKMAPI.LIB mapi32.lib version.lib
[win32com.mapi.exchdapi]
dsp=%PYTHONEX%\com\exchdapi.dsp
cl=/I %PYTHONEX%\win32\src /I %PYTHONEX%\com\win32com\src\include
libs=DAPI.LIB
[servicemanager]
dsp=%PYTHONEX%\win32\PythonService EXE.dsp
Unicode = 1
; Pythonwin
[win32ui]
dsp=%PYTHONEX%\Pythonwin\win32ui.dsp
cl=/D _AFXDLL /D FREEZE_WIN32UI /GX /I %PYTHONEX%\win32\src
libs=mfc42.lib

View file

@ -0,0 +1,2 @@
initialized = True
print("Hello world!")

491
third_party/python/Tools/freeze/freeze.py vendored Executable file
View file

@ -0,0 +1,491 @@
#! /usr/bin/env python3
"""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. It will still be imported
by the frozen binary if it exists on the host system.
-X module Like -x, except the module can never be imported by
the frozen binary.
-E: Freeze will fail if any modules can't be found (that
were not excluded using -x or -X).
-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.)
-r prefix=f: Replace path prefix.
Replace prefix with f in the source path references
contained in the resulting binary.
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 modulefinder
import getopt
import os
import sys
# Import the freeze-private modules
import checkextensions
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'
replace_paths = [] # settable with -r option
error_if_any_missing = 0
# default the exclude list for each platform
if win: exclude = exclude + [
'dos', 'dospath', 'mac', 'macpath', 'macfs', 'MACFS', 'posix', ]
fail_import = exclude[:]
# output files
frozen_c = 'frozen.c'
config_c = 'config.c'
target = 'a.out' # normally derived from script name
makefile = 'Makefile'
subsystem = 'console'
# parse command line by first replacing any "-i" options with the
# file contents.
pos = 1
while pos < len(sys.argv)-1:
# last option can not be "-i", so this ensures "pos+1" is in range!
if sys.argv[pos] == '-i':
try:
options = open(sys.argv[pos+1]).read().split()
except IOError as 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:], 'r:a:dEe:hmo:p:P:qs:wX:x:l:')
except getopt.error as msg:
usage('getopt error: ' + str(msg))
# process 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 == '-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 == '-X':
exclude.append(a)
fail_import.append(a)
if o == '-E':
error_if_any_missing = 1
if o == '-l':
addn_link.append(a)
if o == '-a':
modulefinder.AddPackagePath(*a.split("=", 2))
if o == '-r':
f,r = a.split("=", 2)
replace_paths.append( (f,r) )
# modules that are imported by the Python runtime
implicits = []
for module in ('site', 'warnings', 'encodings.utf_8', 'encodings.latin_1'):
if module not in exclude:
implicits.append(module)
# 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 = '%d.%d' % sys.version_info[:2]
flagged_version = version + sys.abiflags
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, '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-%s' % flagged_version)
incldir = os.path.join(prefix, 'include', 'python%s' % flagged_version)
config_h_dir = os.path.join(exec_prefix, 'include',
'python%s' % flagged_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:
# These are not directories on Windows.
check_dirs = check_dirs + extensions
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 OSError as 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 as 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, replace_paths)
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)
# Alias "importlib._bootstrap" to "_frozen_importlib" so that the
# import machinery can bootstrap. Do the same for
# importlib._bootstrap_external.
mf.modules["_frozen_importlib"] = mf.modules["importlib._bootstrap"]
mf.modules["_frozen_importlib_external"] = mf.modules["importlib._bootstrap_external"]
# 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
if error_if_any_missing:
missing = mf.any_missing()
if missing:
sys.exit("There are some missing modules: %r" % missing)
# generate output for frozen modules
files = makefreeze.makefreeze(base, dict, debug, custom_entry_point,
fail_import)
# look for unfrozen modules (builtin and of unknown origin)
builtins = []
unknown = []
mods = sorted(dict.keys())
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' %
' '.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 )
with open(makefile, 'w') as outfp:
winmakemakefile.makemakefile(outfp,
locals(),
frozen_extensions,
os.path.basename(target))
return
# generate config.c and Makefile
builtins.sort()
with open(config_c_in) as infp, bkfile.open(config_c, 'w') as outfp:
makeconfig.makeconfig(infp, outfp, builtins)
cflags = ['$(OPT)']
cppflags = defines + includes
libs = [os.path.join(binlib, '$(LDLIBRARY)')]
somevars = {}
if os.path.exists(makefile_in):
makevars = parsesetup.getmakevars(makefile_in)
for key in makevars:
somevars[key] = makevars[key]
somevars['CFLAGS'] = ' '.join(cflags) # override
somevars['CPPFLAGS'] = ' '.join(cppflags) # override
files = [base_config_c, base_frozen_c] + \
files + supp_sources + addfiles + libs + \
['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
with bkfile.open(makefile, 'w') as outfp:
makemakefile.makemakefile(outfp, somevars, files, base_target)
# Done!
if odir:
print('Now run "make" in', odir, end=' ')
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,59 @@
import re
import sys
# Write the config.c file
never = ['marshal', '_imp', '_ast', '__main__', 'builtins',
'sys', 'gc', '_warnings']
def makeconfig(infp, outfp, modules, with_ifdef=0):
m1 = re.compile('-- ADDMODULE MARKER 1 --')
m2 = re.compile('-- ADDMODULE MARKER 2 --')
for line in infp:
outfp.write(line)
if m1 and m1.search(line):
m1 = None
for mod in modules:
if mod in never:
continue
if with_ifdef:
outfp.write("#ifndef PyInit_%s\n"%mod)
outfp.write('extern PyObject* PyInit_%s(void);\n' % mod)
if with_ifdef:
outfp.write("#endif\n")
elif m2 and m2.search(line):
m2 = None
for mod in modules:
if mod in never:
continue
outfp.write('\t{"%s", PyInit_%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():
if not sys.argv[3:]:
print('usage: python makeconfig.py config.c.in outputfile', end=' ')
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,87 @@
import marshal
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.
default_entry_point = """
int
main(int argc, char **argv)
{
extern int Py_FrozenMain(int, char **);
""" + ((not __debug__ and """
Py_OptimizeFlag++;
""") or "") + """
PyImport_FrozenModules = _PyImport_FrozenModules;
return Py_FrozenMain(argc, argv);
}
"""
def makefreeze(base, dict, debug=0, entry_point=None, fail_import=()):
if entry_point is None: entry_point = default_entry_point
done = []
files = []
mods = sorted(dict.keys())
for mod in mods:
m = dict[mod]
mangled = "__".join(mod.split("."))
if m.__code__:
file = 'M_' + mangled + '.c'
with bkfile.open(base + file, 'w') as outfp:
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)
if debug:
print("generating table of frozen modules")
with bkfile.open(base + 'frozen.c', 'w') as outfp:
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('\n')
# The following modules have a NULL code pointer, indicating
# that the frozen program should not search for them on the host
# system. Importing them will *always* raise an ImportError.
# The zero value size is never used.
for mod in fail_import:
outfp.write('\t{"%s", NULL, 0},\n' % (mod,))
outfp.write(trailer)
outfp.write(entry_point)
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 bytes(str[i:i+16]):
outfp.write('%d,' % c)
outfp.write('\n};\n')
## def writecode(outfp, mod, str):
## outfp.write('unsigned char M_%s[%d] = "%s";\n' % (mod, len(str),
## '\\"'.join(map(lambda s: repr(s)[1:-1], str.split('"')))))

View file

@ -0,0 +1,28 @@
# Write the actual Makefile.
import os
def makemakefile(outfp, makevars, files, target):
outfp.write("# Makefile generated by freeze.py script\n\n")
keys = sorted(makevars.keys())
for key in keys:
outfp.write("%s=%s\n" % (key, makevars[key]))
outfp.write("\nall: %s\n\n" % target)
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) $(PY_CFLAGS) $(PY_CPPFLAGS) -c %s\n" % file)
files[i] = dest
deps.append(dest)
outfp.write("\n%s: %s\n" % (target, ' '.join(deps)))
outfp.write("\t$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) %s -o %s $(LDLAST)\n" %
(' '.join(files), target))
outfp.write("\nclean:\n\t-rm -f *.o %s\n" % target)

View file

@ -0,0 +1,111 @@
# Parse Makefiles and Python Setup(.in) files.
import re
# Extract variable definitions from a Makefile.
# Return a dictionary mapping names to values.
# May raise IOError.
makevardef = re.compile('^([a-zA-Z0-9_]+)[ \t]*=(.*)')
def getmakevars(filename):
variables = {}
fp = open(filename)
pendingline = ""
try:
while 1:
line = fp.readline()
if pendingline:
line = pendingline + line
pendingline = ""
if not line:
break
if line.endswith('\\\n'):
pendingline = line[:-2]
matchobj = makevardef.match(line)
if not matchobj:
continue
(name, value) = matchobj.group(1, 2)
# Strip trailing comment
i = value.find('#')
if i >= 0:
value = value[:i]
value = value.strip()
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 = re.compile('^([a-zA-Z0-9_]+)=(.*)')
def getsetupinfo(filename):
modules = {}
variables = {}
fp = open(filename)
pendingline = ""
try:
while 1:
line = fp.readline()
if pendingline:
line = pendingline + line
pendingline = ""
if not line:
break
# Strip comments
i = line.find('#')
if i >= 0:
line = line[:i]
if line.endswith('\\\n'):
pendingline = line[:-2]
continue
matchobj = setupvardef.match(line)
if matchobj:
(name, value) = matchobj.group(1, 2)
variables[name] = value.strip()
else:
words = line.split()
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 = sorted(d.keys())
for key in keys:
value = d[key]
print("%-15s" % key, str(value))
if __name__ == '__main__':
test()

View file

@ -0,0 +1,2 @@
import sys
sys.exit(0)

View file

@ -0,0 +1,119 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<META NAME="Generator" CONTENT="Microsoft Word 97">
<TITLE>win32</TITLE>
<META NAME="Version" CONTENT="8.0.3410">
<META NAME="Date" CONTENT="10/11/96">
<META NAME="Template" CONTENT="D:\Program Files\Microsoft Office\Office\HTML.DOT">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#ffffff">
<H1>Freeze for Win32</H1>
<P>This document describes how to use Freeze for the Win32 platform. </P>
<P>Freeze itself is a Python tool for creating stand-alone executables from Python source code. This document does not attempt to document freeze itself - only the win32 specific changes.</P>
<H2>Frozen programs under Win32</H2>
<P>Frozen programs under Win32 can (theoretically) freeze any type of program supported by Python on Win32 - At the moment, Console .EXE and NT Service .EXE programs are supported. GUI Python programs and COM .EXE programs are very nearly all ready to go.</P>
<H3>Program Dependencies</H3>
<P>The person freezing the program has control over what external DLLs are required by a frozen program. The following dependencies are supported:</P>
<H4>Minimal frozen programs</H4>
<P>These programs freeze only .py files in your program. All external DLLs are required at run-time. This includes all .pyd/.dll modules used by your program, Python20.dll, and msvcrt.dll. </P>
<P>A small Python program would typically create a .EXE around 300kb.</P>
<H4>Frozen Extension programs</H4>
<B><I><P>Note:</B></I> For Python1.5.1, you must get a patch from Guido to import.c for this to work.</P>
<P>These programs also freeze in the sources from all .pyd and .dll files used at runtime. This means the resulting .EXE is only dependent on Python20.dll and msvcrt.dll.</P>
<P>A small Python program using win32api, win32con and one or 2 other win32 extensions would typically create a .EXE around 400kb.</P>
<H4>Completely frozen programs</H4>
<P>Completely stand-alone programs, as is the default on Unix systems. These are currently not supported, mainly as the size of a decent Python program gets very large. However, by tweaking the existing Unix support, this would not be difficult to do.</P>
<H2>Freezing Extension Modules</H2>
<P>By default, a file in the main "freeze" directory called "extensions_win32.ini" is used to obtain information about frozen extensions. A typical entry is:</P>
<CODE><P>[win32api]</P>
<P>dsp=%PYTHONEX%\win32\win32api.dsp</P>
<P>cl=/I %PYTHONEX%\win32\src</P>
<P>libs=kernel32.lib user32.lib shell32.lib advapi32.lib</P>
</CODE><P>&nbsp;</P>
<P>This entry indicates that the win32api extension module is defined in the MSVC project file "<CODE>%PYTHONEX%\win32\win32api.dsp</CODE>". Note the use of<CODE> </CODE>"<CODE>%PYTHONEX%" </CODE>- most strings are substituted with environment variables. In this case, it is assumed variable PYTHONEX points to the main "Python Extensions" source directory (which is assumed to be in the same structure as the release of the extension sources).</P>
<P>An entry in a .INI file can also control specific compiler options, and also the .lib files necessary to be linked with the application.</P>
<H3>Freezing Extension Module Considerations</H3>
<P>To prevent freezing extension modules, simply exclude that module using the freeze "-x" switch.</P>
<P>Occasionally, it will be necessary to explicitly include dependent modules. For example, many win32 modules are dependent on the "pywintypes" module - for example, the win32api module. In this case, the module may be explicitly included using the freeze "-m" option.</P>
<H3>Freezing win32com and PythonCOM</H3>
<P>PythonCOM.dll can be frozen as long as you are not implementing COM Servers. Ie, you can freeze programs which control other applications, but can not implement programs that are themselves controlled by other applications.</P>
<P>If you use any of the win32com .pyd extensions (ex, axscript, mapi, internet, axcontrol), then you will need to specify an additional "-a" option to point to the win32comext directory. There is an example below.</P>
<P>The use of the "win32com.client.gencache" module is not supported (although could be quite easily??)</P>
<H2>Examples</H2>
<P>Before we start, we must:</P>
<CODE><P>D:\temp\delme&gt;set PYTHONEX=d:\src\pythonex</P>
</CODE><H3>Helloworld.py</H3>
<H4>Source Code</H4><DIR>
<DIR>
<CODE><P>import sys</P>
<P>&nbsp;</P>
<P>print " ".join( ["Hello", "world"] + sys.argv[1:] )</P></DIR>
</DIR>
</CODE><H4>Command Line used</H4><DIR>
<DIR>
<FONT FACE="Courier New" SIZE=2><P>\src\python-1.5.1\tools\freeze\freeze.py helloworld.py</P>
<P>nmake</P></DIR>
</DIR>
</FONT><P>Resulting helloworld.exe: 114,688 bytes.</P>
<H3>Helloworld2.py</H3>
<P>Uses win32api. Demonstrates requirement for pywintypes, and difference between freezing extensions and not.</P>
<H4>Source Code</H4><DIR>
<DIR>
<P>import win32api</P>
<P>print "Hello from", win32api.GetComputerName()</P></DIR>
</DIR>
<H4>Command Line used</H4>
<P>By default, win32api will be frozen in with the .EXE. If you do not provide the "pywintypes" inclusion, then the link step will fail looking for all the pywintypes modules.</P><DIR>
<DIR>
<FONT FACE="Courier New" SIZE=2><P>\src\python-1.5.1\tools\freeze\freeze.py helloworld2.py -m pywintypes</P>
<P>nmake</P></DIR>
</DIR>
</FONT><P>Resulting helloworld2.exe: 167,936 bytes</P>
<P>Simply adding win32con to the mix gives an EXE of size: 352,768 bytes.</P>
<H4>Command Line used</H4>
<P>Using this build, we are dependent at runtime on the win32api.pyd and pywintypes15.dll files.</P><DIR>
<DIR>
<P>\src\python-1.5.1\tools\freeze\freeze.py -x win32api helloworld.py</P></DIR>
</DIR>
<P>Resulting helloworld2.exe: 114,688</P>
<P>Adding win32con to this build results in a size of: 252,928</P>
<H3>Testmapi.py</H3>
<P>Uses MAPI, a PythonCOM extension, and win32api.</P>
<H4>Source Code</H4>
<P>from win32com.mapi import mapi</P>
<P>import win32api</P>
<P>mapi.MAPIInitialize( (mapi.MAPI_INIT_VERSION, 0) )</P>
<P>print "Hello from", win32api.GetComputerName()</P>
<P>mapi.MAPIUninitialize()</P>
<H4>Command Line used</H4>
<P>As it does not import pythoncom or pywintypes itself, they must be specified. As it uses the win32comext directory, -a must be used. If you have built the win32com extensions from sources, then the second -a is required.</P><DIR>
<DIR>
<CODE><P>\src\python-1.5.1\tools\freeze\freeze.py -a win32com=%PYTHONEX%\com\win32comext -a win32com.mapi=%PYTHONEX%\com\build\release testmapi.py -m pywintypes -m pythoncom</P></DIR>
</DIR>
</CODE><P>Resulting testmapi.exe: 352,768 bytes</P>
<H3>PipeTestService.py</H3>
<P>This is a standard Python demo in the Win32 extensions. It can be found in the "win32\demos\service" directory.</P>
<H4>Command Line used</H4>
<P>This will create a native NT Service EXE, dependent only on the main Python20.dll. All other modules are built-in to the final .EXE</P><DIR>
<DIR>
<CODE><P>\src\python-1.5.1\tools\freeze\freeze.py -s service %PYTHONEX%\win32\demos\service\pipeTestService.py</P></DIR>
</DIR>
<P>Resulting pipeTestService.exe: </CODE><FONT FACE="Courier New" SIZE=2>533,504 bytes.</P></FONT></BODY>
</HTML>

View file

@ -0,0 +1,148 @@
import sys, os
# 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 = "%r%r" % sys.version_info[:2]
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(r' 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(r'$(temp_dir)\%s.obj: "%s"' % (base, file))
print("\t@$(CC) -c -nologo /Fo$* $(cdl) $(c_debug) /D BUILD_FREEZE", end=' ')
print('"-I$(pythonhome)/Include" "-I$(pythonhome)/PC" \\')
print("\t\t$(cflags) $(cdebug) $(cinclude) \\")
extra = moddefn.GetCompilerOptions()
if extra:
print("\t\t%s \\" % (' '.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=", end=' ')
for addn in vars['addn_link']: print('"%s"' % (addn), end=' ')
print() ; print()
print("OBJS=", end=' ')
for obj in objects: print(r'"$(temp_dir)\%s"' % (obj), end=' ')
print() ; print()
print("LIBS=", end=' ')
for lib in libs: print('"%s"' % (lib), end=' ')
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()
print("clean:")
print("\t-del /f *.obj")
print("\t-del /f $(target).exe")