summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/build_utils/__init__.py114
-rw-r--r--numpy/core/bscript49
2 files changed, 163 insertions, 0 deletions
diff --git a/numpy/build_utils/__init__.py b/numpy/build_utils/__init__.py
index ba9fa72be..0fa3f0ff4 100644
--- a/numpy/build_utils/__init__.py
+++ b/numpy/build_utils/__init__.py
@@ -106,3 +106,117 @@ int main()
return ret == 0
return ret
+def do_binary_search(conf, type_name, kw):
+ code = """\
+typedef %(type)s waf_check_sizeof_type;
+int main ()
+{
+ static int test_array [1 - 2 * !(((long) (sizeof (waf_check_sizeof_type))) >= 0)];
+ test_array [0] = 0
+
+ ;
+ return 0;
+}
+""" % {"type": type_name}
+ kw["code"] = to_header(kw) + code
+
+ try:
+ conf.run_c_code(**kw)
+ except conf.errors.ConfigurationError, e:
+ conf.end_msg("failed !")
+ if waflib.Logs.verbose > 1:
+ raise
+ else:
+ conf.fatal("The configuration failed !")
+
+ body = r"""
+typedef %(type)s waf_check_sizeof_type;
+int main ()
+{
+ static int test_array [1 - 2 * !(((long) (sizeof (waf_check_sizeof_type))) <= %(size)s)];
+ test_array [0] = 0
+
+ ;
+ return 0;
+}
+"""
+ # The principle is simple: we first find low and high bounds
+ # of size for the type, where low/high are looked up on a log
+ # scale. Then, we do a binary search to find the exact size
+ # between low and high
+ low = 0
+ mid = 0
+ while True:
+ try:
+ kw["code"] = to_header(kw) + body % {"type": type_name, "size": mid}
+ validate_arguments(conf, kw)
+ conf.run_c_code(**kw)
+ break
+ except conf.errors.ConfigurationError:
+ #log.info("failure to test for bound %d" % mid)
+ low = mid + 1
+ mid = 2 * mid + 1
+
+ high = mid
+ ret = None
+ # Binary search:
+ while low != high:
+ mid = (high - low) / 2 + low
+ try:
+ kw["code"] = to_header(kw) + body % {"type": type_name, "size": mid}
+ validate_arguments(conf, kw)
+ ret = conf.run_c_code(**kw)
+ high = mid
+ except conf.errors.ConfigurationError:
+ low = mid + 1
+
+ return low
+
+@waflib.Configure.conf
+def check_type_size(conf, type_name, expected_sizes=None, **kw):
+ kw["define_name"] = "SIZEOF_%s" % sanitize_string(type_name)
+ kw["define_comment"] = "/* The size of `%s', as computed by sizeof. */" % type_name
+ kw["msg"] = "Checking sizeof(%s)" % type_name
+
+ validate_arguments(conf, kw)
+ conf.start_msg(kw["msg"])
+
+ if expected_sizes is not None:
+ try:
+ val = int(expected_sizes)
+ except TypeError:
+ values = expected_sizes
+ else:
+ values = [val]
+
+ size = None
+ for value in values:
+ code = """\
+ typedef %(type)s waf_check_sizeof_type;
+ int main ()
+ {
+ static int test_array [1 - 2 * !(((long) (sizeof (waf_check_sizeof_type))) == %(size)d)];
+ test_array [0] = 0
+
+ ;
+ return 0;
+ }
+ """ % {"type": type_name, "size": value}
+ kw["code"] = to_header(kw) + code
+ try:
+ conf.run_c_code(**kw)
+ size = value
+ break
+ except conf.errors.ConfigurationError:
+ pass
+ if size is None:
+ size = do_binary_search(conf, type_name, kw)
+ else:
+ size = do_binary_search(conf, type_name, kw)
+
+ kw["define_value"] = size
+ kw["success"] = 0
+ conf.end_msg(size)
+ conf.post_check(**kw)
+ return size
+
diff --git a/numpy/core/bscript b/numpy/core/bscript
index 22913ac3c..3936d802c 100644
--- a/numpy/core/bscript
+++ b/numpy/core/bscript
@@ -1,3 +1,5 @@
+import sys
+
from bento.commands.hooks \
import \
pre_configure
@@ -36,6 +38,51 @@ def write_numpy_config(conf):
onode = conf.bldnode.find_or_declare(node.path_from(conf.srcnode)).change_ext("")
onode.write(cnt)
+def type_checks(conf):
+ header_name = "Python.h"
+ features = "c pyext"
+ for c_type in ("int", "long", "short"):
+ macro_name = "SIZEOF_%s" % numpy.build_utils.sanitize_string(c_type)
+ conf.check_declaration(macro_name, header_name=header_name,
+ features=features)
+ NUMPYCONFIG_SYM.append((macro_name, macro_name))
+
+ for c_type, e_size in (("float", 4), ("double", 8), ("long double", [12, 16])):
+ macro_name = "SIZEOF_%s" % numpy.build_utils.sanitize_string(c_type)
+ size = conf.check_type_size(c_type, header_name=header_name,
+ features=features, expected_sizes=e_size)
+ NUMPYCONFIG_SYM.append((macro_name, str(size)))
+
+ macro_name = "SIZEOF_COMPLEX_%s" % numpy.build_utils.sanitize_string(c_type)
+ complex_def = "struct {%s __x; %s __y;}" % (c_type, c_type)
+ size = conf.check_type_size(complex_def, header_name=header_name,
+ features=features, expected_sizes=2*size)
+ NUMPYCONFIG_SYM.append((macro_name, str(size)))
+
+ if sys.platform != 'darwin':
+ conf.check_ldouble_representation()
+
+ size = conf.check_type_size("Py_intptr_t", header_name=header_name,
+ expected_sizes=[4, 8], features=features)
+ NUMPYCONFIG_SYM.append(('SIZEOF_%s' % numpy.build_utils.sanitize_string("Py_intptr_t"),
+ '%d' % size))
+
+ # We check declaration AND type because that's how distutils does it.
+ try:
+ conf.check_declaration("PY_LONG_LONG", header_name=header_name,
+ features=features)
+ size = conf.check_type_size("PY_LONG_LONG", header_name=header_name,
+ features=features, expected_sizes=[4, 8])
+ NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_LONGLONG",
+ "#define NPY_SIZEOF_LONGLONG %d" % size))
+ NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_PY_LONG_LONG",
+ "#define NPY_SIZEOF_PY_LONG_LONG %d" % size))
+ except waflib.Errors.ConfigurationError:
+ NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_LONGLONG", ""))
+ NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_PY_LONG_LONG", ""))
+
+ conf.check_declaration("CHAR_BIT", header_name=header_name, features=features)
+
@pre_configure()
def configure(context):
conf = context.waf_context
@@ -56,6 +103,8 @@ def configure(context):
except waflib.Errors.ConfigurationError:
NUMPYCONFIG_SYM.append(('DEFINE_NPY_USE_C99_FORMATS', ''))
+ type_checks(conf)
+
conf.env["CONFIG_HEADER_TEMPLATE"] = """\
%(content)s
#ifndef _NPY_NPY_CONFIG_H_