import os import contextlib import Build from samba_utils import * from samba_autoconf import * from Logs import warn from TaskGen import extension, before, after, feature from Configure import conf @feature('extrapyext') @before('apply_incpaths', 'apply_lib_vars', 'apply_type_vars', 'apply_bundle') @after('vars_target_cshlib') def init_extrapyext(self): self.default_install_path = '${PYTHONARCHDIR}' self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'EXTRAPYEXT' in self.uselib: self.uselib.append('EXTRAPYEXT') @before('apply_link', 'apply_lib_vars', 'apply_type_vars') @after('apply_bundle') @feature('extrapyext') def extrapyext_shlib_ext(self): # override shlib_PATTERN set by the osx module self.env['shlib_PATTERN'] = self.env['extrapyext_PATTERN'] @before('apply_incpaths', 'apply_lib_vars', 'apply_type_vars') @feature('extrapyembed') def init_extrapyembed(self): self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'EXTRAPYEMBED' in self.uselib: self.uselib.append('EXTRAPYEMBED') # For extrapython, we store config in a separate set of env variables. # During the configure step we swap these with the normal *PYTHON* equivalents, # use waf's regular Python tool, and then switch them all back. EXTRAPYTHON_ENV_KEYS = ( ('PYTHON', 'EXTRAPYTHON'), ('PYTHONDIR', 'EXTRAPYTHONDIR'), ('PYTHONARCHDIR', 'EXTRAPYTHONARCHDIR'), ('PYTHON_VERSION', 'EXTRAPYTHON_VERSION'), ('CCFLAGS_PYEXT', 'CCFLAGS_EXTRAPYEXT'), ('CCFLAGS_PYEMBED', 'CCFLAGS_EXTRAPYEMBED'), ('LIBPATH_PYEXT', 'LIBPATH_EXTRAPYEXT'), ('LIBPATH_PYEMBED', 'LIBPATH_EXTRAPYEMBED'), ('LIB_PYEXT', 'LIB_EXTRAPYEXT'), ('LIB_PYEMBED', 'LIB_EXTRAPYEMBED'), ('CPPPATH_PYEXT', 'CPPPATH_EXTRAPYEXT'), ('CPPPATH_PYEMBED', 'CPPPATH_EXTRAPYEMBED'), ('LINKFLAGS_PYEXT', 'LINKFLAGS_EXTRAPYEXT'), ('LINKFLAGS_PYEMBED', 'LINKFLAGS_EXTRAPYEMBED'), ('HAVE_PYTHON_H', 'EXTRAPY_HAVE_PYTHON_H'), ('PYTHON_CONFIG', 'EXTRAPYTHON_CONFIG'), ('pyext_PATTERN', 'extrapyext_PATTERN'), ('PYCMD', 'EXTRAPYCMD'), ('PYFLAGS', 'EXTRAPYFLAGS'), ('PYFLAGS_OPT', 'EXTRAPYFLAGS_OPT'), ('PYTHON_SO_ABI_FLAG', 'EXTRAPYTHON_SO_ABI_FLAG'), ) EXTRAPYTHON_DEFINES_KEYS = ( ('PYTHONDIR', 'EXTRAPYTHONDIR'), ('PYTHONARCHDIR', 'EXTRAPYTHONARCHDIR'), ('HAVE_PYTHON_H', 'EXTRAPY_HAVE_PYTHON_H'), ) @contextlib.contextmanager def extrapython_map(env, keys): saved = {} for key, extrakey in keys: if key in env: saved[key] = env[key] if extrakey in env: env[key] = env[extrakey] else: env.pop(key, None) yield for key, extrakey in keys: if key in env: env[extrakey] = env[key] else: env.pop(extrakey, None) if key in saved: env[key] = saved[key] else: env.pop(key, None) @contextlib.contextmanager def extrapython_env(env): with extrapython_map(env, EXTRAPYTHON_ENV_KEYS): with extrapython_map(env['defines'], EXTRAPYTHON_DEFINES_KEYS): yield @conf def SAMBA_CHECK_PYTHON(conf, mandatory=True, version=(2,4,2)): # enable tool to build python extensions interpreters = [] if conf.env['EXTRA_PYTHON']: with extrapython_env(conf.env): conf.env['PYTHON'] = conf.env['EXTRA_PYTHON'] conf.find_program('python', var='PYTHON', mandatory=True) conf.check_tool('python') try: conf.check_python_version((3, 3, 0)) except Exception: warn('extra-python needs to be Python 3.3 or later') raise interpreters.append(conf.env['EXTRA_PYTHON']) conf.find_program('python', var='PYTHON', mandatory=mandatory) conf.check_tool('python') path_python = conf.find_program('python') conf.env.PYTHON_SPECIFIED = (conf.env.PYTHON != path_python) conf.check_python_version(version) interpreters.append(conf.env['PYTHON']) conf.env.python_interpreters = interpreters def check_python_headers(conf, mandatory): conf.check_python_headers(mandatory=mandatory) if conf.env['PYTHON_VERSION'] > '3': abi_pattern = os.path.splitext(conf.env['pyext_PATTERN'])[0] conf.env['PYTHON_SO_ABI_FLAG'] = abi_pattern % '' else: conf.env['PYTHON_SO_ABI_FLAG'] = '' @conf def SAMBA_CHECK_PYTHON_HEADERS(conf, mandatory=True): if conf.env["python_headers_checked"] == []: pre_dict = conf.env.get_merged_dict() if conf.env['EXTRA_PYTHON']: with extrapython_env(conf.env): check_python_headers(conf, mandatory=True) check_python_headers(conf, mandatory=mandatory) conf.env["python_headers_checked"] = "yes" if conf.env['EXTRAPYTHON_VERSION'] == conf.env['PYTHON_VERSION']: raise Utils.WafError("extrapython %s is same as main python %s" % ( conf.env['EXTRAPYTHON_VERSION'], conf.env['PYTHON_VERSION'])) else: conf.msg("python headers", "using cache") def SAMBA_PYTHON(bld, name, source='', deps='', public_deps='', realname=None, cflags='', includes='', init_function_sentinel=None, local_include=True, vars=None, install=True, enabled=True, extra_python=False): '''build a python extension for Samba''' # when we support static python modules we'll need to gather # the list from all the SAMBA_PYTHON() targets if init_function_sentinel is not None: cflags += '-DSTATIC_LIBPYTHON_MODULES=%s' % init_function_sentinel source = bld.EXPAND_VARIABLES(source, vars=vars) if realname is not None: link_name = 'python_modules/%s' % realname else: link_name = None if extra_python: pyfeature = 'extrapyext' target_type = 'EXTRAPYTHON' install_path = '${EXTRAPYTHONARCHDIR}' else: pyfeature = 'pyext' target_type = 'PYTHON' install_path = '${PYTHONARCHDIR}' bld.SAMBA_LIBRARY(name, source=source, deps=deps, public_deps=public_deps, includes=includes, cflags=cflags, local_include=local_include, vars=vars, realname=realname, link_name=link_name, pyfeature=pyfeature, target_type=target_type, install_path=install_path, allow_undefined_symbols=True, allow_warnings=True, install=install, enabled=enabled) Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON def pyembed_libname(bld, name, extrapython=False): if extrapython: return name + bld.env['EXTRAPYTHON_SO_ABI_FLAG'] else: return name + bld.env['PYTHON_SO_ABI_FLAG'] return name Build.BuildContext.pyembed_libname = pyembed_libname