blob: 2588c6023244bd3b04b0d1dedde22c40fe525854 [file] [log] [blame]
Guido van Rossumdbaf3321994-10-03 10:25:54 +00001#! /usr/local/bin/python
2
Guido van Rossum00ff4331994-10-03 16:33:08 +00003# "Freeze" a Python script into a binary.
4# Usage: see first function below (before the imports!)
Guido van Rossumdbaf3321994-10-03 10:25:54 +00005
Guido van Rossum00ff4331994-10-03 16:33:08 +00006# HINTS:
7# - Edit the line at XXX below before running!
8# - You must have done "make inclinstall libainstall" in the Python
9# build directory.
10# - The script should not use dynamically loaded modules
11# (*.so on most systems).
12
13
14# XXX Change the following line to point to your Demo/freeze directory!
15pack = '/ufs/guido/src/python/Demo/freeze'
16
17
18# Print usage message and exit
19
20def usage(msg = None):
21 if msg:
22 sys.stderr.write(str(msg) + '\n')
23 sys.stderr.write('usage: freeze [-p prefix] script [module] ...\n')
24 sys.exit(2)
25
26
27# Import standard modules
28
Guido van Rossumdbaf3321994-10-03 10:25:54 +000029import getopt
Guido van Rossum00ff4331994-10-03 16:33:08 +000030import os
Guido van Rossumdbaf3321994-10-03 10:25:54 +000031import string
Guido van Rossum00ff4331994-10-03 16:33:08 +000032import sys
33import addpack
Guido van Rossumdbaf3321994-10-03 10:25:54 +000034
Guido van Rossumdbaf3321994-10-03 10:25:54 +000035
Guido van Rossum00ff4331994-10-03 16:33:08 +000036# Set the directory to look for the freeze-private modules
Guido van Rossumdbaf3321994-10-03 10:25:54 +000037
Guido van Rossum00ff4331994-10-03 16:33:08 +000038dir = os.path.dirname(sys.argv[0])
39if dir:
40 pack = dir
41addpack.addpack(pack)
Guido van Rossumdbaf3321994-10-03 10:25:54 +000042
Guido van Rossum00ff4331994-10-03 16:33:08 +000043
44# Import the freeze-private modules
45
46import findmodules
47import makeconfig
48import makefreeze
49import makemakefile
50import parsesetup
51
52hint = """
53Use the '-p prefix' command line option to specify the prefix used
54when you ran 'Make inclinstall libainstall' in the Python build directory.
55(Please specify an absolute path.)
56"""
57
58
59# Main program
60
Guido van Rossumdbaf3321994-10-03 10:25:54 +000061def main():
Guido van Rossum00ff4331994-10-03 16:33:08 +000062 # overridable context
63 prefix = '/usr/local' # settable with -p option
64 path = sys.path
65
66 # output files
67 frozen_c = 'frozen.c'
68 config_c = 'config.c'
69 target = 'a.out' # normally derived from script name
70 makefile = 'Makefile'
71
72 # parse command line
Guido van Rossumdbaf3321994-10-03 10:25:54 +000073 try:
Guido van Rossum00ff4331994-10-03 16:33:08 +000074 opts, args = getopt.getopt(sys.argv[1:], 'p:')
75 if not args:
76 raise getopt.error, 'not enough arguments'
Guido van Rossumdbaf3321994-10-03 10:25:54 +000077 except getopt.error, msg:
Guido van Rossum00ff4331994-10-03 16:33:08 +000078 usage('getopt error: ' + str(msg))
79
80 # proces option arguments
Guido van Rossumdbaf3321994-10-03 10:25:54 +000081 for o, a in opts:
Guido van Rossum00ff4331994-10-03 16:33:08 +000082 if o == '-p':
83 prefix = a
Guido van Rossumdbaf3321994-10-03 10:25:54 +000084
Guido van Rossum00ff4331994-10-03 16:33:08 +000085 # locations derived from options
86 binlib = os.path.join(prefix, 'lib/python/lib')
87 incldir = os.path.join(prefix, 'include/Py')
88 config_c_in = os.path.join(binlib, 'config.c.in')
89 frozenmain_c = os.path.join(binlib, 'frozenmain.c')
90 makefile_in = os.path.join(binlib, 'Makefile')
91 defines = ['-DHAVE_CONFIG_H', '-DUSE_FROZEN', '-DNO_MAIN',
92 '-DPTHONPATH=\\"$(PYTHONPATH)\\"']
93 includes = ['-I' + incldir, '-I' + binlib]
Guido van Rossumdbaf3321994-10-03 10:25:54 +000094
Guido van Rossum00ff4331994-10-03 16:33:08 +000095 # sanity check of locations
96 for dir in prefix, binlib, incldir:
97 if not os.path.exists(dir):
98 usage('needed directory %s not found' % dir + hint)
99 if not os.path.isdir(dir):
100 usage('%s: not a directory' % dir)
101 for file in config_c_in, makefile_in, frozenmain_c:
102 if not os.path.exists(file):
103 usage('needed file %s not found' % file)
104 if not os.path.isfile(file):
105 usage('%s: not a plain file' % file)
106
107 # check that file arguments exist
108 for arg in args:
109 if not os.path.exists(arg):
110 usage('argument %s not found' % arg)
111 if not os.path.isfile(arg):
112 usage('%s: not a plain file' % arg)
113
114 # process non-option arguments
115 scriptfile = args[0]
116 modules = args[1:]
117
118 # derive target name from script name
119 base = os.path.basename(scriptfile)
120 base, ext = os.path.splitext(base)
121 if base:
122 if base != scriptfile:
123 target = base
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000124 else:
Guido van Rossum00ff4331994-10-03 16:33:08 +0000125 target = base + '.bin'
126
127 # Actual work starts here...
128
129 dict = findmodules.findmodules(scriptfile, modules, path)
130
131 builtins = []
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000132 for mod in dict.keys():
Guido van Rossum00ff4331994-10-03 16:33:08 +0000133 if dict[mod] == '<builtin>':
134 builtins.append(mod)
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000135
Guido van Rossum00ff4331994-10-03 16:33:08 +0000136 outfp = open(frozen_c, 'w')
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000137 try:
Guido van Rossum00ff4331994-10-03 16:33:08 +0000138 makefreeze.makefreeze(outfp, dict)
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000139 finally:
Guido van Rossum00ff4331994-10-03 16:33:08 +0000140 outfp.close()
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000141
Guido van Rossum00ff4331994-10-03 16:33:08 +0000142 infp = open(config_c_in)
143 outfp = open(config_c, 'w')
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000144 try:
Guido van Rossum00ff4331994-10-03 16:33:08 +0000145 makeconfig.makeconfig(infp, outfp, builtins)
146 finally:
147 outfp.close()
148 infp.close()
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000149
Guido van Rossum00ff4331994-10-03 16:33:08 +0000150 cflags = defines + includes + ['$(OPT)']
151 libs = []
152 for n in 'Modules', 'Python', 'Objects', 'Parser':
153 n = 'lib%s.a' % n
154 n = os.path.join(binlib, n)
155 libs.append(n)
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000156
Guido van Rossum00ff4331994-10-03 16:33:08 +0000157 makevars = parsesetup.getmakevars(makefile_in)
158 somevars = {}
159 for key in makevars.keys():
160 somevars[key] = makevars[key]
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000161
Guido van Rossum00ff4331994-10-03 16:33:08 +0000162 somevars['CFLAGS'] = string.join(cflags) # override
163 files = ['$(OPT)', config_c, frozenmain_c] + libs + \
164 ['$(MODLIBS)', '$(LIBS)', '$(SYSLIBS)']
165
166 outfp = open(makefile, 'w')
167 try:
168 makemakefile.makemakefile(outfp, somevars, files, target)
169 finally:
170 outfp.close()
171
172 # Done!
173
174 print 'Now run make to build the target:', target
175
Guido van Rossumdbaf3321994-10-03 10:25:54 +0000176main()