Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e956386

Browse files
committed
Jaap V's version
1 parent 6d67b60 commit e956386

1 file changed

Lines changed: 312 additions & 0 deletions

File tree

Tools/freeze/nfreeze.py

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
#! /usr/local/bin/python
2+
3+
# "Freeze" a Python script into a binary.
4+
# Usage: see variable usage_msg below (before the imports!)
5+
6+
# This version builds the frozen binary in a temporary directory;
7+
# courtesy Jaap Vermeulen. Use the -l option to get the functionality
8+
# of the standard version.
9+
10+
# HINTS:
11+
# - Edit the lines marked XXX below to localize.
12+
# - You must have done "make inclinstall libainstall" in the Python
13+
# build directory.
14+
# - The script should not use dynamically loaded modules
15+
# (*.so on most systems).
16+
17+
18+
# Usage message
19+
20+
usage_msg = """
21+
usage: freeze [-p prefix] [-e extension] [-l] ... script [module] ...
22+
23+
-p prefix: This is the prefix used when you ran
24+
'Make inclinstall libainstall' in the Python build directory.
25+
(If you never ran this, freeze won't work.)
26+
The default is /usr/local.
27+
28+
-e extension: A directory containing additional .o files that
29+
may be used to resolve modules. This directory
30+
should also have a Setup file describing the .o files.
31+
More than one -e option may be given.
32+
33+
-l: Local compilation. Instead of using a temporary directory
34+
that is removed after succesful compilation, the current
35+
directory is used and temporary files are not removed.
36+
37+
script: The Python script to be executed by the resulting binary.
38+
39+
module ...: Additional Python modules (referenced by pathname)
40+
that will be included in the resulting binary. These
41+
may be .py or .pyc files.
42+
"""
43+
44+
45+
# XXX Change the following line to point to your Tools/freeze directory
46+
PACK = '/ufs/guido/src/python/Tools/freeze'
47+
48+
# XXX Change the following line to point to your install prefix
49+
PREFIX = '/usr/local'
50+
51+
# XXX Change the following line to point to your favority temporary directory
52+
TMPDIR = '/usr/tmp'
53+
54+
55+
# Import standard modules
56+
57+
import cmp
58+
import getopt
59+
import os
60+
import string
61+
import sys
62+
import addpack
63+
64+
65+
# Set the directory to look for the freeze-private modules
66+
67+
dir = os.path.dirname(sys.argv[0])
68+
if dir:
69+
pack = dir
70+
else:
71+
pack = PACK
72+
addpack.addpack(pack)
73+
74+
75+
# Establish temporary directory name
76+
77+
tmpdir = os.path.join(TMPDIR, 'freeze.' + `os.getpid()`)
78+
79+
80+
# Import the freeze-private modules
81+
82+
import checkextensions
83+
import findmodules
84+
import makeconfig
85+
import makefreeze
86+
import makemakefile
87+
import parsesetup
88+
89+
90+
# Main program
91+
92+
def main():
93+
# module variable
94+
global tmpdir
95+
96+
# overridable context
97+
prefix = PREFIX # settable with -p option
98+
extensions = []
99+
path = sys.path
100+
101+
# output files
102+
frozen_c = 'frozen.c'
103+
config_c = 'config.c'
104+
target = 'a.out' # normally derived from script name
105+
makefile = 'Makefile'
106+
107+
# parse command line
108+
try:
109+
opts, args = getopt.getopt(sys.argv[1:], 'e:p:l')
110+
except getopt.error, msg:
111+
usage('getopt error: ' + str(msg))
112+
113+
# proces option arguments
114+
for o, a in opts:
115+
if o == '-e':
116+
extensions.append(a)
117+
if o == '-l':
118+
tmpdir = None
119+
if o == '-p':
120+
prefix = a
121+
122+
# locations derived from options
123+
binlib = os.path.join(prefix, 'lib/python/lib')
124+
incldir = os.path.join(prefix, 'include/Py')
125+
config_c_in = os.path.join(binlib, 'config.c.in')
126+
frozenmain_c = os.path.join(binlib, 'frozenmain.c')
127+
makefile_in = os.path.join(binlib, 'Makefile')
128+
defines = ['-DHAVE_CONFIG_H', '-DUSE_FROZEN', '-DNO_MAIN',
129+
'-DPYTHONPATH=\\"$(PYTHONPATH)\\"']
130+
includes = ['-I' + incldir, '-I' + binlib]
131+
132+
# sanity check of directories and files
133+
for dir in [prefix, binlib, incldir] + extensions:
134+
if not os.path.exists(dir):
135+
usage('needed directory %s not found' % dir)
136+
if not os.path.isdir(dir):
137+
usage('%s: not a directory' % dir)
138+
for file in config_c_in, makefile_in, frozenmain_c:
139+
if not os.path.exists(file):
140+
usage('needed file %s not found' % file)
141+
if not os.path.isfile(file):
142+
usage('%s: not a plain file' % file)
143+
for dir in extensions:
144+
setup = os.path.join(dir, 'Setup')
145+
if not os.path.exists(setup):
146+
usage('needed file %s not found' % setup)
147+
if not os.path.isfile(setup):
148+
usage('%s: not a plain file' % setup)
149+
150+
# check that enough arguments are passed
151+
if not args:
152+
usage('at least one filename argument required')
153+
154+
# check that file arguments exist
155+
for arg in args:
156+
if not os.path.exists(arg):
157+
usage('argument %s not found' % arg)
158+
if not os.path.isfile(arg):
159+
usage('%s: not a plain file' % arg)
160+
161+
# process non-option arguments
162+
scriptfile = args[0]
163+
modules = args[1:]
164+
165+
# derive target name from script name
166+
base = os.path.basename(scriptfile)
167+
base, ext = os.path.splitext(base)
168+
if base:
169+
if base != scriptfile:
170+
target = base
171+
else:
172+
target = base + '.bin'
173+
174+
# use temporary directory
175+
if tmpdir:
176+
try: os.mkdir(tmpdir, 0700)
177+
except os.error, errmsg:
178+
sys.stderr.write('mkdir: (%s) %s\n' % errmsg)
179+
sys.stderr.write('Error: cannot create temporary directory: %s\n' % (tmpdir,))
180+
sys.exit(2)
181+
frozen_c = os.path.join(tmpdir, frozen_c)
182+
config_c = os.path.join(tmpdir, config_c)
183+
makefile = os.path.join(tmpdir, makefile)
184+
185+
dict = findmodules.findmodules(scriptfile, modules, path)
186+
187+
# Actual work starts here...
188+
189+
backup = frozen_c + '~'
190+
try:
191+
os.rename(frozen_c, backup)
192+
except os.error:
193+
backup = None
194+
outfp = open(frozen_c, 'w')
195+
try:
196+
makefreeze.makefreeze(outfp, dict)
197+
finally:
198+
outfp.close()
199+
if backup:
200+
if cmp.cmp(backup, frozen_c):
201+
sys.stderr.write('%s not changed, not written\n' %
202+
frozen_c)
203+
os.rename(backup, frozen_c)
204+
205+
builtins = []
206+
unknown = []
207+
mods = dict.keys()
208+
mods.sort()
209+
for mod in mods:
210+
if dict[mod] == '<builtin>':
211+
builtins.append(mod)
212+
elif dict[mod] == '<unknown>':
213+
unknown.append(mod)
214+
215+
addfiles = []
216+
if unknown:
217+
addfiles, addmods = \
218+
checkextensions.checkextensions(unknown, extensions)
219+
for mod in addmods:
220+
unknown.remove(mod)
221+
builtins = builtins + addmods
222+
if unknown:
223+
sys.stderr.write('Warning: unknown modules remain: %s\n' %
224+
string.join(unknown))
225+
226+
builtins.sort()
227+
infp = open(config_c_in)
228+
backup = config_c + '~'
229+
try:
230+
os.rename(config_c, backup)
231+
except os.error:
232+
backup = None
233+
outfp = open(config_c, 'w')
234+
try:
235+
makeconfig.makeconfig(infp, outfp, builtins)
236+
finally:
237+
outfp.close()
238+
infp.close()
239+
if backup:
240+
if cmp.cmp(backup, config_c):
241+
sys.stderr.write('%s not changed, not written\n' %
242+
config_c)
243+
os.rename(backup, config_c)
244+
245+
cflags = defines + includes + ['$(OPT)']
246+
libs = []
247+
for n in 'Modules', 'Python', 'Objects', 'Parser':
248+
n = 'lib%s.a' % n
249+
n = os.path.join(binlib, n)
250+
libs.append(n)
251+
252+
makevars = parsesetup.getmakevars(makefile_in)
253+
somevars = {}
254+
for key in makevars.keys():
255+
somevars[key] = makevars[key]
256+
257+
somevars['CFLAGS'] = string.join(cflags) # override
258+
files = ['$(OPT)', config_c, frozen_c, frozenmain_c] + \
259+
addfiles + libs + \
260+
['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
261+
262+
backup = makefile + '~'
263+
try:
264+
os.rename(makefile, backup)
265+
except os.error:
266+
backup = None
267+
outfp = open(makefile, 'w')
268+
try:
269+
makemakefile.makemakefile(outfp, somevars, files, target)
270+
finally:
271+
outfp.close()
272+
if backup:
273+
if not cmp.cmp(backup, makefile):
274+
print 'previous Makefile saved as', backup
275+
276+
# Done!
277+
278+
if tmpdir:
279+
# Run make
280+
curdir = os.getcwd()
281+
os.chdir(tmpdir)
282+
status = os.system('make > /dev/null')
283+
os.chdir(curdir)
284+
285+
if status:
286+
sys.stderr.write('Compilation failed. Files left in %s\n' %
287+
(tmpdir,))
288+
else:
289+
tmptarget = os.path.join(tmpdir, target)
290+
try: os.rename(tmptarget, target)
291+
except os.error:
292+
os.system('cp %s %s' % (tmptarget, target))
293+
os.system('rm -rf %s' % (tmpdir,))
294+
print 'Frozen target:', target
295+
tmpdir = None
296+
else:
297+
print 'Now run make to build the target:', target
298+
299+
300+
# Print usage message and exit
301+
302+
def usage(msg = None):
303+
if msg:
304+
sys.stderr.write(str(msg) + '\n')
305+
sys.stderr.write(usage_msg)
306+
sys.exit(2)
307+
308+
309+
try: main()
310+
finally:
311+
if tmpdir:
312+
os.system('rm -rf %s' % (tmpdir,))

0 commit comments

Comments
 (0)