third_party:waf: update to upstream 2.0.4 release
[vlendec/samba-autobuild/.git] / third_party / waf / waflib / Tools / python.py
1 #! /usr/bin/env python
2 # encoding: utf-8
3 # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
4
5 #!/usr/bin/env python
6 # encoding: utf-8
7 # Thomas Nagy, 2007-2015 (ita)
8 # Gustavo Carneiro (gjc), 2007
9
10 """
11 Support for Python, detect the headers and libraries and provide
12 *use* variables to link C/C++ programs against them::
13
14         def options(opt):
15                 opt.load('compiler_c python')
16         def configure(conf):
17                 conf.load('compiler_c python')
18                 conf.check_python_version((2,4,2))
19                 conf.check_python_headers()
20         def build(bld):
21                 bld.program(features='pyembed', source='a.c', target='myprog')
22                 bld.shlib(features='pyext', source='b.c', target='mylib')
23 """
24
25 import os, sys
26 from waflib import Errors, Logs, Node, Options, Task, Utils
27 from waflib.TaskGen import extension, before_method, after_method, feature
28 from waflib.Configure import conf
29
30 FRAG = '''
31 #include <Python.h>
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35         void Py_Initialize(void);
36         void Py_Finalize(void);
37 #ifdef __cplusplus
38 }
39 #endif
40 int main(int argc, char **argv)
41 {
42    (void)argc; (void)argv;
43    Py_Initialize();
44    Py_Finalize();
45    return 0;
46 }
47 '''
48 """
49 Piece of C/C++ code used in :py:func:`waflib.Tools.python.check_python_headers`
50 """
51
52 INST = '''
53 import sys, py_compile
54 py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True)
55 '''
56 """
57 Piece of Python code used in :py:class:`waflib.Tools.python.pyo` and :py:class:`waflib.Tools.python.pyc` for byte-compiling python files
58 """
59
60 DISTUTILS_IMP = ['from distutils.sysconfig import get_config_var, get_python_lib']
61
62 @before_method('process_source')
63 @feature('py')
64 def feature_py(self):
65         """
66         Create tasks to byte-compile .py files and install them, if requested
67         """
68         self.install_path = getattr(self, 'install_path', '${PYTHONDIR}')
69         install_from = getattr(self, 'install_from', None)
70         if install_from and not isinstance(install_from, Node.Node):
71                 install_from = self.path.find_dir(install_from)
72         self.install_from = install_from
73
74         ver = self.env.PYTHON_VERSION
75         if not ver:
76                 self.bld.fatal('Installing python files requires PYTHON_VERSION, try conf.check_python_version')
77
78         if int(ver.replace('.', '')) > 31:
79                 self.install_32 = True
80
81 @extension('.py')
82 def process_py(self, node):
83         """
84         Add signature of .py file, so it will be byte-compiled when necessary
85         """
86         assert(hasattr(self, 'install_path')), 'add features="py"'
87
88         # where to install the python file
89         if self.install_path:
90                 if self.install_from:
91                         self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=True)
92                 else:
93                         self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=True)
94
95         lst = []
96         if self.env.PYC:
97                 lst.append('pyc')
98         if self.env.PYO:
99                 lst.append('pyo')
100
101         if self.install_path:
102                 if self.install_from:
103                         pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.install_from)), self.env)
104                 else:
105                         pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.path)), self.env)
106         else:
107                 pyd = node.abspath()
108
109         for ext in lst:
110                 if self.env.PYTAG and not self.env.NOPYCACHE:
111                         # __pycache__ installation for python 3.2 - PEP 3147
112                         name = node.name[:-3]
113                         pyobj = node.parent.get_bld().make_node('__pycache__').make_node("%s.%s.%s" % (name, self.env.PYTAG, ext))
114                         pyobj.parent.mkdir()
115                 else:
116                         pyobj = node.change_ext(".%s" % ext)
117
118                 tsk = self.create_task(ext, node, pyobj)
119                 tsk.pyd = pyd
120
121                 if self.install_path:
122                         self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=True)
123
124 class pyc(Task.Task):
125         """
126         Byte-compiling python files
127         """
128         color = 'PINK'
129         def __str__(self):
130                 node = self.outputs[0]
131                 return node.path_from(node.ctx.launch_node())
132         def run(self):
133                 cmd = [Utils.subst_vars('${PYTHON}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd]
134                 ret = self.generator.bld.exec_command(cmd)
135                 return ret
136
137 class pyo(Task.Task):
138         """
139         Byte-compiling python files
140         """
141         color = 'PINK'
142         def __str__(self):
143                 node = self.outputs[0]
144                 return node.path_from(node.ctx.launch_node())
145         def run(self):
146                 cmd = [Utils.subst_vars('${PYTHON}', self.env), Utils.subst_vars('${PYFLAGS_OPT}', self.env), '-c', INST, self.inputs[0].abspath(), self.outputs[0].abspath(), self.pyd]
147                 ret = self.generator.bld.exec_command(cmd)
148                 return ret
149
150 @feature('pyext')
151 @before_method('propagate_uselib_vars', 'apply_link')
152 @after_method('apply_bundle')
153 def init_pyext(self):
154         """
155         Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the
156         *lib* prefix from library names.
157         """
158         self.uselib = self.to_list(getattr(self, 'uselib', []))
159         if not 'PYEXT' in self.uselib:
160                 self.uselib.append('PYEXT')
161         # override shlib_PATTERN set by the osx module
162         self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN = self.env.pyext_PATTERN
163         self.env.fcshlib_PATTERN = self.env.dshlib_PATTERN = self.env.pyext_PATTERN
164
165         try:
166                 if not self.install_path:
167                         return
168         except AttributeError:
169                 self.install_path = '${PYTHONARCHDIR}'
170
171 @feature('pyext')
172 @before_method('apply_link', 'apply_bundle')
173 def set_bundle(self):
174         """Mac-specific pyext extension that enables bundles from c_osx.py"""
175         if Utils.unversioned_sys_platform() == 'darwin':
176                 self.mac_bundle = True
177
178 @before_method('propagate_uselib_vars')
179 @feature('pyembed')
180 def init_pyembed(self):
181         """
182         Add the PYEMBED variable.
183         """
184         self.uselib = self.to_list(getattr(self, 'uselib', []))
185         if not 'PYEMBED' in self.uselib:
186                 self.uselib.append('PYEMBED')
187
188 @conf
189 def get_python_variables(self, variables, imports=None):
190         """
191         Spawn a new python process to dump configuration variables
192
193         :param variables: variables to print
194         :type variables: list of string
195         :param imports: one import by element
196         :type imports: list of string
197         :return: the variable values
198         :rtype: list of string
199         """
200         if not imports:
201                 try:
202                         imports = self.python_imports
203                 except AttributeError:
204                         imports = DISTUTILS_IMP
205
206         program = list(imports) # copy
207         program.append('')
208         for v in variables:
209                 program.append("print(repr(%s))" % v)
210         os_env = dict(os.environ)
211         try:
212                 del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool
213         except KeyError:
214                 pass
215
216         try:
217                 out = self.cmd_and_log(self.env.PYTHON + ['-c', '\n'.join(program)], env=os_env)
218         except Errors.WafError:
219                 self.fatal('The distutils module is unusable: install "python-devel"?')
220         self.to_log(out)
221         return_values = []
222         for s in out.splitlines():
223                 s = s.strip()
224                 if not s:
225                         continue
226                 if s == 'None':
227                         return_values.append(None)
228                 elif (s[0] == "'" and s[-1] == "'") or (s[0] == '"' and s[-1] == '"'):
229                         return_values.append(eval(s))
230                 elif s[0].isdigit():
231                         return_values.append(int(s))
232                 else: break
233         return return_values
234
235 @conf
236 def test_pyembed(self, mode, msg='Testing pyembed configuration'):
237         self.check(header_name='Python.h', define_name='HAVE_PYEMBED', msg=msg,
238                 fragment=FRAG, errmsg='Could not build a python embedded interpreter',
239                 features='%s %sprogram pyembed' % (mode, mode))
240
241 @conf
242 def test_pyext(self, mode, msg='Testing pyext configuration'):
243         self.check(header_name='Python.h', define_name='HAVE_PYEXT', msg=msg,
244                 fragment=FRAG, errmsg='Could not build python extensions',
245                 features='%s %sshlib pyext' % (mode, mode))
246
247 @conf
248 def python_cross_compile(self, features='pyembed pyext'):
249         """
250         For cross-compilation purposes, it is possible to bypass the normal detection and set the flags that you want:
251         PYTHON_VERSION='3.4' PYTAG='cpython34' pyext_PATTERN="%s.so" PYTHON_LDFLAGS='-lpthread -ldl' waf configure
252
253         The following variables are used:
254         PYTHON_VERSION    required
255         PYTAG             required
256         PYTHON_LDFLAGS    required
257         pyext_PATTERN     required
258         PYTHON_PYEXT_LDFLAGS
259         PYTHON_PYEMBED_LDFLAGS
260         """
261         features = Utils.to_list(features)
262         if not ('PYTHON_LDFLAGS' in self.environ or 'PYTHON_PYEXT_LDFLAGS' in self.environ or 'PYTHON_PYEMBED_LDFLAGS' in self.environ):
263                 return False
264
265         for x in 'PYTHON_VERSION PYTAG pyext_PATTERN'.split():
266                 if not x in self.environ:
267                         self.fatal('Please set %s in the os environment' % x)
268                 else:
269                         self.env[x] = self.environ[x]
270
271         xx = self.env.CXX_NAME and 'cxx' or 'c'
272         if 'pyext' in features:
273                 flags = self.environ.get('PYTHON_PYEXT_LDFLAGS', self.environ.get('PYTHON_LDFLAGS'))
274                 if flags is None:
275                         self.fatal('No flags provided through PYTHON_PYEXT_LDFLAGS as required')
276                 else:
277                         self.parse_flags(flags, 'PYEXT')
278                 self.test_pyext(xx)
279         if 'pyembed' in features:
280                 flags = self.environ.get('PYTHON_PYEMBED_LDFLAGS', self.environ.get('PYTHON_LDFLAGS'))
281                 if flags is None:
282                         self.fatal('No flags provided through PYTHON_PYEMBED_LDFLAGS as required')
283                 else:
284                         self.parse_flags(flags, 'PYEMBED')
285                 self.test_pyembed(xx)
286         return True
287
288 @conf
289 def check_python_headers(conf, features='pyembed pyext'):
290         """
291         Check for headers and libraries necessary to extend or embed python by using the module *distutils*.
292         On success the environment variables xxx_PYEXT and xxx_PYEMBED are added:
293
294         * PYEXT: for compiling python extensions
295         * PYEMBED: for embedding a python interpreter
296         """
297         features = Utils.to_list(features)
298         assert ('pyembed' in features) or ('pyext' in features), "check_python_headers features must include 'pyembed' and/or 'pyext'"
299         env = conf.env
300         if not env.CC_NAME and not env.CXX_NAME:
301                 conf.fatal('load a compiler first (gcc, g++, ..)')
302
303         # bypass all the code below for cross-compilation
304         if conf.python_cross_compile(features):
305                 return
306
307         if not env.PYTHON_VERSION:
308                 conf.check_python_version()
309
310         pybin = env.PYTHON
311         if not pybin:
312                 conf.fatal('Could not find the python executable')
313
314         # so we actually do all this for compatibility reasons and for obtaining pyext_PATTERN below
315         v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split()
316         try:
317                 lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v])
318         except RuntimeError:
319                 conf.fatal("Python development headers not found (-v for details).")
320
321         vals = ['%s = %r' % (x, y) for (x, y) in zip(v, lst)]
322         conf.to_log("Configuration returned from %r:\n%s\n" % (pybin, '\n'.join(vals)))
323
324         dct = dict(zip(v, lst))
325         x = 'MACOSX_DEPLOYMENT_TARGET'
326         if dct[x]:
327                 env[x] = conf.environ[x] = dct[x]
328         env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake
329
330
331         # Try to get pythonX.Y-config
332         num = '.'.join(env.PYTHON_VERSION.split('.')[:2])
333         conf.find_program([''.join(pybin) + '-config', 'python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', msg="python-config", mandatory=False)
334
335         if env.PYTHON_CONFIG:
336                 # python2.6-config requires 3 runs
337                 all_flags = [['--cflags', '--libs', '--ldflags']]
338                 if sys.hexversion < 0x2070000:
339                         all_flags = [[k] for k in all_flags[0]]
340
341                 xx = env.CXX_NAME and 'cxx' or 'c'
342
343                 if 'pyembed' in features:
344                         for flags in all_flags:
345                                 conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=flags)
346
347                         try:
348                                 conf.test_pyembed(xx)
349                         except conf.errors.ConfigurationError:
350                                 # python bug 7352
351                                 if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']:
352                                         env.append_unique('LIBPATH_PYEMBED', [dct['LIBDIR']])
353                                         conf.test_pyembed(xx)
354                                 else:
355                                         raise
356
357                 if 'pyext' in features:
358                         for flags in all_flags:
359                                 conf.check_cfg(msg='Asking python-config for pyext %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEXT', args=flags)
360
361                         try:
362                                 conf.test_pyext(xx)
363                         except conf.errors.ConfigurationError:
364                                 # python bug 7352
365                                 if dct['Py_ENABLE_SHARED'] and dct['LIBDIR']:
366                                         env.append_unique('LIBPATH_PYEXT', [dct['LIBDIR']])
367                                         conf.test_pyext(xx)
368                                 else:
369                                         raise
370
371                 conf.define('HAVE_PYTHON_H', 1)
372                 return
373
374         # No python-config, do something else on windows systems
375         all_flags = dct['LDFLAGS'] + ' ' + dct['CFLAGS']
376         conf.parse_flags(all_flags, 'PYEMBED')
377
378         all_flags = dct['LDFLAGS'] + ' ' + dct['LDSHARED'] + ' ' + dct['CFLAGS']
379         conf.parse_flags(all_flags, 'PYEXT')
380
381         result = None
382         if not dct["LDVERSION"]:
383                 dct["LDVERSION"] = env.PYTHON_VERSION
384
385         # further simplification will be complicated
386         for name in ('python' + dct['LDVERSION'], 'python' + env.PYTHON_VERSION + 'm', 'python' + env.PYTHON_VERSION.replace('.', '')):
387
388                 # LIBPATH_PYEMBED is already set; see if it works.
389                 if not result and env.LIBPATH_PYEMBED:
390                         path = env.LIBPATH_PYEMBED
391                         conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path)
392                         result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name)
393
394                 if not result and dct['LIBDIR']:
395                         path = [dct['LIBDIR']]
396                         conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path)
397                         result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name)
398
399                 if not result and dct['LIBPL']:
400                         path = [dct['LIBPL']]
401                         conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n")
402                         result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name)
403
404                 if not result:
405                         path = [os.path.join(dct['prefix'], "libs")]
406                         conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n")
407                         result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name)
408
409                 if result:
410                         break # do not forget to set LIBPATH_PYEMBED
411
412         if result:
413                 env.LIBPATH_PYEMBED = path
414                 env.append_value('LIB_PYEMBED', [name])
415         else:
416                 conf.to_log("\n\n### LIB NOT FOUND\n")
417
418         # under certain conditions, python extensions must link to
419         # python libraries, not just python embedding programs.
420         if Utils.is_win32 or dct['Py_ENABLE_SHARED']:
421                 env.LIBPATH_PYEXT = env.LIBPATH_PYEMBED
422                 env.LIB_PYEXT = env.LIB_PYEMBED
423
424         conf.to_log("Include path for Python extensions (found via distutils module): %r\n" % (dct['INCLUDEPY'],))
425         env.INCLUDES_PYEXT = [dct['INCLUDEPY']]
426         env.INCLUDES_PYEMBED = [dct['INCLUDEPY']]
427
428         # Code using the Python API needs to be compiled with -fno-strict-aliasing
429         if env.CC_NAME == 'gcc':
430                 env.append_value('CFLAGS_PYEMBED', ['-fno-strict-aliasing'])
431                 env.append_value('CFLAGS_PYEXT', ['-fno-strict-aliasing'])
432         if env.CXX_NAME == 'gcc':
433                 env.append_value('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing'])
434                 env.append_value('CXXFLAGS_PYEXT', ['-fno-strict-aliasing'])
435
436         if env.CC_NAME == "msvc":
437                 from distutils.msvccompiler import MSVCCompiler
438                 dist_compiler = MSVCCompiler()
439                 dist_compiler.initialize()
440                 env.append_value('CFLAGS_PYEXT', dist_compiler.compile_options)
441                 env.append_value('CXXFLAGS_PYEXT', dist_compiler.compile_options)
442                 env.append_value('LINKFLAGS_PYEXT', dist_compiler.ldflags_shared)
443
444         # See if it compiles
445         conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG, errmsg='Distutils not installed? Broken python installation? Get python-config now!')
446
447 @conf
448 def check_python_version(conf, minver=None):
449         """
450         Check if the python interpreter is found matching a given minimum version.
451         minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver.
452
453         If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR'
454         (eg. '2.4') of the actual python version found, and PYTHONDIR is
455         defined, pointing to the site-packages directory appropriate for
456         this python version, where modules/packages/extensions should be
457         installed.
458
459         :param minver: minimum version
460         :type minver: tuple of int
461         """
462         assert minver is None or isinstance(minver, tuple)
463         pybin = conf.env.PYTHON
464         if not pybin:
465                 conf.fatal('could not find the python executable')
466
467         # Get python version string
468         cmd = pybin + ['-c', 'import sys\nfor x in sys.version_info: print(str(x))']
469         Logs.debug('python: Running python command %r', cmd)
470         lines = conf.cmd_and_log(cmd).split()
471         assert len(lines) == 5, "found %r lines, expected 5: %r" % (len(lines), lines)
472         pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4]))
473
474         # Compare python version with the minimum required
475         result = (minver is None) or (pyver_tuple >= minver)
476
477         if result:
478                 # define useful environment variables
479                 pyver = '.'.join([str(x) for x in pyver_tuple[:2]])
480                 conf.env.PYTHON_VERSION = pyver
481
482                 if 'PYTHONDIR' in conf.env:
483                         # Check if --pythondir was specified
484                         pydir = conf.env.PYTHONDIR
485                 elif 'PYTHONDIR' in conf.environ:
486                         # Check environment for PYTHONDIR
487                         pydir = conf.environ['PYTHONDIR']
488                 else:
489                         # Finally, try to guess
490                         if Utils.is_win32:
491                                 (python_LIBDEST, pydir) = conf.get_python_variables(
492                                           ["get_config_var('LIBDEST') or ''",
493                                            "get_python_lib(standard_lib=0) or ''"])
494                         else:
495                                 python_LIBDEST = None
496                                 (pydir,) = conf.get_python_variables( ["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX])
497                         if python_LIBDEST is None:
498                                 if conf.env.LIBDIR:
499                                         python_LIBDEST = os.path.join(conf.env.LIBDIR, 'python' + pyver)
500                                 else:
501                                         python_LIBDEST = os.path.join(conf.env.PREFIX, 'lib', 'python' + pyver)
502
503                 if 'PYTHONARCHDIR' in conf.env:
504                         # Check if --pythonarchdir was specified
505                         pyarchdir = conf.env.PYTHONARCHDIR
506                 elif 'PYTHONARCHDIR' in conf.environ:
507                         # Check environment for PYTHONDIR
508                         pyarchdir = conf.environ['PYTHONARCHDIR']
509                 else:
510                         # Finally, try to guess
511                         (pyarchdir, ) = conf.get_python_variables( ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env.PREFIX])
512                         if not pyarchdir:
513                                 pyarchdir = pydir
514
515                 if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist
516                         conf.define('PYTHONDIR', pydir)
517                         conf.define('PYTHONARCHDIR', pyarchdir)
518
519                 conf.env.PYTHONDIR = pydir
520                 conf.env.PYTHONARCHDIR = pyarchdir
521
522         # Feedback
523         pyver_full = '.'.join(map(str, pyver_tuple[:3]))
524         if minver is None:
525                 conf.msg('Checking for python version', pyver_full)
526         else:
527                 minver_str = '.'.join(map(str, minver))
528                 conf.msg('Checking for python version >= %s' % (minver_str,), pyver_full, color=result and 'GREEN' or 'YELLOW')
529
530         if not result:
531                 conf.fatal('The python version is too old, expecting %r' % (minver,))
532
533 PYTHON_MODULE_TEMPLATE = '''
534 import %s as current_module
535 version = getattr(current_module, '__version__', None)
536 if version is not None:
537         print(str(version))
538 else:
539         print('unknown version')
540 '''
541
542 @conf
543 def check_python_module(conf, module_name, condition=''):
544         """
545         Check if the selected python interpreter can import the given python module::
546
547                 def configure(conf):
548                         conf.check_python_module('pygccxml')
549                         conf.check_python_module('re', condition="ver > num(2, 0, 4) and ver <= num(3, 0, 0)")
550
551         :param module_name: module
552         :type module_name: string
553         """
554         msg = "Checking for python module %r" % module_name
555         if condition:
556                 msg = '%s (%s)' % (msg, condition)
557         conf.start_msg(msg)
558         try:
559                 ret = conf.cmd_and_log(conf.env.PYTHON + ['-c', PYTHON_MODULE_TEMPLATE % module_name])
560         except Errors.WafError:
561                 conf.end_msg(False)
562                 conf.fatal('Could not find the python module %r' % module_name)
563
564         ret = ret.strip()
565         if condition:
566                 conf.end_msg(ret)
567                 if ret == 'unknown version':
568                         conf.fatal('Could not check the %s version' % module_name)
569
570                 from distutils.version import LooseVersion
571                 def num(*k):
572                         if isinstance(k[0], int):
573                                 return LooseVersion('.'.join([str(x) for x in k]))
574                         else:
575                                 return LooseVersion(k[0])
576                 d = {'num': num, 'ver': LooseVersion(ret)}
577                 ev = eval(condition, {}, d)
578                 if not ev:
579                         conf.fatal('The %s version does not satisfy the requirements' % module_name)
580         else:
581                 if ret == 'unknown version':
582                         conf.end_msg(True)
583                 else:
584                         conf.end_msg(ret)
585
586 def configure(conf):
587         """
588         Detect the python interpreter
589         """
590         v = conf.env
591         if getattr(Options.options, 'pythondir', None):
592                 v.PYTHONDIR = Options.options.pythondir
593         if getattr(Options.options, 'pythonarchdir', None):
594                 v.PYTHONARCHDIR = Options.options.pythonarchdir
595         if getattr(Options.options, 'nopycache', None):
596                 v.NOPYCACHE=Options.options.nopycache
597
598         if not v.PYTHON:
599                 v.PYTHON = [getattr(Options.options, 'python', None) or sys.executable]
600         v.PYTHON = Utils.to_list(v.PYTHON)
601         conf.find_program('python', var='PYTHON')
602
603         v.PYFLAGS = ''
604         v.PYFLAGS_OPT = '-O'
605
606         v.PYC = getattr(Options.options, 'pyc', 1)
607         v.PYO = getattr(Options.options, 'pyo', 1)
608
609         try:
610                 v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import imp;print(imp.get_tag())"]).strip()
611         except Errors.WafError:
612                 pass
613
614 def options(opt):
615         """
616         Add python-specific options
617         """
618         pyopt=opt.add_option_group("Python Options")
619         pyopt.add_option('--nopyc', dest = 'pyc', action='store_false', default=1,
620                                          help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]')
621         pyopt.add_option('--nopyo', dest='pyo', action='store_false', default=1,
622                                          help='Do not install optimised compiled .pyo files (configuration) [Default:install]')
623         pyopt.add_option('--nopycache',dest='nopycache', action='store_true',
624                                          help='Do not use __pycache__ directory to install objects [Default:auto]')
625         pyopt.add_option('--python', dest="python",
626                                          help='python binary to be used [Default: %s]' % sys.executable)
627         pyopt.add_option('--pythondir', dest='pythondir',
628                                          help='Installation path for python modules (py, platform-independent .py and .pyc files)')
629         pyopt.add_option('--pythonarchdir', dest='pythonarchdir',
630                                          help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)')
631