Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
1b776a27
Commit
1b776a27
authored
Jul 17, 2001
by
Guido van Rossum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Deleting merge zombie.
parent
0d00254c
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
480 deletions
+0
-480
Demo/scripts/freeze.py
Demo/scripts/freeze.py
+0
-480
No files found.
Demo/scripts/freeze.py
deleted
100755 → 0
View file @
0d00254c
#! /usr/local/bin/python
# Given a Python script, create a binary that runs the script.
# The binary is 100% independent of Python libraries and binaries.
# It will not contain any Python source code -- only "compiled" Python
# (as initialized static variables containing marshalled code objects).
# It even does the right thing for dynamically loaded modules!
# The module search path of the binary is set to the current directory.
#
# Some problems remain:
# - It's highly non-portable, since it knows about paths and libraries
# (there's a customization section though, and it knows how to
# distinguish an SGI from a Sun SPARC system -- adding knowledge
# about more systems is left as an exercise for the reader).
# - You need to have the Python source tree lying around as well as
# the "libpython.a" used to generate the Python binary.
# - For scripts that use many modules it generates absurdly large
# files (frozen.c and config.o as well as the final binary),
# and is consequently rather slow.
#
# Caveats:
# - The search for modules sometimes finds modules that are never
# actually imported since the code importing them is never executed.
# - If an imported module isn't found, you get a warning but the
# process of freezing continues. The binary will fail if it
# actually tries to import one of these modules.
# - This often happens with the module 'mac', which module 'os' tries
# to import (to determine whether it is running on a Macintosh).
# You can ignore the warning about this.
# - If the program dynamically reads or generates Python code and
# executes it, this code may reference built-in or library modules
# that aren't present in the frozen binary, and this will fail.
# - Your program may be using external data files, e.g. compiled
# forms definitions (*.fd). These aren't incorporated. Since
# sys.path in the resulting binary only contains '.', if your
# program searches its data files along sys.path (as the 'flp'
# modules does to find its forms definitions), you may need to
# change the program to extend the search path or instruct its users
# to set the environment variable PYTHONPATH to point to your data
# files.
#
# Usage hints:
# - If you have a bunch of scripts that you want to freeze, instead
# of freezing each of them separately, you might consider writing
# a tiny main script that looks at sys.argv[0] and then imports
# the corresponding module. You can then make links to the
# frozen binary named after the various scripts you support.
# Pass the additional scripts as arguments after the main script.
# A minimal script to do this is the following.
# import sys, posixpath
# exec('import ' + posixpath.basename(sys.argv[0]) + '\n')
import
os
import
sys
import
regex
import
getopt
import
regsub
import
string
import
marshal
# Function to join two pathnames with a slash in between
j
=
os
.
path
.
join
##################################
# START OF CONFIGURATION SECTION #
##################################
# Attempt to guess machine architecture
if
os
.
path
.
exists
(
'/usr/lib/libgl_s'
):
ARCH
=
'sgi'
elif
os
.
path
.
exists
(
'/etc/issue'
):
ARCH
=
'sequent'
else
:
ARCH
=
'sun4'
# Site parametrizations (change to match your site)
CC
=
'cc'
# C compiler
TOP
=
'/ufs/guido/src'
# Parent of all source trees
PYTHON
=
j
(
TOP
,
'python'
)
# Top of the Python source tree
SRC
=
j
(
PYTHON
,
'src'
)
# Python source directory
BLD
=
j
(
PYTHON
,
'build.'
+
ARCH
)
# Python build directory
#BLD = SRC # Use this if you build in SRC
LIBINST
=
'/ufs/guido/src/python/irix4/tmp/lib/python/lib'
# installed libraries
INCLINST
=
'/ufs/guido/src/python/irix4/tmp/include/Py'
# installed include files
# Other packages (change to match your site)
DL
=
j
(
TOP
,
'dl'
)
# Top of the dl source tree
DL_DLD
=
j
(
TOP
,
'dl-dld'
)
# The dl-dld source directory
DLD
=
j
(
TOP
,
'dld-3.2.3'
)
# The dld source directory
FORMS
=
j
(
TOP
,
'forms'
)
# Top of the FORMS source tree
STDWIN
=
j
(
TOP
,
'stdwin'
)
# Top of the STDWIN source tree
READLINE
=
j
(
TOP
,
'readline.'
+
ARCH
)
# Top of the GNU Readline source tree
SUN_X11
=
'/usr/local/X11R5/lib/libX11.a'
# File names (usually no need to change)
LIBP
=
[
# Main Python libraries
j
(
LIBINST
,
'libPython.a'
),
j
(
LIBINST
,
'libParser.a'
),
j
(
LIBINST
,
'libObjects.a'
),
j
(
LIBINST
,
'libModules.a'
)
]
CONFIG_IN
=
j
(
LIBINST
,
'config.c.in'
)
# Configuration source file
FMAIN
=
j
(
LIBINST
,
'frozenmain.c'
)
# Special main source file
# Libraries needed when linking. First tuple item is built-in module
# for which it is needed (or '*' for always), rest are ld arguments.
# There is a separate list per architecture.
libdeps_sgi
=
[
\
(
'stdwin'
,
j
(
STDWIN
,
'Build/'
+
ARCH
+
'/x11/lib/lib.a'
)),
\
(
'fl'
,
j
(
FORMS
,
'FORMS/libforms.a'
),
'-lfm_s'
),
\
(
'*'
,
j
(
READLINE
,
'libreadline.a'
),
'-ltermcap'
),
\
(
'al'
,
'-laudio'
),
\
(
'sv'
,
'-lsvideo'
,
'-lXext'
),
\
(
'cd'
,
'-lcdaudio'
,
'-lds'
),
\
(
'cl'
,
'-lcl'
),
\
(
'imgfile'
,
'-limage'
,
'-lgutil'
,
'-lm'
),
\
(
'mpz'
,
'/ufs/guido/src/gmp/libgmp.a'
),
\
(
'*'
,
'-lsun'
),
\
(
'*'
,
j
(
DL
,
'libdl.a'
),
'-lmld'
),
\
(
'*'
,
'-lmpc'
),
\
(
'fm'
,
'-lfm_s'
),
\
(
'gl'
,
'-lgl_s'
,
'-lX11_s'
),
\
(
'stdwin'
,
'-lX11_s'
),
\
(
'*'
,
'-lm'
),
\
(
'*'
,
'-lc_s'
),
\
]
libdeps_sun4
=
[
\
(
'*'
,
'-Bstatic'
),
\
(
'stdwin'
,
j
(
STDWIN
,
'Build/'
+
ARCH
+
'/x11/lib/lib.a'
)),
\
(
'*'
,
j
(
READLINE
,
'libreadline.a'
)),
\
(
'*'
,
'-lm'
),
\
(
'*'
,
j
(
DL_DLD
,
'libdl.a'
),
j
(
DLD
,
'libdld.a'
)),
\
(
'*'
,
SUN_X11
),
\
(
'*'
,
'-ltermcap'
),
\
(
'*'
,
'-lc'
),
\
]
libdeps_sequent
=
[
\
(
'*'
,
j
(
LIBINST
,
'libreadline.a'
),
'-ltermcap'
),
\
(
'*'
,
'-lsocket'
),
\
(
'*'
,
'-linet'
),
\
(
'*'
,
'-lnsl'
),
\
(
'*'
,
'-lm'
),
\
(
'*'
,
'-lc'
),
\
]
libdeps
=
eval
(
'libdeps_'
+
ARCH
)
################################
# END OF CONFIGURATION SECTION #
################################
# Exception used when scanfile fails
NoSuchFile
=
'NoSuchFile'
# Global options
quiet
=
0
# -q
verbose
=
0
# -v
noexec
=
0
# -n
nowrite
=
0
# -N
ofile
=
'a.out'
# -o file
# Main program -- argument parsing etc.
def
main
():
global
quiet
,
verbose
,
noexec
,
nowrite
,
ofile
try
:
opts
,
args
=
getopt
.
getopt
(
sys
.
argv
[
1
:],
'nNo:qv'
)
except
getopt
.
error
,
msg
:
usage
(
str
(
msg
))
sys
.
exit
(
2
)
for
o
,
a
in
opts
:
if
o
==
'-n'
:
noexec
=
1
if
o
==
'-N'
:
nowrite
=
1
if
o
==
'-o'
:
ofile
=
a
if
o
==
'-q'
:
verbose
=
0
;
quiet
=
1
if
o
==
'-v'
:
verbose
=
verbose
+
1
;
quiet
=
0
if
len
(
args
)
<
1
:
usage
(
'please pass at least one file argument'
)
sys
.
exit
(
2
)
process
(
args
[
0
],
args
[
1
:])
# Print usage message to stderr
def
usage
(
*
msgs
):
sys
.
stdout
=
sys
.
stderr
for
msg
in
msgs
:
print
msg
print
'Usage: freeze [options] scriptfile [modulefile ...]'
print
'-n : generate the files but don
\
'
t compile and link'
print
'-N : don
\
'
t write frozen.c (do compile unless -n given)'
print
'-o file : binary output file (default a.out)'
print
'-q : quiet (no messages at all except errors)'
print
'-v : verbose (lots of extra messages)'
# Process the script file
def
process
(
filename
,
addmodules
):
global
noexec
#
if
not
quiet
:
print
'Computing needed modules ...'
todo
=
{}
todo
[
'__main__'
]
=
filename
for
name
in
addmodules
:
mod
=
os
.
path
.
basename
(
name
)
if
mod
[
-
3
:]
==
'.py'
:
mod
=
mod
[:
-
3
]
todo
[
mod
]
=
name
try
:
dict
=
closure
(
todo
)
except
NoSuchFile
,
filename
:
sys
.
stderr
.
write
(
'Can
\
'
t open file %s
\
n
'
%
filename
)
sys
.
exit
(
1
)
#
mods
=
dict
.
keys
()
mods
.
sort
()
#
if
verbose
:
print
'%-15s %s'
%
(
'Module'
,
'Filename'
)
for
mod
in
mods
:
print
'%-15s %s'
%
(
`mod`
,
dict
[
mod
])
#
if
not
quiet
:
print
'Looking for dynamically linked modules ...'
dlmodules
=
[]
objs
=
[]
libs
=
[]
for
mod
in
mods
:
if
dict
[
mod
][
-
2
:]
==
'.o'
:
if
verbose
:
print
'Found'
,
mod
,
dict
[
mod
]
dlmodules
.
append
(
mod
)
objs
.
append
(
dict
[
mod
])
libsname
=
dict
[
mod
][:
-
2
]
+
'.libs'
try
:
f
=
open
(
libsname
,
'r'
)
except
IOError
:
f
=
None
if
f
:
libtext
=
f
.
read
()
f
.
close
()
for
lib
in
string
.
split
(
libtext
):
if
lib
in
libs
:
libs
.
remove
(
lib
)
libs
.
append
(
lib
)
#
if
not
nowrite
:
if
not
quiet
:
print
'Writing frozen.c ...'
writefrozen
(
'frozen.c'
,
dict
)
else
:
if
not
quiet
:
print
'NOT writing frozen.c ...'
#
## if not dlmodules:
if
0
:
config
=
CONFIG
if
not
quiet
:
print
'Using existing'
,
config
,
'...'
else
:
config
=
'tmpconfig.c'
if
nowrite
:
if
not
quiet
:
print
'NOT writing config.c ...'
else
:
if
not
quiet
:
print
'Writing config.c with dl modules ...'
f
=
open
(
CONFIG_IN
,
'r'
)
g
=
open
(
config
,
'w'
)
m1
=
regex
.
compile
(
'-- ADDMODULE MARKER 1 --'
)
m2
=
regex
.
compile
(
'-- ADDMODULE MARKER 2 --'
)
builtinmodules
=
[]
stdmodules
=
(
'sys'
,
'__main__'
,
'__builtin__'
,
'marshal'
)
todomodules
=
builtinmodules
+
dlmodules
for
mod
in
dict
.
keys
():
if
dict
[
mod
]
==
'<builtin>'
and
\
mod
not
in
stdmodules
:
builtinmodules
.
append
(
mod
)
while
1
:
line
=
f
.
readline
()
if
not
line
:
break
g
.
write
(
line
)
if
m1
.
search
(
line
)
>=
0
:
if
verbose
:
print
'Marker 1 ...'
for
mod
in
todomodules
:
g
.
write
(
'extern void init'
+
\
mod
+
'();
\
n
'
)
if
m2
.
search
(
line
)
>=
0
:
if
verbose
:
print
'Marker 2 ...'
for
mod
in
todomodules
:
g
.
write
(
'{"'
+
mod
+
\
'", init'
+
mod
+
'},
\
n
'
)
g
.
close
()
#
if
not
quiet
:
if
noexec
:
print
'Generating compilation commands ...'
else
:
print
'Starting compilation ...'
defs
=
[
'-DNO_MAIN'
,
'-DUSE_FROZEN'
,
'-DPYTHONPATH=
\
'
"."
\
'
'
]
#
incs
=
[
'-I.'
,
'-I'
+
INCLINST
]
if
dict
.
has_key
(
'stdwin'
):
incs
.
append
(
'-I'
+
j
(
STDWIN
,
'H'
))
#
srcs
=
[
config
,
FMAIN
]
#
if
type
(
LIBP
)
==
type
(
''
):
libs
.
append
(
LIBP
)
else
:
for
lib
in
LIBP
:
libs
.
append
(
lib
)
for
item
in
libdeps
:
m
=
item
[
0
]
if
m
==
'*'
or
dict
.
has_key
(
m
):
for
l
in
item
[
1
:]:
if
l
in
libs
:
libs
.
remove
(
l
)
libs
.
append
(
l
)
#
sts
=
0
#
cmd
=
CC
+
' -c'
cmd
=
cmd
+
' '
+
string
.
join
(
defs
)
cmd
=
cmd
+
' '
+
string
.
join
(
incs
)
cmd
=
cmd
+
' '
+
string
.
join
(
srcs
)
print
cmd
#
if
not
noexec
:
sts
=
os
.
system
(
cmd
)
if
sts
:
print
'Exit status'
,
sts
,
'-- turning on -n'
noexec
=
1
#
for
s
in
srcs
:
s
=
os
.
path
.
basename
(
s
)
if
s
[
-
2
:]
==
'.c'
:
s
=
s
[:
-
2
]
o
=
s
+
'.o'
objs
.
insert
(
0
,
o
)
#
cmd
=
CC
cmd
=
cmd
+
' '
+
string
.
join
(
objs
)
cmd
=
cmd
+
' '
+
string
.
join
(
libs
)
cmd
=
cmd
+
' -o '
+
ofile
print
cmd
#
if
not
noexec
:
sts
=
os
.
system
(
cmd
)
if
sts
:
print
'Exit status'
,
sts
else
:
print
'Done.'
#
if
not
quiet
and
not
noexec
and
sts
==
0
:
print
'Note: consider this:'
;
print
'
\
t
strip'
,
ofile
#
sys
.
exit
(
sts
)
# Generate code for a given module
def
makecode
(
filename
):
if
filename
[
-
2
:]
==
'.o'
:
return
None
try
:
f
=
open
(
filename
,
'r'
)
except
IOError
:
return
None
if
verbose
:
print
'Making code from'
,
filename
,
'...'
text
=
f
.
read
()
code
=
compile
(
text
,
filename
,
'exec'
)
f
.
close
()
return
marshal
.
dumps
(
code
)
# Write the C source file containing the frozen Python code
def
writefrozen
(
filename
,
dict
):
f
=
open
(
filename
,
'w'
)
codelist
=
[]
for
mod
in
dict
.
keys
():
codestring
=
makecode
(
dict
[
mod
])
if
codestring
is
not
None
:
codelist
.
append
((
mod
,
codestring
))
write
=
sys
.
stdout
.
write
save_stdout
=
sys
.
stdout
try
:
sys
.
stdout
=
f
for
mod
,
codestring
in
codelist
:
if
verbose
:
write
(
'Writing initializer for %s
\
n
'
%
mod
)
print
'static unsigned char M_'
+
mod
+
'['
+
\
str
(
len
(
codestring
))
+
'+1] = {'
for
i
in
range
(
0
,
len
(
codestring
),
16
):
for
c
in
codestring
[
i
:
i
+
16
]:
print
str
(
ord
(
c
))
+
','
,
print
print
'};'
print
'struct frozen {'
print
' char *name;'
print
' unsigned char *code;'
print
' int size;'
print
'} frozen_modules[] = {'
for
mod
,
codestring
in
codelist
:
print
' {"'
+
mod
+
'",'
,
print
'M_'
+
mod
+
','
,
print
str
(
len
(
codestring
))
+
'},'
print
' {0, 0, 0} /* sentinel */'
print
'};'
finally
:
sys
.
stdout
=
save_stdout
f
.
close
()
# Determine the names and filenames of the modules imported by the
# script, recursively. This is done by scanning for lines containing
# import statements. (The scanning has only superficial knowledge of
# Python syntax and no knowledge of semantics, so in theory the result
# may be incorrect -- however this is quite unlikely if you don't
# intentionally obscure your Python code.)
# Compute the closure of scanfile() -- special first file because of script
def
closure
(
todo
):
done
=
{}
while
todo
:
newtodo
=
{}
for
modname
in
todo
.
keys
():
if
not
done
.
has_key
(
modname
):
filename
=
todo
[
modname
]
if
filename
is
None
:
filename
=
findmodule
(
modname
)
done
[
modname
]
=
filename
if
filename
in
(
'<builtin>'
,
'<unknown>'
):
continue
modules
=
scanfile
(
filename
)
for
m
in
modules
:
if
not
done
.
has_key
(
m
):
newtodo
[
m
]
=
None
todo
=
newtodo
return
done
# Scan a file looking for import statements
importstr
=
'
\
(^
\
|:
\
)[
\
t]*import[
\
t
]+
\
([
a
-zA-Z0-9_,
\
t
]+
\
)
'
fromstr = '
\
(
^
\
|
:
\
)[
\
t
]
*
from
[
\
t
]
+
\
([
a
-
zA
-
Z0
-
9
_
]
+
\
)[
\
t
]
+
import
[
\
t
]
+
'
isimport = regex.compile(importstr)
isfrom = regex.compile(fromstr)
def scanfile(filename):
allmodules = {}
try:
f = open(filename, 'r')
except IOError, msg:
raise NoSuchFile, filename
while 1:
line = f.readline()
if not line: break # EOF
while line[-2:] == '
\\\
n
': # Continuation line
line = line[:-2] + '
'
line = line + f.readline()
if isimport.search(line) >= 0:
rawmodules = isimport.group(2)
modules = string.splitfields(rawmodules, '
,
')
for i in range(len(modules)):
modules[i] = string.strip(modules[i])
elif isfrom.search(line) >= 0:
modules = [isfrom.group(2)]
else:
continue
for mod in modules:
allmodules[mod] = None
f.close()
return allmodules.keys()
# Find the file containing a module, given its name; None if not found
builtins = sys.builtin_module_names + ['
sys
']
def findmodule(modname):
if modname in builtins: return '
<
builtin
>
'
for dirname in sys.path:
dlfullname = os.path.join(dirname, modname + '
module
.
o
')
try:
f = open(dlfullname, 'r')
except IOError:
f = None
if f:
f.close()
return dlfullname
fullname = os.path.join(dirname, modname + '
.
py
')
try:
f = open(fullname, 'r')
except IOError:
continue
f.close()
return fullname
if not quiet:
sys.stderr.write('
Warning
:
module
%
s
not
found
\
n
' % modname)
return '
<
unknown
>
'
# Call the main program
main()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment