5
import TaskGen,Utils,Utils,Runner,Options,Build
6
from Logs import debug,warn
7
from TaskGen import extension,taskgen,before,after,feature
8
from Configure import conf
12
self.default_install_path='${PYTHONDIR}'
13
self.uselib=self.to_list(self.uselib)
14
if not'PYEXT'in self.uselib:
15
self.uselib.append('PYEXT')
16
self.env['MACBUNDLE']=True
17
def pyext_shlib_ext(self):
18
self.env['shlib_PATTERN']=self.env['pyext_PATTERN']
19
def init_pyembed(self):
20
self.uselib=self.to_list(self.uselib)
21
if not'PYEMBED'in self.uselib:
22
self.uselib.append('PYEMBED')
23
def process_py(self,node):
25
class py_taskgen(TaskGen.task_gen):
26
def __init__(self,env=None):
27
TaskGen.task_gen.__init__(self)
28
self.default_install_path='${PYTHONDIR}'
32
for filename in self.to_list(self.source):
33
node=self.path.find_resource(filename)
35
files_to_install.append(node.abspath())
37
node=self.path.find_or_declare(filename)
39
raise Utils.WafError("Cannot install file %s: not found in %s"%(filename,self.path))
41
files_to_install.append(node.abspath(self.env))
42
installed_files=Build.bld.install_files(self.install_path,files_to_install,self.env,self.chmod)
43
if not installed_files:
45
if Options.commands['uninstall']:
46
print"* removing byte compiled python files"
47
for fname in installed_files:
57
if self.env['PYC']or self.env['PYO']:
58
print"* byte compiling python files"
61
import sys, py_compile
62
for pyfile in sys.argv[1:]:
63
py_compile.compile(pyfile, pyfile + 'c')
65
argv=[self.env['PYTHON'],"-c",program]
66
argv.extend(installed_files)
67
retval=pproc.Popen(argv).wait()
69
raise Utils.WafError("bytecode compilation failed")
72
import sys, py_compile
73
for pyfile in sys.argv[1:]:
74
py_compile.compile(pyfile, pyfile + 'o')
76
argv=[self.env['PYTHON'],self.env['PYFLAGS_OPT'],"-c",program]
77
argv.extend(installed_files)
78
retval=pproc.Popen(argv).wait()
80
raise Utils.WafError("bytecode compilation failed")
81
def _get_python_variables(python_exe,variables,imports=['import sys']):
85
program.append("print repr(%s)"%v)
86
proc=pproc.Popen([python_exe,"-c",'\n'.join(program)],stdout=pproc.PIPE)
87
output=proc.communicate()[0].split("\n")
90
warn("Python program to extract python configuration variables failed:\n%s"%'\n'.join(["line %03i: %s"%(lineno+1,line)for lineno,line in enumerate(program)]))
98
return_values.append(None)
99
elif s[0]=="'"and s[-1]=="'":
100
return_values.append(s[1:-1])
102
return_values.append(int(s))
105
def check_python_headers(conf):
108
assert python,("python is %r !"%(python,))
110
if checks.detect_platform(None)=='darwin':
111
conf.check_tool('osx')
113
v='prefix SO SYSLIBS SHLIBS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED'.split()
114
(python_prefix,python_SO,python_SYSLIBS,python_SHLIBS,python_LIBDIR,python_LIBPL,INCLUDEPY,Py_ENABLE_SHARED)=_get_python_variables(python,["get_config_var('%s')"%x for x in v],['from distutils.sysconfig import get_config_var'])
116
conf.fatal("Python development headers not found (-v for details).")
117
Runner.print_log("""Configuration returned from %r:
125
Py_ENABLE_SHARED = %r
126
"""%(python,python_prefix,python_SO,python_SYSLIBS,python_SHLIBS,python_LIBDIR,python_LIBPL,INCLUDEPY,Py_ENABLE_SHARED))
127
env['pyext_PATTERN']='%s'+python_SO
128
if python_SYSLIBS is not None:
129
for lib in python_SYSLIBS.split():
130
if lib.startswith('-l'):
132
env.append_value('LIB_PYEMBED',lib)
133
if python_SHLIBS is not None:
134
for lib in python_SHLIBS.split():
135
if lib.startswith('-l'):
137
env.append_value('LIB_PYEMBED',lib)
138
lib=conf.create_library_configurator()
139
lib.name='python'+env['PYTHON_VERSION']
145
void Py_Initialize(void);
146
void Py_Finalize(void);
150
int main(int argc, char *argv[]) { Py_Initialize(); Py_Finalize(); return 0; }
152
if python_LIBDIR is not None:
153
lib.path=[python_LIBDIR]
158
if python_LIBPL is not None:
159
lib.path=[python_LIBPL]
164
lib.path=[os.path.join(python_prefix,"libs")]
165
lib.name='python'+env['PYTHON_VERSION'].replace('.','')
168
env['LIBPATH_PYEMBED']=lib.path
169
env.append_value('LIB_PYEMBED',lib.name)
170
if(sys.platform=='win32'or sys.platform.startswith('os2')or sys.platform=='darwin'or Py_ENABLE_SHARED):
171
env['LIBPATH_PYEXT']=env['LIBPATH_PYEMBED']
172
env['LIB_PYEXT']=env['LIB_PYEMBED']
173
python_config=conf.find_program('python%s-config'%('.'.join(env['PYTHON_VERSION'].split('.')[:2])),var='PYTHON_CONFIG')
176
for incstr in os.popen("%s %s --includes"%(python,python_config)).readline().strip().split():
177
if(incstr.startswith('-I')or incstr.startswith('/I')):
179
if incstr not in includes:
180
includes.append(incstr)
181
env['CPPPATH_PYEXT']=list(includes)
182
env['CPPPATH_PYEMBED']=list(includes)
184
env['CPPPATH_PYEXT']=[INCLUDEPY]
185
env['CPPPATH_PYEMBED']=[INCLUDEPY]
187
version=os.popen("%s --version"%env['CC']).readline()
189
env.append_value('CCFLAGS_PYEMBED','-fno-strict-aliasing')
190
env.append_value('CCFLAGS_PYEXT','-fno-strict-aliasing')
192
version=os.popen("%s --version"%env['CXX']).readline()
194
env.append_value('CXXFLAGS_PYEMBED','-fno-strict-aliasing')
195
env.append_value('CXXFLAGS_PYEXT','-fno-strict-aliasing')
196
header=conf.create_header_configurator()
197
header.name='Python.h'
198
header.define='HAVE_PYTHON_H'
199
header.uselib='PYEXT'
200
header.code="#include <Python.h>\nint main(int argc, char *argv[]) { Py_Initialize(); Py_Finalize(); return 0; }"
203
conf.fatal("Python development headers not found.")
204
def check_python_version(conf,minver=None):
205
assert minver is None or isinstance(minver,tuple)
206
python=conf.env['PYTHON']
207
assert python,("python is %r !"%(python,))
208
cmd=[python,"-c","import sys\nfor x in sys.version_info: print str(x)"]
209
debug('python: Running python command %r'%cmd)
210
proc=pproc.Popen(cmd,stdout=pproc.PIPE)
211
lines=proc.communicate()[0].split()
212
assert len(lines)==5,"found %i lines, expected 5: %r"%(len(lines),lines)
213
pyver_tuple=(int(lines[0]),int(lines[1]),int(lines[2]),lines[3],int(lines[4]))
214
result=(minver is None)or(pyver_tuple>=minver)
216
pyver='.'.join([str(x)for x in pyver_tuple[:2]])
217
conf.env['PYTHON_VERSION']=pyver
218
if'PYTHONDIR'in os.environ:
219
pydir=os.environ['PYTHONDIR']
221
if sys.platform=='win32':
222
(python_LIBDEST,)=_get_python_variables(python,["get_config_var('LIBDEST')"],['from distutils.sysconfig import get_config_var'])
225
if python_LIBDEST is None:
226
if conf.env['LIBDIR']:
227
python_LIBDEST=os.path.join(conf.env['LIBDIR'],"python"+pyver)
229
python_LIBDEST=os.path.join(conf.env['PREFIX'],"lib","python"+pyver)
230
pydir=os.path.join(python_LIBDEST,"site-packages")
231
if hasattr(conf,'define'):
232
conf.define('PYTHONDIR',pydir)
233
conf.env['PYTHONDIR']=pydir
234
pyver_full='.'.join(map(str,pyver_tuple[:3]))
236
conf.check_message_custom('Python version','',pyver_full)
238
minver_str='.'.join(map(str,minver))
239
conf.check_message('Python version',">= %s"%(minver_str,),result,option=pyver_full)
241
conf.fatal("Python too old.")
242
def check_python_module(conf,module_name):
243
result=not pproc.Popen([conf.env['PYTHON'],"-c","import %s"%module_name],stderr=pproc.PIPE,stdout=pproc.PIPE).wait()
244
conf.check_message('Python module',module_name,result)
246
conf.fatal("Python module not found.")
248
python=conf.find_program('python',var='PYTHON')
251
v['PYCMD']='"import sys, py_compile;py_compile.compile(sys.argv[1], sys.argv[2])"'
253
v['PYFLAGS_OPT']='-O'
254
v['PYC']=getattr(Options.options,'pyc',1)
255
v['PYO']=getattr(Options.options,'pyo',1)
256
def set_options(opt):
257
opt.add_option('--nopyc',action='store_false',default=1,help='no pyc files (configuration)',dest='pyc')
258
opt.add_option('--nopyo',action='store_false',default=1,help='no pyo files (configuration)',dest='pyo')
261
before('apply_incpaths')(init_pyext)
262
feature('pyext')(init_pyext)
263
before('apply_bundle')(init_pyext)
264
taskgen(pyext_shlib_ext)
265
before('apply_link')(pyext_shlib_ext)
266
before('apply_lib_vars')(pyext_shlib_ext)
267
after('apply_bundle')(pyext_shlib_ext)
268
feature('pyext')(pyext_shlib_ext)
269
taskgen(init_pyembed)
270
before('apply_incpaths')(init_pyembed)
271
feature('pyembed')(init_pyembed)
272
extension(EXT_PY)(process_py)
273
conf(check_python_headers)
274
conf(check_python_version)
275
conf(check_python_module)