python: Assert that we use Py_ssize_t consistently for PyParseArgs*()
[sfrench/samba-autobuild/.git] / buildtools / wafsamba / samba_python.py
1 # waf build tool for building IDL files with pidl
2
3 import os
4 import Build, Logs, Utils, Configure
5 from Configure import conf
6
7 @conf
8 def SAMBA_CHECK_PYTHON(conf, mandatory=True, version=(2,4,2)):
9     # enable tool to build python extensions
10     if conf.env.HAVE_PYTHON_H:
11         conf.check_python_version(version)
12         return
13
14     interpreters = []
15
16     if conf.env['EXTRA_PYTHON']:
17         conf.all_envs['extrapython'] = conf.env.copy()
18         conf.setenv('extrapython')
19         conf.env['PYTHON'] = conf.env['EXTRA_PYTHON']
20         conf.env['IS_EXTRA_PYTHON'] = 'yes'
21         conf.find_program('python', var='PYTHON', mandatory=True)
22         conf.check_tool('python')
23         try:
24             conf.check_python_version((3, 3, 0))
25         except Exception:
26             Logs.warn('extra-python needs to be Python 3.3 or later')
27             raise
28         interpreters.append(conf.env['PYTHON'])
29         conf.setenv('default')
30
31     conf.find_program('python', var='PYTHON', mandatory=mandatory)
32     conf.check_tool('python')
33     path_python = conf.find_program('python')
34     conf.env.PYTHON_SPECIFIED = (conf.env.PYTHON != path_python)
35     conf.check_python_version(version)
36
37     interpreters.append(conf.env['PYTHON'])
38     conf.env.python_interpreters = interpreters
39
40
41 @conf
42 def SAMBA_CHECK_PYTHON_HEADERS(conf, mandatory=True):
43     if conf.env["python_headers_checked"] == []:
44         if conf.env['EXTRA_PYTHON']:
45             conf.setenv('extrapython')
46             _check_python_headers(conf, mandatory=True)
47             conf.setenv('default')
48
49         _check_python_headers(conf, mandatory)
50         conf.env["python_headers_checked"] = "yes"
51
52         if conf.env['EXTRA_PYTHON']:
53             extraversion = conf.all_envs['extrapython']['PYTHON_VERSION']
54             if extraversion == conf.env['PYTHON_VERSION']:
55                 raise Utils.WafError("extrapython %s is same as main python %s" % (
56                     extraversion, conf.env['PYTHON_VERSION']))
57     else:
58         conf.msg("python headers", "using cache")
59
60     # we don't want PYTHONDIR in config.h, as otherwise changing
61     # --prefix causes a complete rebuild
62     del(conf.env.defines['PYTHONDIR'])
63     del(conf.env.defines['PYTHONARCHDIR'])
64
65 def _check_python_headers(conf, mandatory):
66     try:
67         Configure.ConfigurationError
68         conf.check_python_headers(mandatory=mandatory)
69     except Configure.ConfigurationError:
70         if mandatory:
71              raise
72
73     if conf.env['PYTHON_VERSION'] > '3':
74         abi_pattern = os.path.splitext(conf.env['pyext_PATTERN'])[0]
75         conf.env['PYTHON_SO_ABI_FLAG'] = abi_pattern % ''
76     else:
77         conf.env['PYTHON_SO_ABI_FLAG'] = ''
78
79
80 def SAMBA_PYTHON(bld, name,
81                  source='',
82                  deps='',
83                  public_deps='',
84                  realname=None,
85                  cflags='',
86                  includes='',
87                  init_function_sentinel=None,
88                  local_include=True,
89                  vars=None,
90                  install=True,
91                  enabled=True):
92     '''build a python extension for Samba'''
93
94     if bld.env['IS_EXTRA_PYTHON']:
95         name = 'extra-' + name
96
97     # when we support static python modules we'll need to gather
98     # the list from all the SAMBA_PYTHON() targets
99     if init_function_sentinel is not None:
100         cflags += '-DSTATIC_LIBPYTHON_MODULES=%s' % init_function_sentinel
101
102     # From https://docs.python.org/2/c-api/arg.html:
103     # Starting with Python 2.5 the type of the length argument to
104     # PyArg_ParseTuple(), PyArg_ParseTupleAndKeywords() and PyArg_Parse()
105     # can be controlled by defining the macro PY_SSIZE_T_CLEAN before
106     # including Python.h. If the macro is defined, length is a Py_ssize_t
107     # rather than an int.
108
109     # Because <Python.h> if often included before includes.h/config.h
110     # This must be in the -D compiler options
111     cflags += ' -DPY_SSIZE_T_CLEAN=1'
112
113     source = bld.EXPAND_VARIABLES(source, vars=vars)
114
115     if realname is not None:
116         link_name = 'python_modules/%s' % realname
117     else:
118         link_name = None
119
120     bld.SAMBA_LIBRARY(name,
121                       source=source,
122                       deps=deps,
123                       public_deps=public_deps,
124                       includes=includes,
125                       cflags=cflags,
126                       local_include=local_include,
127                       vars=vars,
128                       realname=realname,
129                       link_name=link_name,
130                       pyext=True,
131                       target_type='PYTHON',
132                       install_path='${PYTHONARCHDIR}',
133                       allow_undefined_symbols=True,
134                       install=install,
135                       enabled=enabled)
136
137 Build.BuildContext.SAMBA_PYTHON = SAMBA_PYTHON
138
139
140 def pyembed_libname(bld, name, extrapython=False):
141     return name + bld.env['PYTHON_SO_ABI_FLAG']
142
143 Build.BuildContext.pyembed_libname = pyembed_libname
144
145
146 def gen_python_environments(bld, extra_env_vars=()):
147     """Generate all Python environments
148
149     To be used in a for loop. Normally, the loop body will be executed once.
150
151     When --extra-python is used, the body will additionaly be executed
152     with the extra-python environment active.
153     """
154     yield
155
156     if bld.env['EXTRA_PYTHON']:
157         copied = ('GLOBAL_DEPENDENCIES', 'TARGET_TYPE') + tuple(extra_env_vars)
158         for name in copied:
159             bld.all_envs['extrapython'][name] = bld.all_envs['default'][name]
160         default_env = bld.all_envs['default']
161         bld.all_envs['default'] = bld.all_envs['extrapython']
162         yield
163         bld.all_envs['default'] = default_env
164
165 Build.BuildContext.gen_python_environments = gen_python_environments