diff options
author | Alex Willmer <alex@moreati.org.uk> | 2015-08-05 17:21:33 +0100 |
---|---|---|
committer | Alex Willmer <alex@moreati.org.uk> | 2015-08-05 17:21:33 +0100 |
commit | ff668ba0d7652c12b28a6b6f9dbb3b581a383833 (patch) | |
tree | 7a4033c5be2deefac3812c7a221d8c9a741454e4 /numpy/build_utils | |
parent | f179ec92d8ddb0dc5f7445255022be5c4765a704 (diff) | |
download | numpy-ff668ba0d7652c12b28a6b6f9dbb3b581a383833.tar.gz |
BLD: Move numpy.build_utils -> numpy._build_utils, add to MANIFEST.in
This fixes the distutils built from an sdist (e.g. under tox),
without including _build_utils in binary distributions or the installed numpy.
Diffstat (limited to 'numpy/build_utils')
-rw-r--r-- | numpy/build_utils/__init__.py | 1 | ||||
-rw-r--r-- | numpy/build_utils/apple_accelerate.py | 21 | ||||
-rw-r--r-- | numpy/build_utils/common.py | 138 | ||||
-rw-r--r-- | numpy/build_utils/src/apple_sgemv_fix.c | 227 | ||||
-rw-r--r-- | numpy/build_utils/waf.py | 531 |
5 files changed, 0 insertions, 918 deletions
diff --git a/numpy/build_utils/__init__.py b/numpy/build_utils/__init__.py deleted file mode 100644 index 1d0f69b67..000000000 --- a/numpy/build_utils/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import division, absolute_import, print_function diff --git a/numpy/build_utils/apple_accelerate.py b/numpy/build_utils/apple_accelerate.py deleted file mode 100644 index d7351f4c5..000000000 --- a/numpy/build_utils/apple_accelerate.py +++ /dev/null @@ -1,21 +0,0 @@ -import os -import sys -import re - -__all__ = ['uses_accelerate_framework', 'get_sgemv_fix'] - -def uses_accelerate_framework(info): - """ Returns True if Accelerate framework is used for BLAS/LAPACK """ - if sys.platform != "darwin": - return False - r_accelerate = re.compile("Accelerate") - extra_link_args = info.get('extra_link_args', '') - for arg in extra_link_args: - if r_accelerate.search(arg): - return True - return False - -def get_sgemv_fix(): - """ Returns source file needed to correct SGEMV """ - path = os.path.abspath(os.path.dirname(__file__)) - return [os.path.join(path, 'src', 'apple_sgemv_fix.c')] diff --git a/numpy/build_utils/common.py b/numpy/build_utils/common.py deleted file mode 100644 index 8435c462c..000000000 --- a/numpy/build_utils/common.py +++ /dev/null @@ -1,138 +0,0 @@ -from __future__ import division, absolute_import, print_function - -import sys -import copy -import binascii - -LONG_DOUBLE_REPRESENTATION_SRC = r""" -/* "before" is 16 bytes to ensure there's no padding between it and "x". - * We're not expecting any "long double" bigger than 16 bytes or with - * alignment requirements stricter than 16 bytes. */ -typedef %(type)s test_type; - -struct { - char before[16]; - test_type x; - char after[8]; -} foo = { - { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\001', '\043', '\105', '\147', '\211', '\253', '\315', '\357' }, - -123456789.0, - { '\376', '\334', '\272', '\230', '\166', '\124', '\062', '\020' } -}; -""" - -def pyod(filename): - """Python implementation of the od UNIX utility (od -b, more exactly). - - Parameters - ---------- - filename : str - name of the file to get the dump from. - - Returns - ------- - out : seq - list of lines of od output - - Note - ---- - We only implement enough to get the necessary information for long double - representation, this is not intended as a compatible replacement for od. - """ - def _pyod2(): - out = [] - - fid = open(filename, 'r') - try: - yo = [int(oct(int(binascii.b2a_hex(o), 16))) for o in fid.read()] - for i in range(0, len(yo), 16): - line = ['%07d' % int(oct(i))] - line.extend(['%03d' % c for c in yo[i:i+16]]) - out.append(" ".join(line)) - return out - finally: - fid.close() - - def _pyod3(): - out = [] - - fid = open(filename, 'rb') - try: - yo2 = [oct(o)[2:] for o in fid.read()] - for i in range(0, len(yo2), 16): - line = ['%07d' % int(oct(i)[2:])] - line.extend(['%03d' % int(c) for c in yo2[i:i+16]]) - out.append(" ".join(line)) - return out - finally: - fid.close() - - if sys.version_info[0] < 3: - return _pyod2() - else: - return _pyod3() - -_BEFORE_SEQ = ['000', '000', '000', '000', '000', '000', '000', '000', - '001', '043', '105', '147', '211', '253', '315', '357'] -_AFTER_SEQ = ['376', '334', '272', '230', '166', '124', '062', '020'] - -_IEEE_DOUBLE_BE = ['301', '235', '157', '064', '124', '000', '000', '000'] -_IEEE_DOUBLE_LE = _IEEE_DOUBLE_BE[::-1] -_INTEL_EXTENDED_12B = ['000', '000', '000', '000', '240', '242', '171', '353', - '031', '300', '000', '000'] -_INTEL_EXTENDED_16B = ['000', '000', '000', '000', '240', '242', '171', '353', - '031', '300', '000', '000', '000', '000', '000', '000'] -_IEEE_QUAD_PREC_BE = ['300', '031', '326', '363', '105', '100', '000', '000', - '000', '000', '000', '000', '000', '000', '000', '000'] -_IEEE_QUAD_PREC_LE = _IEEE_QUAD_PREC_BE[::-1] -_DOUBLE_DOUBLE_BE = ['301', '235', '157', '064', '124', '000', '000', '000'] + \ - ['000'] * 8 - -def long_double_representation(lines): - """Given a binary dump as given by GNU od -b, look for long double - representation.""" - - # Read contains a list of 32 items, each item is a byte (in octal - # representation, as a string). We 'slide' over the output until read is of - # the form before_seq + content + after_sequence, where content is the long double - # representation: - # - content is 12 bytes: 80 bits Intel representation - # - content is 16 bytes: 80 bits Intel representation (64 bits) or quad precision - # - content is 8 bytes: same as double (not implemented yet) - read = [''] * 32 - saw = None - for line in lines: - # we skip the first word, as od -b output an index at the beginning of - # each line - for w in line.split()[1:]: - read.pop(0) - read.append(w) - - # If the end of read is equal to the after_sequence, read contains - # the long double - if read[-8:] == _AFTER_SEQ: - saw = copy.copy(read) - if read[:12] == _BEFORE_SEQ[4:]: - if read[12:-8] == _INTEL_EXTENDED_12B: - return 'INTEL_EXTENDED_12_BYTES_LE' - elif read[:8] == _BEFORE_SEQ[8:]: - if read[8:-8] == _INTEL_EXTENDED_16B: - return 'INTEL_EXTENDED_16_BYTES_LE' - elif read[8:-8] == _IEEE_QUAD_PREC_BE: - return 'IEEE_QUAD_BE' - elif read[8:-8] == _IEEE_QUAD_PREC_LE: - return 'IEEE_QUAD_LE' - elif read[8:-8] == _DOUBLE_DOUBLE_BE: - return 'DOUBLE_DOUBLE_BE' - elif read[:16] == _BEFORE_SEQ: - if read[16:-8] == _IEEE_DOUBLE_LE: - return 'IEEE_DOUBLE_LE' - elif read[16:-8] == _IEEE_DOUBLE_BE: - return 'IEEE_DOUBLE_BE' - - if saw is not None: - raise ValueError("Unrecognized format (%s)" % saw) - else: - # We never detected the after_sequence - raise ValueError("Could not lock sequences (%s)" % saw) diff --git a/numpy/build_utils/src/apple_sgemv_fix.c b/numpy/build_utils/src/apple_sgemv_fix.c deleted file mode 100644 index ffdfb81f7..000000000 --- a/numpy/build_utils/src/apple_sgemv_fix.c +++ /dev/null @@ -1,227 +0,0 @@ -/* This is a collection of ugly hacks to circumvent a bug in - * Apple Accelerate framework's SGEMV subroutine. - * - * See: https://github.com/numpy/numpy/issues/4007 - * - * SGEMV in Accelerate framework will segfault on MacOS X version 10.9 - * (aka Mavericks) if arrays are not aligned to 32 byte boundaries - * and the CPU supports AVX instructions. This can produce segfaults - * in np.dot. - * - * This patch overshadows the symbols cblas_sgemv, sgemv_ and sgemv - * exported by Accelerate to produce the correct behavior. The MacOS X - * version and CPU specs are checked on module import. If Mavericks and - * AVX are detected the call to SGEMV is emulated with a call to SGEMM - * if the arrays are not 32 byte aligned. If the exported symbols cannot - * be overshadowed on module import, a fatal error is produced and the - * process aborts. All the fixes are in a self-contained C file - * and do not alter the multiarray C code. The patch is not applied - * unless NumPy is configured to link with Apple's Accelerate - * framework. - * - */ - -#define NPY_NO_DEPRECATED_API NPY_API_VERSION -#include "Python.h" -#include "numpy/arrayobject.h" - -#include <string.h> -#include <dlfcn.h> -#include <stdlib.h> -#include <stdio.h> - -/* ----------------------------------------------------------------- */ -/* Original cblas_sgemv */ - -#define VECLIB_FILE "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/vecLib" - -enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; -enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; -extern void cblas_xerbla(int info, const char *rout, const char *form, ...); - -typedef void cblas_sgemv_t(const enum CBLAS_ORDER order, - const enum CBLAS_TRANSPOSE TransA, const int M, const int N, - const float alpha, const float *A, const int lda, - const float *X, const int incX, - const float beta, float *Y, const int incY); - -typedef void cblas_sgemm_t(const enum CBLAS_ORDER order, - const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, - const int M, const int N, const int K, - const float alpha, const float *A, const int lda, - const float *B, const int ldb, - const float beta, float *C, const int incC); - -typedef void fortran_sgemv_t( const char* trans, const int* m, const int* n, - const float* alpha, const float* A, const int* ldA, - const float* X, const int* incX, - const float* beta, float* Y, const int* incY ); - -static void *veclib = NULL; -static cblas_sgemv_t *accelerate_cblas_sgemv = NULL; -static cblas_sgemm_t *accelerate_cblas_sgemm = NULL; -static fortran_sgemv_t *accelerate_sgemv = NULL; -static int AVX_and_10_9 = 0; - -/* Dynamic check for AVX support - * __builtin_cpu_supports("avx") is available in gcc 4.8, - * but clang and icc do not currently support it. */ -#define cpu_supports_avx()\ -(system("sysctl -n machdep.cpu.features | grep -q AVX") == 0) - -/* Check if we are using MacOS X version 10.9 */ -#define using_mavericks()\ -(system("sw_vers -productVersion | grep -q 10\\.9\\.") == 0) - -__attribute__((destructor)) -static void unloadlib(void) -{ - if (veclib) dlclose(veclib); -} - -__attribute__((constructor)) -static void loadlib() -/* automatically executed on module import */ -{ - char errormsg[1024]; - int AVX, MAVERICKS; - memset((void*)errormsg, 0, sizeof(errormsg)); - /* check if the CPU supports AVX */ - AVX = cpu_supports_avx(); - /* check if the OS is MacOS X Mavericks */ - MAVERICKS = using_mavericks(); - /* we need the workaround when the CPU supports - * AVX and the OS version is Mavericks */ - AVX_and_10_9 = AVX && MAVERICKS; - /* load vecLib */ - veclib = dlopen(VECLIB_FILE, RTLD_LOCAL | RTLD_FIRST); - if (!veclib) { - veclib = NULL; - snprintf(errormsg, sizeof(errormsg), - "Failed to open vecLib from location '%s'.", VECLIB_FILE); - Py_FatalError(errormsg); /* calls abort() and dumps core */ - } - /* resolve Fortran SGEMV from Accelerate */ - accelerate_sgemv = (fortran_sgemv_t*) dlsym(veclib, "sgemv_"); - if (!accelerate_sgemv) { - unloadlib(); - Py_FatalError("Failed to resolve symbol 'sgemv_'."); - } - /* resolve cblas_sgemv from Accelerate */ - accelerate_cblas_sgemv = (cblas_sgemv_t*) dlsym(veclib, "cblas_sgemv"); - if (!accelerate_cblas_sgemv) { - unloadlib(); - Py_FatalError("Failed to resolve symbol 'cblas_sgemv'."); - } - /* resolve cblas_sgemm from Accelerate */ - accelerate_cblas_sgemm = (cblas_sgemm_t*) dlsym(veclib, "cblas_sgemm"); - if (!accelerate_cblas_sgemm) { - unloadlib(); - Py_FatalError("Failed to resolve symbol 'cblas_sgemm'."); - } -} - -/* ----------------------------------------------------------------- */ -/* Fortran SGEMV override */ - -void sgemv_( const char* trans, const int* m, const int* n, - const float* alpha, const float* A, const int* ldA, - const float* X, const int* incX, - const float* beta, float* Y, const int* incY ) -{ - /* It is safe to use the original SGEMV if we are not using AVX on Mavericks - * or the input arrays A, X and Y are all aligned on 32 byte boundaries. */ - #define BADARRAY(x) (((npy_intp)(void*)x) % 32) - const int use_sgemm = AVX_and_10_9 && (BADARRAY(A) || BADARRAY(X) || BADARRAY(Y)); - if (!use_sgemm) { - accelerate_sgemv(trans,m,n,alpha,A,ldA,X,incX,beta,Y,incY); - return; - } - - /* Arrays are misaligned, the CPU supports AVX, and we are running - * Mavericks. - * - * Emulation of SGEMV with SGEMM: - * - * SGEMV allows vectors to be strided. SGEMM requires all arrays to be - * contiguous along the leading dimension. To emulate striding in SGEMV - * with the leading dimension arguments in SGEMM we compute - * - * Y = alpha * op(A) @ X + beta * Y - * - * as - * - * Y.T = alpha * X.T @ op(A).T + beta * Y.T - * - * Because Fortran uses column major order and X.T and Y.T are row vectors, - * the leading dimensions of X.T and Y.T in SGEMM become equal to the - * strides of the the column vectors X and Y in SGEMV. */ - - switch (*trans) { - case 'T': - case 't': - case 'C': - case 'c': - accelerate_cblas_sgemm( CblasColMajor, CblasNoTrans, CblasNoTrans, - 1, *n, *m, *alpha, X, *incX, A, *ldA, *beta, Y, *incY ); - break; - case 'N': - case 'n': - accelerate_cblas_sgemm( CblasColMajor, CblasNoTrans, CblasTrans, - 1, *m, *n, *alpha, X, *incX, A, *ldA, *beta, Y, *incY ); - break; - default: - cblas_xerbla(1, "SGEMV", "Illegal transpose setting: %c\n", *trans); - } -} - -/* ----------------------------------------------------------------- */ -/* Override for an alias symbol for sgemv_ in Accelerate */ - -void sgemv (char *trans, - const int *m, const int *n, - const float *alpha, - const float *A, const int *lda, - const float *B, const int *incB, - const float *beta, - float *C, const int *incC) -{ - sgemv_(trans,m,n,alpha,A,lda,B,incB,beta,C,incC); -} - -/* ----------------------------------------------------------------- */ -/* cblas_sgemv override, based on Netlib CBLAS code */ - -void cblas_sgemv(const enum CBLAS_ORDER order, - const enum CBLAS_TRANSPOSE TransA, const int M, const int N, - const float alpha, const float *A, const int lda, - const float *X, const int incX, const float beta, - float *Y, const int incY) -{ - char TA; - if (order == CblasColMajor) - { - if (TransA == CblasNoTrans) TA = 'N'; - else if (TransA == CblasTrans) TA = 'T'; - else if (TransA == CblasConjTrans) TA = 'C'; - else - { - cblas_xerbla(2, "cblas_sgemv","Illegal TransA setting, %d\n", TransA); - } - sgemv_(&TA, &M, &N, &alpha, A, &lda, X, &incX, &beta, Y, &incY); - } - else if (order == CblasRowMajor) - { - if (TransA == CblasNoTrans) TA = 'T'; - else if (TransA == CblasTrans) TA = 'N'; - else if (TransA == CblasConjTrans) TA = 'N'; - else - { - cblas_xerbla(2, "cblas_sgemv", "Illegal TransA setting, %d\n", TransA); - return; - } - sgemv_(&TA, &N, &M, &alpha, A, &lda, X, &incX, &beta, Y, &incY); - } - else - cblas_xerbla(1, "cblas_sgemv", "Illegal Order setting, %d\n", order); -} diff --git a/numpy/build_utils/waf.py b/numpy/build_utils/waf.py deleted file mode 100644 index 263640d9e..000000000 --- a/numpy/build_utils/waf.py +++ /dev/null @@ -1,531 +0,0 @@ -from __future__ import division, absolute_import, print_function - -import os -import re - -import waflib.Configure -import waflib.Tools.c_config -from waflib import Logs, Utils - -from .common \ - import \ - LONG_DOUBLE_REPRESENTATION_SRC, pyod, \ - long_double_representation - -DEFKEYS = waflib.Tools.c_config.DEFKEYS -DEFINE_COMMENTS = "define_commentz" - -def to_header(dct): - if 'header_name' in dct: - dct = Utils.to_list(dct['header_name']) - return ''.join(['#include <%s>\n' % x for x in dct]) - return '' - -# Make the given string safe to be used as a CPP macro -def sanitize_string(s): - key_up = s.upper() - return re.sub('[^A-Z0-9_]', '_', key_up) - -def validate_arguments(self, kw): - if not 'env' in kw: - kw['env'] = self.env.derive() - if not "compile_mode" in kw: - kw["compile_mode"] = "c" - if not 'compile_filename' in kw: - kw['compile_filename'] = 'test.c' + \ - ((kw['compile_mode'] == 'cxx') and 'pp' or '') - if not 'features' in kw: - kw['features'] = [kw['compile_mode']] - if not 'execute' in kw: - kw['execute'] = False - if not 'okmsg' in kw: - kw['okmsg'] = 'yes' - if not 'errmsg' in kw: - kw['errmsg'] = 'no !' - - if 'define_name' in kw: - comment = kw.get('define_comment', None) - self.undefine_with_comment(kw['define_name'], comment) - -def try_compile(self, kw): - self.start_msg(kw["msg"]) - ret = None - try: - ret = self.run_c_code(**kw) - except self.errors.ConfigurationError as e: - self.end_msg(kw['errmsg'], 'YELLOW') - if Logs.verbose > 1: - raise - else: - self.fatal('The configuration failed') - else: - kw['success'] = ret - self.end_msg(self.ret_msg(kw['okmsg'], kw)) - -@waflib.Configure.conf -def check_header(self, header_name, **kw): - code = """ -%s - -int main() -{ -} -""" % to_header({"header_name": header_name}) - - kw["code"] = code - kw["define_comment"] = "/* Define to 1 if you have the <%s> header file. */" % header_name - kw["define_name"] = "HAVE_%s" % sanitize_string(header_name) - if not "features" in kw: - kw["features"] = ["c"] - kw["msg"] = "Checking for header %r" % header_name - - validate_arguments(self, kw) - try_compile(self, kw) - ret = kw["success"] - if ret == 0: - kw["define_value"] = 1 - else: - kw["define_value"] = 0 - - self.post_check(**kw) - if not kw.get('execute', False): - return ret == 0 - return ret - -@waflib.Configure.conf -def check_declaration(self, symbol, **kw): - code = r""" -int main() -{ -#ifndef %s - (void) %s; -#endif - ; - return 0; -} -""" % (symbol, symbol) - - kw["code"] = to_header(kw) + code - kw["msg"] = "Checking for macro %r" % symbol - kw["errmsg"] = "not found" - kw["okmsg"] = "yes" - - validate_arguments(self, kw) - try_compile(self, kw) - ret = kw["success"] - - kw["define_name"] = "HAVE_DECL_%s" % sanitize_string(symbol) - kw["define_comment"] = "/* Set to 1 if %s is defined. */" % symbol - self.post_check(**kw) - if not kw.get('execute', False): - return ret == 0 - return ret - -@waflib.Configure.conf -def check_type(self, type_name, **kw): - code = r""" -int main() { - if ((%(type_name)s *) 0) - return 0; - if (sizeof (%(type_name)s)) - return 0; -} -""" % {"type_name": type_name} - - kw["code"] = to_header(kw) + code - kw["msg"] = "Checking for type %r" % type_name - kw["errmsg"] = "not found" - kw["okmsg"] = "yes" - - validate_arguments(self, kw) - try_compile(self, kw) - ret = kw["success"] - if ret == 0: - kw["define_value"] = 1 - else: - kw["define_value"] = 0 - - kw["define_name"] = "HAVE_%s" % sanitize_string(type_name) - kw["define_comment"] = "/* Define to 1 if the system has the type `%s'. */" % type_name - self.post_check(**kw) - if not kw.get('execute', False): - 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 as 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 - -@waflib.Configure.conf -def check_functions_at_once(self, funcs, **kw): - header = [] - header = ['#ifdef __cplusplus'] - header.append('extern "C" {') - header.append('#endif') - for f in funcs: - header.append("\tchar %s();" % f) - # Handle MSVC intrinsics: force MS compiler to make a function - # call. Useful to test for some functions when built with - # optimization on, to avoid build error because the intrinsic - # and our 'fake' test declaration do not match. - header.append("#ifdef _MSC_VER") - header.append("#pragma function(%s)" % f) - header.append("#endif") - header.append('#ifdef __cplusplus') - header.append('};') - header.append('#endif') - funcs_decl = "\n".join(header) - - tmp = [] - for f in funcs: - tmp.append("\t%s();" % f) - tmp = "\n".join(tmp) - - code = r""" -%(include)s -%(funcs_decl)s - -int main (void) -{ - %(tmp)s - return 0; -} -""" % {"tmp": tmp, "include": to_header(kw), "funcs_decl": funcs_decl} - kw["code"] = code - if not "features" in kw: - kw["features"] = ["c", "cprogram"] - - msg = ", ".join(funcs) - if len(msg) > 30: - _funcs = list(funcs) - msg = [] - while len(", ".join(msg)) < 30 and _funcs: - msg.append(_funcs.pop(0)) - msg = ", ".join(msg) + ",..." - if "lib" in kw: - kw["msg"] = "Checking for functions %s in library %r" % (msg, kw["lib"]) - else: - kw["msg"] = "Checking for functions %s" % msg - - validate_arguments(self, kw) - try_compile(self, kw) - ret = kw["success"] - - # We set the config.h define here because we need to define several of them - # in one shot - if ret == 0: - for f in funcs: - self.define_with_comment("HAVE_%s" % sanitize_string(f), 1, - "/* Define to 1 if you have the `%s' function. */" % f) - - self.post_check(**kw) - if not kw.get('execute', False): - return ret == 0 - return ret - -@waflib.Configure.conf -def check_inline(conf, **kw): - validate_arguments(conf, kw) - - code = """ -#ifndef __cplusplus -static %(inline)s int static_func (void) -{ - return 0; -} -%(inline)s int nostatic_func (void) -{ - return 0; -} -#endif""" - - conf.start_msg("Checking for inline support") - inline = None - for k in ['inline', '__inline__', '__inline']: - try: - kw["code"] = code % {"inline": k} - ret = conf.run_c_code(**kw) - inline = k - break - except conf.errors.ConfigurationError: - pass - - if inline is None: - conf.end_msg("failed", 'YELLOW') - if Logs.verbose > 1: - raise - else: - conf.fatal('The configuration failed') - else: - kw['success'] = ret - conf.end_msg(inline) - return inline - -@waflib.Configure.conf -def check_ldouble_representation(conf, **kw): - msg = { - 'INTEL_EXTENDED_12_BYTES_LE': "Intel extended, little endian", - 'INTEL_EXTENDED_16_BYTES_LE': "Intel extended, little endian", - 'IEEE_QUAD_BE': "IEEE Quad precision, big endian", - 'IEEE_QUAD_LE': "IEEE Quad precision, little endian", - 'IEEE_DOUBLE_LE': "IEEE Double precision, little endian", - 'IEEE_DOUBLE_BE': "IEEE Double precision, big endian" - } - - code = LONG_DOUBLE_REPRESENTATION_SRC % {'type': 'long double'} - validate_arguments(conf, kw) - - conf.start_msg("Checking for long double representation... ") - try: - kw["code"] = code - ret = conf.run_c_code(**kw) - except conf.errors.ConfigurationError as e: - conf.end_msg(kw['errmsg'], 'YELLOW') - if Logs.verbose > 1: - raise - else: - conf.fatal('The configuration failed') - else: - task_gen = conf.test_bld.groups[0][0] - obj_filename = task_gen.tasks[0].outputs[0].abspath() - tp = long_double_representation(pyod(obj_filename)) - kw['success'] = ret - conf.end_msg(msg[tp]) - kw["define_name"] = "HAVE_LDOUBLE_%s" % tp - kw["define_comment"] = "/* Define for arch-specific long double representation */" - ret = kw["success"] - - conf.post_check(**kw) - if not kw.get('execute', False): - return ret == 0 - return ret - -@waflib.Configure.conf -def post_check(self, *k, **kw): - "set the variables after a test was run successfully" - - is_success = False - if kw['execute']: - if kw['success'] is not None: - if kw.get('define_ret', False): - is_success = kw['success'] - else: - is_success = (kw['success'] == 0) - else: - is_success = (kw['success'] == 0) - - def define_or_stuff(): - nm = kw['define_name'] - cmt = kw.get('define_comment', None) - value = kw.get("define_value", is_success) - if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str): - self.define_with_comment(kw['define_name'], value, cmt, quote=kw.get('quote', 1)) - else: - self.define_cond(kw['define_name'], value, cmt) - - if 'define_name' in kw: - define_or_stuff() - - if is_success and 'uselib_store' in kw: - from waflib.Tools import ccroot - - # TODO see get_uselib_vars from ccroot.py - _vars = set([]) - for x in kw['features']: - if x in ccroot.USELIB_VARS: - _vars |= ccroot.USELIB_VARS[x] - - for k in _vars: - lk = k.lower() - if k == 'INCLUDES': lk = 'includes' - if k == 'DEFKEYS': lk = 'defines' - if lk in kw: - val = kw[lk] - # remove trailing slash - if isinstance(val, str): - val = val.rstrip(os.path.sep) - self.env.append_unique(k + '_' + kw['uselib_store'], val) - return is_success - -@waflib.Configure.conf -def define_with_comment(conf, define, value, comment=None, quote=True): - if comment is None: - return conf.define(define, value, quote) - - assert define and isinstance(define, str) - - comment_tbl = conf.env[DEFINE_COMMENTS] or {} - comment_tbl[define] = comment - conf.env[DEFINE_COMMENTS] = comment_tbl - - return conf.define(define, value, quote) - -@waflib.Configure.conf -def undefine_with_comment(conf, define, comment=None): - if comment is None: - return conf.undefine(define) - - comment_tbl = conf.env[DEFINE_COMMENTS] or {} - comment_tbl[define] = comment - conf.env[DEFINE_COMMENTS] = comment_tbl - - conf.undefine(define) - -@waflib.Configure.conf -def get_comment(self, key): - assert key and isinstance(key, str) - - if key in self.env[DEFINE_COMMENTS]: - return self.env[DEFINE_COMMENTS][key] - return None - -@waflib.Configure.conf -def define_cond(self, name, value, comment): - """Conditionally define a name. - Formally equivalent to: if value: define(name, 1) else: undefine(name)""" - if value: - self.define_with_comment(name, value, comment) - else: - self.undefine(name) - -@waflib.Configure.conf -def get_config_header(self, defines=True, headers=False, define_prefix=None): - """ - Create the contents of a ``config.h`` file from the defines and includes - set in conf.env.define_key / conf.env.include_key. No include guards are added. - - :param defines: write the defines values - :type defines: bool - :param headers: write the headers - :type headers: bool - :return: the contents of a ``config.h`` file - :rtype: string - """ - tpl = self.env["CONFIG_HEADER_TEMPLATE"] or "%(content)s" - - lst = [] - if headers: - for x in self.env[INCKEYS]: - lst.append('#include <%s>' % x) - - if defines: - for x in self.env[DEFKEYS]: - cmt = self.get_comment(x) - if cmt is not None: - lst.append(cmt) - if self.is_defined(x): - val = self.get_define(x) - lst.append('#define %s %s\n' % (x, val)) - else: - lst.append('/* #undef %s */\n' % x) - return tpl % {"content": "\n".join(lst)} |