OK, now it uses sys.[exec_]prefix and supports

a -o option to specify an output directory.  *Much* more convenient.
Removed a whole lot of hullabaloo from the README file, too.
This commit is contained in:
Guido van Rossum 1996-08-26 05:14:20 +00:00
parent 6498cad34e
commit 96c4dd95cf
2 changed files with 68 additions and 131 deletions

View File

@ -69,63 +69,16 @@ to run.)
How do I use Freeze?
--------------------
Ideally, you should be able to use it as follows:
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 /ufs/guido/src/python/Tools/freeze/freeze.py).
such as /usr/joe/python/Tools/freeze/freeze.py).
Unfortunately, this doesn't work. Well, it might, but somehow it's
extremely unlikely that it'll work on the first try. (If it does,
skip to the next section.) Most likely you'll get this error message:
needed directory /usr/local/lib/python/lib not found
The reason is that Freeze require that some files that are normally
kept inside the Python build tree are installed, and it searches for
it in the default install location. (The default install prefix is
/usr/local; these particular files are installed at lib/python/lib
under the install prefix.)
The particular set of files needed is installed only if you run "make
libainstall" (note: "liba", not "lib") in the Python build tree (which
is the tree where you build Python -- often, but not necessarily, this
is also the Python source tree). If you have in fact done a "make
libainstall" but used a different prefix, all you need to do is pass
that same prefix to Freeze with the -p option:
python freeze.py -p your-prefix hello.py
If you haven't run "make libainstall" yet, you should do it now
(perhaps figuring out first *where* you want everything to be
installed).
How do I configure Freeze?
--------------------------
It's a good idea to change the first line marked with XXX in freeze.py
(an assignment to variable PACK) to point to the absolute pathname of
the directory where Freeze lives (Tools/freeze in the Python source
tree.) This makes it possible to call Freeze from other directories.
You can also edit the assignment to variable PREFIX (also marked with
XXX) -- this saves a lot of -p options.
How do I use Freeze with extensions modules?
--------------------------------------------
XXX to be written. (In short: pass -e extensionbuilddir.)
How do I use Freeze with dynamically loaded extension modules?
--------------------------------------------------------------
XXX to be written. (In short: pass -e modulebuilddir -- this even
works if you built the modules in Python's own Modules directory.)
(With Python 1.4, freeze is much more likely to work "out of the box"
than before, provided Python has been installed properly.)
What do I do next?
@ -134,37 +87,22 @@ What do I do next?
Freeze creates three files: frozen.c, config.c and Makefile. 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". On the
other hand, if the argument was "hello", the binary will be called
"hello.bin". If you passed any other filename, all bets are off. :-)
In any case, the name of the file will be printed as the last message
from Freeze.
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.
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 -- read the text above to find out how to install
relevant parts of Python properly and how to configure Freeze to find
them.
A common problem is having installed an old version -- rerunning "make
libainstall" often clears up problems with missing modules or
libraries at link time.
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.
What is nfreeze.py?
-------------------
The script nfreeze.py is an unsupported variant on freeze.py which
creates all files in a temporary directory and runs "make" there. It
has the advantage that it doesn't overwrite files in the current
directory, but the disadvantage is that it removes all files when it
is finished.
--Guido van Rossum, CWI, Amsterdam <mailto:Guido.van.Rossum@cwi.nl>
<http://www.cwi.nl/cwi/people/Guido.van.Rossum.html>
--Guido van Rossum (home page: http://www.python.org/~guido/)

View File

@ -1,36 +1,29 @@
#! /usr/local/bin/python
# "Freeze" a Python script into a binary.
# Usage: see variable usage_msg below (before the imports!)
"""Freeze a Python script into a binary.
# HINTS:
# - Edit the lines marked XXX below to localize.
# - Make sure the #! line above matches the localizations.
# - You must have done "make inclinstall libainstall" in the Python
# build directory.
# - The script name should end in ".py".
# - The script should not use dynamically loaded modules
# (*.so on most systems).
usage: freeze [options...] script.py [module]...
Options:
# Usage message
usage_msg = """
usage: freeze [-p prefix] [-P exec_prefix] [-e extension] script.py [module]...
-p prefix: This is the prefix used when you ran
'Make inclinstall libainstall' in the Python build directory.
-p prefix: This is the prefix used when you ran ``name install''
in the Python build directory.
(If you never ran this, freeze won't work.)
The default is /usr/local.
The default is whatever sys.prefix evaluates to.
-P exec_prefix: Like -p but this is the 'exec_prefix', used to
install objects etc. The default is the value for -p.
install objects etc. The default is whatever sys.exec_prefix
evaluates to, or the -p argument if given.
-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.
More than one -e option may be given.
-o dir: Directory where the output files are created; default '.'.
Arguments:
script.py: The Python script to be executed by the resulting binary.
It *must* end with a .py suffix!
@ -43,22 +36,11 @@ NOTES:
In order to use freeze successfully, you must have built Python and
installed it ("make install").
The -p and -P options passed into the freeze script must correspond to
the --prefix and --exec-prefix options passed into Python's configure
script.
The script should not use modules provided only as shared libraries;
if it does, the resulting binary is not self-contained.
"""
# XXX Change the following line to point to your Tools/freeze directory
PACK = '/home/guido/python/src/Tools/freeze'
# XXX Change the following line to point to your install prefix
PREFIX = '/usr/local'
# XXX Change the following line to point to your install exec_prefix
EXEC_PREFIX = None # If None, use -p option for default
# Import standard modules
import cmp
@ -69,16 +51,6 @@ import sys
import addpack
# Set the directory to look for the freeze-private modules
dir = os.path.dirname(sys.argv[0])
if dir:
pack = dir
else:
pack = PACK
addpack.addpack(pack)
# Import the freeze-private modules
import checkextensions
@ -93,10 +65,11 @@ import parsesetup
def main():
# overridable context
prefix = PREFIX # settable with -p option
prefix = None # settable with -p option
exec_prefix = None # settable with -P option
extensions = []
path = sys.path
odir = ''
# output files
frozen_c = 'frozen.c'
@ -106,7 +79,7 @@ def main():
# parse command line
try:
opts, args = getopt.getopt(sys.argv[1:], 'e:p:P:')
opts, args = getopt.getopt(sys.argv[1:], 'e:o:p:P:')
except getopt.error, msg:
usage('getopt error: ' + str(msg))
@ -114,20 +87,26 @@ def main():
for o, a in opts:
if o == '-e':
extensions.append(a)
if o == '-o':
odir = a
if o == '-p':
prefix = a
if o == '-P':
exec_prefix = a
# default exec_prefix
if exec_prefix is None:
exec_prefix = EXEC_PREFIX
if exec_prefix is None:
# 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
# locations derived from options
binlib = os.path.join(exec_prefix, 'lib/python1.4/config')
incldir = os.path.join(prefix, 'include/python1.4')
version = sys.version[:3]
binlib = os.path.join(exec_prefix, 'lib/python%s/config' % version)
incldir = os.path.join(prefix, 'include/python%s' % version)
config_c_in = os.path.join(binlib, 'config.c.in')
frozenmain_c = os.path.join(binlib, 'frozenmain.c')
getpath_c = os.path.join(binlib, 'getpath.c')
@ -182,6 +161,22 @@ def main():
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)))
if 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)
# Actual work starts here...
dict = findmodules.findmodules(scriptfile, modules, path)
@ -260,7 +255,7 @@ def main():
somevars[key] = makevars[key]
somevars['CFLAGS'] = string.join(cflags) # override
files = ['$(OPT)', '$(LDFLAGS)', config_c, frozen_c] + \
files = ['$(OPT)', '$(LDFLAGS)', base_config_c, base_frozen_c] + \
supp_sources + addfiles + libs + \
['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
@ -271,7 +266,7 @@ def main():
backup = None
outfp = open(makefile, 'w')
try:
makemakefile.makemakefile(outfp, somevars, files, target)
makemakefile.makemakefile(outfp, somevars, files, base_target)
finally:
outfp.close()
if backup:
@ -284,13 +279,17 @@ def main():
# Done!
print 'Now run make to build the target:', target
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 = None):
sys.stderr.write(usage_msg)
sys.stderr.write(__doc__)
# Put the error last since the usage message scrolls off the screen
if msg:
sys.stderr.write('\nError: ' + str(msg) + '\n')