summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarrod Millman <millman@berkeley.edu>2008-02-08 10:12:16 +0000
committerJarrod Millman <millman@berkeley.edu>2008-02-08 10:12:16 +0000
commit0b7800b455b3aaf50cb83a224f283e72f1dea951 (patch)
treeaab6281c88fd6bed7c74df03562c197d934edd83
parent964727a2c475a7e48e262efc52b51345f51f2522 (diff)
parentfb3f711f1a1eafb2895a84a80f88814d7fb9a465 (diff)
downloadnumpy-0b7800b455b3aaf50cb83a224f283e72f1dea951.tar.gz
merging David Cournapeau's build_with_scons branch, which adds scons support to numpy.distutils and modifies the configuration of numpy/core
-rw-r--r--numpy/core/SConstruct292
-rw-r--r--numpy/core/code_generators/__init__.py0
-rw-r--r--numpy/core/code_generators/generate_array_api.py35
-rw-r--r--numpy/core/code_generators/generate_ufunc_api.py31
-rw-r--r--numpy/core/include/numpy/ndarrayobject.h45
-rw-r--r--numpy/core/include/numpy/numpyconfig.h.in16
-rw-r--r--numpy/core/scons_support.py183
-rw-r--r--numpy/core/setup.py175
-rw-r--r--numpy/core/setupscons.py106
-rw-r--r--numpy/core/src/arraytypes.inc.src1
-rw-r--r--numpy/core/src/multiarraymodule.c2
-rw-r--r--numpy/core/src/umathmodule.c.src1
-rw-r--r--numpy/distutils/command/build.py6
-rw-r--r--numpy/distutils/command/config.py15
-rw-r--r--numpy/distutils/command/scons.py335
-rw-r--r--numpy/distutils/core.py10
-rw-r--r--numpy/distutils/misc_util.py110
-rw-r--r--numpy/distutils/numpy_distribution.py28
-rw-r--r--numpy/distutils/setupscons.py15
-rwxr-xr-xnumpy/f2py/setupscons.py130
-rw-r--r--numpy/fft/SConstruct13
-rw-r--r--numpy/fft/setupscons.py15
-rw-r--r--numpy/lib/SConstruct12
-rw-r--r--numpy/lib/setupscons.py16
-rw-r--r--numpy/linalg/SConstruct33
-rw-r--r--numpy/linalg/setupscons.py20
-rw-r--r--numpy/numarray/SConstruct12
-rw-r--r--numpy/numarray/setupscons.py14
-rw-r--r--numpy/oldnumeric/setupscons.py8
-rw-r--r--numpy/random/SConstruct50
-rw-r--r--numpy/random/setupscons.py40
-rw-r--r--numpy/setupscons.py22
-rwxr-xr-xnumpy/testing/setupscons.py16
-rwxr-xr-xsetupscons.py108
-rw-r--r--test.sh18
35 files changed, 1852 insertions, 81 deletions
diff --git a/numpy/core/SConstruct b/numpy/core/SConstruct
new file mode 100644
index 000000000..209d642c7
--- /dev/null
+++ b/numpy/core/SConstruct
@@ -0,0 +1,292 @@
+# Last Change: Wed Jan 23 08:00 PM 2008 J
+# vim:syntax=python
+import os
+import sys
+from os.path import join as pjoin, basename as pbasename, dirname as pdirname
+from copy import deepcopy
+
+from numscons import get_python_inc, get_pythonlib_dir
+from numscons import GetNumpyEnvironment
+from numscons import CheckCBLAS
+from numscons import write_info
+
+from scons_support import CheckBrokenMathlib, define_no_smp, \
+ check_mlib, check_mlibs, is_npy_no_signal
+
+env = GetNumpyEnvironment(ARGUMENTS)
+env.Append(CPPPATH = [get_python_inc()])
+if os.name == 'nt':
+ # NT needs the pythonlib to run any code importing Python.h, including
+ # simple code using only typedef and so on, so we need it for configuration
+ # checks
+ env.AppendUnique(LIBPATH = [get_pythonlib_dir()])
+
+#=======================
+# Starting Configuration
+#=======================
+config = env.NumpyConfigure(custom_tests = {'CheckBrokenMathlib' : CheckBrokenMathlib,
+ 'CheckCBLAS' : CheckCBLAS}, config_h = pjoin(env['build_dir'], 'config.h'))
+
+# numpyconfig_sym will keep the values of some configuration variables, the one
+# needed for the public numpy API.
+
+# Convention: list of tuples (definition, value). value:
+# - 0: #undef definition
+# - 1: #define definition
+# - string: #define definition value
+numpyconfig_sym = []
+
+#---------------
+# Checking Types
+#---------------
+def check_type(type, include = None):
+ st = config.CheckTypeSize(type, includes = include)
+ type = type.replace(' ', '_')
+ if st:
+ numpyconfig_sym.append(('SIZEOF_%s' % type.upper(), '%d' % st))
+ else:
+ numpyconfig_sym.append(('SIZEOF_%s' % type.upper(), 0))
+
+for type in ('short', 'int', 'long', 'float', 'double', 'long double'):
+ check_type(type)
+
+for type in ('Py_intptr_t',):
+ check_type(type, include = "#include <Python.h>\n")
+
+# We check declaration AND type because that's how distutils does it.
+if config.CheckDeclaration('PY_LONG_LONG', includes = '#include <Python.h>\n'):
+ st = config.CheckTypeSize('PY_LONG_LONG', includes = '#include <Python.h>\n')
+ assert not st == 0
+ numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_LONGLONG', '#define NPY_SIZEOF_LONGLONG %d' % st))
+ numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_PY_LONG_LONG', '#define NPY_SIZEOF_PY_LONG_LONG %d' % st))
+else:
+ numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_LONGLONG', ''))
+ numpyconfig_sym.append(('DEFINE_NPY_SIZEOF_PY_LONG_LONG', ''))
+
+if not config.CheckDeclaration('CHAR_BIT', includes= '#include <Python.h>\n'):
+ raise RuntimeError("Config wo CHAR_BIT is not supported with scons: please contact the maintainer (cdavid)")
+
+#----------------------
+# Checking signal stuff
+#----------------------
+if is_npy_no_signal():
+ numpyconfig_sym.append(('DEFINE_NPY_NO_SIGNAL', '#define NPY_NO_SIGNAL\n'))
+ config.Define('__NPY_PRIVATE_NO_SIGNAL', comment = "define to 1 to disable SMP support ")
+else:
+ numpyconfig_sym.append(('DEFINE_NPY_NO_SIGNAL', ''))
+
+#---------------------
+# Checking SMP option
+#---------------------
+if define_no_smp():
+ nosmp = 1
+else:
+ nosmp = 0
+numpyconfig_sym.append(('NPY_NO_SMP', nosmp))
+
+#----------------------
+# Checking the mathlib
+#----------------------
+mlibs = [[], ['m'], ['cpml']]
+mathlib = os.environ.get('MATHLIB')
+if mathlib:
+ mlibs.insert(0, mathlib)
+
+mlib = check_mlibs(config, mlibs)
+
+# XXX: this is ugly: mathlib has nothing to do in a public header file
+numpyconfig_sym.append(('MATHLIB', ','.join(mlib)))
+
+#----------------------------------
+# Checking the math funcs available
+#----------------------------------
+# Function to check:
+mfuncs = ('expl', 'expf', 'log1p', 'expm1', 'asinh', 'atanhf', 'atanhl',
+ 'isnan', 'isinf', 'rint')
+
+# Set value to 1 for each defined function (in math lib)
+mfuncs_defined = dict([(f, 0) for f in mfuncs])
+
+# TODO: checklib vs checkfunc ?
+def check_func(f):
+ """Check that f is available in mlib, and add the symbol appropriately. """
+ st = config.CheckDeclaration(f, language = 'C', includes = "#include <math.h>")
+ if st:
+ st = config.CheckFunc(f, language = 'C')
+ if st:
+ mfuncs_defined[f] = 1
+ else:
+ mfuncs_defined[f] = 0
+
+for f in mfuncs:
+ check_func(f)
+
+if mfuncs_defined['expl'] == 1:
+ config.Define('HAVE_LONGDOUBLE_FUNCS',
+ comment = 'Define to 1 if long double funcs are available')
+if mfuncs_defined['expf'] == 1:
+ config.Define('HAVE_FLOAT_FUNCS',
+ comment = 'Define to 1 if long double funcs are available')
+if mfuncs_defined['asinh'] == 1:
+ config.Define('HAVE_INVERSE_HYPERBOLIC',
+ comment = 'Define to 1 if inverse hyperbolic funcs are available')
+if mfuncs_defined['atanhf'] == 1:
+ config.Define('HAVE_INVERSE_HYPERBOLIC_FLOAT',
+ comment = 'Define to 1 if inverse hyperbolic float funcs are available')
+if mfuncs_defined['atanhl'] == 1:
+ config.Define('HAVE_INVERSE_HYPERBOLIC_LONGDOUBLE',
+ comment = 'Define to 1 if inverse hyperbolic long double funcs are available')
+
+#-------------------------------------------------------
+# Define the function PyOS_ascii_strod if not available
+#-------------------------------------------------------
+if not config.CheckDeclaration('PyOS_ascii_strtod',
+ includes = "#include <Python.h>"):
+ if config.CheckFunc('strtod'):
+ config.Define('PyOS_ascii_strtod', 'strtod',
+ "Define to a function to use as a replacement for "\
+ "PyOS_ascii_strtod if not available in python header")
+
+#------------------------------------
+# DISTUTILS Hack on AMD64 on windows
+#------------------------------------
+# XXX: this is ugly
+if sys.platform=='win32' or os.name=='nt':
+ from distutils.msvccompiler import get_build_architecture
+ a = get_build_architecture()
+ print 'BUILD_ARCHITECTURE: %r, os.name=%r, sys.platform=%r' % (a, os.name, sys.platform)
+ if a == 'AMD64':
+ distutils_use_sdk = 1
+ config.Define('DISTUTILS_USE_SDK', distutils_use_sdk,
+ "define to 1 to disable SMP support ")
+
+#--------------
+# Checking Blas
+#--------------
+if config.CheckCBLAS():
+ build_blasdot = 1
+else:
+ build_blasdot = 0
+
+config.Finish()
+write_info(env)
+
+#==========
+# Build
+#==========
+
+#---------------------------------------
+# Generate the public configuration file
+#---------------------------------------
+config_dict = {}
+# XXX: this is ugly, make the API for config.h and numpyconfig.h similar
+for key, value in numpyconfig_sym:
+ config_dict['@%s@' % key] = str(value)
+env['SUBST_DICT'] = config_dict
+
+include_dir = 'include/numpy'
+env.SubstInFile(pjoin(env['build_dir'], 'numpyconfig.h'),
+ pjoin(env['src_dir'], include_dir, 'numpyconfig.h.in'))
+
+env['CONFIG_H_GEN'] = numpyconfig_sym
+
+#---------------------------
+# Builder for generated code
+#---------------------------
+from scons_support import do_generate_array_api, do_generate_ufunc_api, \
+ generate_api_emitter,\
+ generate_from_template, generate_from_template_emitter, \
+ generate_umath, generate_umath_emitter
+
+array_api_gen_bld = Builder(action = do_generate_array_api,
+ emitter = generate_api_emitter)
+
+ufunc_api_gen_bld = Builder(action = do_generate_ufunc_api,
+ emitter = generate_api_emitter)
+
+template_bld = Builder(action = generate_from_template,
+ emitter = generate_from_template_emitter)
+
+umath_bld = Builder(action = generate_umath,
+ emitter = generate_umath_emitter)
+
+env.Append(BUILDERS = {'GenerateMultiarrayApi' : array_api_gen_bld,
+ 'GenerateUfuncApi' : ufunc_api_gen_bld,
+ 'GenerateFromTemplate' : template_bld,
+ 'GenerateUmath' : umath_bld})
+
+#------------------------
+# Generate generated code
+#------------------------
+# XXX: the use of env['build_dir'] and env['src_dir'] are really ugly. Will
+# have to think about how removing them (using hierarchical scons and dir
+# option ?)
+from os.path import join as pjoin
+
+scalartypes_src = env.GenerateFromTemplate(
+ pjoin(env['build_dir'], 'src', 'scalartypes'),
+ pjoin(env['src_dir'], 'src', 'scalartypes.inc.src'))
+
+arraytypes_src = env.GenerateFromTemplate(
+ pjoin(env['build_dir'], 'src', 'arraytypes'),
+ pjoin(env['src_dir'], 'src', 'arraytypes.inc.src'))
+
+sortmodule_src = env.GenerateFromTemplate(
+ pjoin(env['build_dir'], 'src', '_sortmodule'),
+ pjoin(env['src_dir'], 'src', '_sortmodule.c.src'))
+
+umathmodule_src = env.GenerateFromTemplate(
+ pjoin(env['build_dir'], 'src', 'umathmodule'),
+ pjoin(env['src_dir'], 'src', 'umathmodule.c.src'))
+
+scalarmathmodule_src = env.GenerateFromTemplate(
+ pjoin(env['build_dir'], 'src', 'scalarmathmodule'),
+ pjoin(env['src_dir'], 'src', 'scalarmathmodule.c.src'))
+
+umath = env.GenerateUmath(
+ pjoin(env['build_dir'], '__umath_generated'),
+ pjoin(env['src_dir'], 'code_generators', 'generate_umath.py'))
+
+multiarray_api = env.GenerateMultiarrayApi(
+ pjoin(env['build_dir'], 'multiarray_api'),
+ [ pjoin(env['src_dir'], 'code_generators',
+ 'array_api_order.txt'),
+ pjoin(env['src_dir'], 'code_generators',
+ 'multiarray_api_order.txt')])
+
+ufunc_api = env.GenerateUfuncApi(
+ pjoin(env['build_dir'], 'ufunc_api'),
+ pjoin(env['src_dir'], 'code_generators', 'ufunc_api_order.txt'))
+
+env.Append(CPPPATH = [pjoin(env['src_dir'], 'include'), env['build_dir']])
+
+#-----------------
+# Build multiarray
+#-----------------
+multiarray_src = [pjoin('src', 'multiarraymodule.c')]
+multiarray = env.NumpyPythonExtension('multiarray', source = multiarray_src)
+
+#------------------
+# Build sort module
+#------------------
+sort = env.NumpyPythonExtension('_sort', source = sortmodule_src)
+
+#-------------------
+# Build umath module
+#-------------------
+umathmodule = env.NumpyPythonExtension('umath', source = umathmodule_src)
+
+#------------------------
+# Build scalarmath module
+#------------------------
+scalarmathmodule = env.NumpyPythonExtension('scalarmath',
+ source = scalarmathmodule_src)
+
+#----------------------
+# Build _dotblas module
+#----------------------
+if build_blasdot:
+ dotblas_src = [pjoin('blasdot', i) for i in ['_dotblas.c']]
+ blasenv = env.Copy()
+ blasenv.Append(CPPPATH = pjoin(env['src_dir'], 'blasdot'))
+ dotblas = blasenv.NumpyPythonExtension('_dotblas', source = dotblas_src)
diff --git a/numpy/core/code_generators/__init__.py b/numpy/core/code_generators/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/numpy/core/code_generators/__init__.py
diff --git a/numpy/core/code_generators/generate_array_api.py b/numpy/core/code_generators/generate_array_api.py
index c6f73c33f..94ab37fa3 100644
--- a/numpy/core/code_generators/generate_array_api.py
+++ b/numpy/core/code_generators/generate_array_api.py
@@ -1,9 +1,6 @@
import os
import genapi
-OBJECT_API_ORDER = 'array_api_order.txt'
-MULTIARRAY_API_ORDER = 'multiarray_api_order.txt'
-
types = ['Generic','Number','Integer','SignedInteger','UnsignedInteger',
'Inexact',
'Floating', 'ComplexFloating', 'Flexible', 'Character',
@@ -122,22 +119,30 @@ void *PyArray_API[] = {
"""
def generate_api(output_dir, force=False):
- header_file = os.path.join(output_dir, '__multiarray_api.h')
- c_file = os.path.join(output_dir,'__multiarray_api.c')
- doc_file = os.path.join(output_dir, 'multiarray_api.txt')
-
- targets = (header_file, c_file, doc_file)
- if (not force
- and not genapi.should_rebuild(targets,
- [OBJECT_API_ORDER,
- MULTIARRAY_API_ORDER,
- __file__])):
+ basename = 'multiarray_api'
+
+ h_file = os.path.join(output_dir, '__%s.h' % basename)
+ c_file = os.path.join(output_dir, '__%s.c' % basename)
+ d_file = os.path.join(output_dir, '%s.txt' % basename)
+ targets = (h_file, c_file, d_file)
+ sources = ['array_api_order.txt', 'multiarray_api_order.txt']
+
+ if (not force and not genapi.should_rebuild(targets, sources + [__file__])):
return targets
+ else:
+ do_generate_api(targets, sources)
+
+ return targets
+
+def do_generate_api(targets, sources):
+ header_file = targets[0]
+ c_file = targets[1]
+ doc_file = targets[2]
objectapi_list = genapi.get_api_functions('OBJECT_API',
- OBJECT_API_ORDER)
+ sources[0])
multiapi_list = genapi.get_api_functions('MULTIARRAY_API',
- MULTIARRAY_API_ORDER)
+ sources[1])
# API fixes for __arrayobject_api.h
fixed = 10
diff --git a/numpy/core/code_generators/generate_ufunc_api.py b/numpy/core/code_generators/generate_ufunc_api.py
index 96bb47cae..fa858b207 100644
--- a/numpy/core/code_generators/generate_ufunc_api.py
+++ b/numpy/core/code_generators/generate_ufunc_api.py
@@ -1,8 +1,6 @@
import os
import genapi
-UFUNC_API_ORDER = 'ufunc_api_order.txt'
-
h_template = r"""
#ifdef _UMATHMODULE
@@ -72,17 +70,28 @@ void *PyUFunc_API[] = {
"""
def generate_api(output_dir, force=False):
- header_file = os.path.join(output_dir, '__ufunc_api.h')
- c_file = os.path.join(output_dir, '__ufunc_api.c')
- doc_file = os.path.join(output_dir, 'ufunc_api.txt')
-
- targets = (header_file, c_file, doc_file)
- if (not force
- and not genapi.should_rebuild(targets,
- [UFUNC_API_ORDER, __file__])):
+ basename = 'ufunc_api'
+
+ h_file = os.path.join(output_dir, '__%s.h' % basename)
+ c_file = os.path.join(output_dir, '__%s.c' % basename)
+ d_file = os.path.join(output_dir, '%s.txt' % basename)
+ targets = (h_file, c_file, d_file)
+
+ sources = ['ufunc_api_order.txt']
+
+ if (not force and not genapi.should_rebuild(targets, sources + [__file__])):
return targets
+ else:
+ do_generate_api(targets, sources)
+
+ return targets
+
+def do_generate_api(targets, sources):
+ header_file = targets[0]
+ c_file = targets[1]
+ doc_file = targets[2]
- ufunc_api_list = genapi.get_api_functions('UFUNC_API', UFUNC_API_ORDER)
+ ufunc_api_list = genapi.get_api_functions('UFUNC_API', sources[0])
# API fixes for __arrayobject_api.h
diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h
index 62986a9eb..3b1376cd3 100644
--- a/numpy/core/include/numpy/ndarrayobject.h
+++ b/numpy/core/include/numpy/ndarrayobject.h
@@ -13,7 +13,14 @@ extern "C" CONFUSE_EMACS
everything when you're typing */
#endif
/* This is auto-generated by the installer */
-#include "config.h"
+#include "numpyconfig.h"
+
+/* Only use thread if configured in config and python supports it */
+#if defined WITH_THREAD && !NPY_NO_SMP
+ #define NPY_ALLOW_THREADS 1
+#else
+ #define NPY_ALLOW_THREADS 0
+#endif
/* There are several places in the code where an array of dimensions is
* allocated statically. This is the size of that static allocation.
@@ -80,7 +87,8 @@ typedef unsigned char npy_bool;
#define NPY_FALSE 0
#define NPY_TRUE 1
-#if SIZEOF_LONG_DOUBLE==SIZEOF_DOUBLE
+
+#if NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE
typedef double npy_longdouble;
#define NPY_LONGDOUBLE_FMT "g"
#else
@@ -279,22 +287,15 @@ typedef enum {
#define NPY_MAX_ULONG ULONG_MAX
-#define NPY_SIZEOF_LONG SIZEOF_LONG
-#define NPY_SIZEOF_INT SIZEOF_INT
-#define NPY_SIZEOF_SHORT SIZEOF_SHORT
-#define NPY_SIZEOF_FLOAT SIZEOF_FLOAT
-#define NPY_SIZEOF_DOUBLE SIZEOF_DOUBLE
-#define NPY_SIZEOF_LONGDOUBLE SIZEOF_LONG_DOUBLE
-#define NPY_SIZEOF_LONGLONG SIZEOF_LONG_LONG
#define NPY_BITSOF_BOOL (sizeof(npy_bool)*CHAR_BIT)
#define NPY_BITSOF_CHAR CHAR_BIT
-#define NPY_BITSOF_SHORT (SIZEOF_SHORT*CHAR_BIT)
-#define NPY_BITSOF_INT (SIZEOF_INT*CHAR_BIT)
-#define NPY_BITSOF_LONG (SIZEOF_LONG*CHAR_BIT)
-#define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG*CHAR_BIT)
-#define NPY_BITSOF_FLOAT (SIZEOF_FLOAT*CHAR_BIT)
-#define NPY_BITSOF_DOUBLE (SIZEOF_DOUBLE*CHAR_BIT)
-#define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE*CHAR_BIT)
+#define NPY_BITSOF_SHORT (NPY_SIZEOF_SHORT * CHAR_BIT)
+#define NPY_BITSOF_INT (NPY_SIZEOF_INT * CHAR_BIT)
+#define NPY_BITSOF_LONG (NPY_SIZEOF_LONG * CHAR_BIT)
+#define NPY_BITSOF_LONGLONG (NPY_SIZEOF_LONGLONG * CHAR_BIT)
+#define NPY_BITSOF_FLOAT (NPY_SIZEOF_FLOAT * CHAR_BIT)
+#define NPY_BITSOF_DOUBLE (NPY_SIZEOF_DOUBLE * CHAR_BIT)
+#define NPY_BITSOF_LONGDOUBLE (NPY_SIZEOF_LONGDOUBLE * CHAR_BIT)
#if NPY_BITSOF_LONG == 8
#define NPY_INT8 NPY_LONG
@@ -918,8 +919,8 @@ typedef enum {
* platform. Py_intptr_t, Py_uintptr_t are defined in pyport.h. */
typedef Py_intptr_t npy_intp;
typedef Py_uintptr_t npy_uintp;
-#define NPY_SIZEOF_INTP SIZEOF_PY_INTPTR_T
-#define NPY_SIZEOF_UINTP SIZEOF_PY_INTPTR_T
+#define NPY_SIZEOF_INTP NPY_SIZEOF_PY_INTPTR_T
+#define NPY_SIZEOF_UINTP NPY_SIZEOF_PY_INTPTR_T
#ifdef constchar
#undef constchar
@@ -940,7 +941,7 @@ typedef Py_uintptr_t npy_uintp;
#define constchar char
#endif
-#if SIZEOF_PY_INTPTR_T == SIZEOF_INT
+#if NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_INT
#define NPY_INTP NPY_INT
#define NPY_UINTP NPY_UINT
#define PyIntpArrType_Type PyIntArrType_Type
@@ -949,7 +950,7 @@ typedef Py_uintptr_t npy_uintp;
#define NPY_MIN_INTP NPY_MIN_INT
#define NPY_MAX_UINTP NPY_MAX_UINT
#define NPY_INTP_FMT "d"
-#elif SIZEOF_PY_INTPTR_T == SIZEOF_LONG
+#elif NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONG
#define NPY_INTP NPY_LONG
#define NPY_UINTP NPY_ULONG
#define PyIntpArrType_Type PyLongArrType_Type
@@ -958,7 +959,7 @@ typedef Py_uintptr_t npy_uintp;
#define NPY_MIN_INTP MIN_LONG
#define NPY_MAX_UINTP NPY_MAX_ULONG
#define NPY_INTP_FMT "ld"
-#elif defined(PY_LONG_LONG) && (SIZEOF_PY_INTPTR_T == SIZEOF_LONG_LONG)
+#elif defined(PY_LONG_LONG) && (NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONGLONG)
#define NPY_INTP NPY_LONGLONG
#define NPY_UINTP NPY_ULONGLONG
#define PyIntpArrType_Type PyLongLongArrType_Type
@@ -1894,7 +1895,7 @@ typedef struct {
#define PyArray_REFCOUNT(obj) (((PyObject *)(obj))->ob_refcnt)
#define NPY_REFCOUNT PyArray_REFCOUNT
-#define NPY_MAX_ELSIZE (2*SIZEOF_LONGDOUBLE)
+#define NPY_MAX_ELSIZE (2 * NPY_SIZEOF_LONGDOUBLE)
#define PyArray_ContiguousFromAny(op, type, min_depth, max_depth) \
PyArray_FromAny(op, PyArray_DescrFromType(type), min_depth, \
diff --git a/numpy/core/include/numpy/numpyconfig.h.in b/numpy/core/include/numpy/numpyconfig.h.in
new file mode 100644
index 000000000..929dc720d
--- /dev/null
+++ b/numpy/core/include/numpy/numpyconfig.h.in
@@ -0,0 +1,16 @@
+#define NPY_SIZEOF_SHORT @SIZEOF_SHORT@
+#define NPY_SIZEOF_INT @SIZEOF_INT@
+#define NPY_SIZEOF_LONG @SIZEOF_LONG@
+#define NPY_SIZEOF_FLOAT @SIZEOF_FLOAT@
+#define NPY_SIZEOF_DOUBLE @SIZEOF_DOUBLE@
+#define NPY_SIZEOF_LONGDOUBLE @SIZEOF_LONG_DOUBLE@
+#define NPY_SIZEOF_PY_INTPTR_T @SIZEOF_PY_INTPTR_T@
+
+@DEFINE_NPY_NO_SIGNAL@
+#define NPY_NO_SMP @NPY_NO_SMP@
+
+/* XXX: this has really nothing to do in a config file... */
+#define NPY_MATHLIB @MATHLIB@
+
+@DEFINE_NPY_SIZEOF_LONGLONG@
+@DEFINE_NPY_SIZEOF_PY_LONG_LONG@
diff --git a/numpy/core/scons_support.py b/numpy/core/scons_support.py
new file mode 100644
index 000000000..2c08d648f
--- /dev/null
+++ b/numpy/core/scons_support.py
@@ -0,0 +1,183 @@
+#! Last Change: Tue Jan 08 10:00 PM 2008 J
+
+"""Code to support special facilities to scons which are only useful for
+numpy.core, hence not put into numpy.distutils.scons"""
+
+import sys
+import os
+
+from os.path import join as pjoin, dirname as pdirname, basename as pbasename
+from copy import deepcopy
+
+from code_generators.generate_array_api import \
+ do_generate_api as nowrap_do_generate_array_api
+from code_generators.generate_ufunc_api import \
+ do_generate_api as nowrap_do_generate_ufunc_api
+
+from numscons.numdist import process_c_str as process_str
+from numscons.core.utils import rsplit, isstring
+
+import SCons.Node
+import SCons
+
+def split_ext(string):
+ sp = rsplit(string, '.', 1)
+ if len(sp) == 1:
+ return (sp[0], '')
+ else:
+ return sp
+#------------------------------------
+# Ufunc and multiarray API generators
+#------------------------------------
+def do_generate_array_api(target, source, env):
+ nowrap_do_generate_array_api([str(i) for i in target],
+ [str(i) for i in source])
+ return 0
+
+def do_generate_ufunc_api(target, source, env):
+ nowrap_do_generate_ufunc_api([str(i) for i in target],
+ [str(i) for i in source])
+ return 0
+
+def generate_api_emitter(target, source, env):
+ """Returns the list of targets generated by the code generator for array
+ api and ufunc api."""
+ base, ext = split_ext(str(target[0]))
+ dir = pdirname(base)
+ ba = pbasename(base)
+ h = pjoin(dir, '__' + ba + '.h')
+ c = pjoin(dir, '__' + ba + '.c')
+ txt = base + '.txt'
+ #print h, c, txt
+ t = [h, c, txt]
+ return (t, source)
+
+#-------------------------
+# From template generators
+#-------------------------
+# XXX: this is general and can be used outside numpy.core.
+def do_generate_from_template(targetfile, sourcefile, env):
+ t = open(targetfile, 'w')
+ s = open(sourcefile, 'r')
+ allstr = s.read()
+ s.close()
+ writestr = process_str(allstr)
+ t.write(writestr)
+ t.close()
+ return 0
+
+def generate_from_template(target, source, env):
+ for t, s in zip(target, source):
+ do_generate_from_template(str(t), str(s), env)
+
+def generate_from_template_emitter(target, source, env):
+ base, ext = split_ext(pbasename(str(source[0])))
+ t = pjoin(pdirname(str(target[0])), base)
+ return ([t], source)
+
+#----------------
+# umath generator
+#----------------
+def do_generate_umath(targetfile, sourcefile, env):
+ t = open(targetfile, 'w')
+ from code_generators import generate_umath
+ code = generate_umath.make_code(generate_umath.defdict, generate_umath.__file__)
+ t.write(code)
+ t.close()
+
+def generate_umath(target, source, env):
+ for t, s in zip(target, source):
+ do_generate_umath(str(t), str(s), env)
+
+def generate_umath_emitter(target, source, env):
+ t = str(target[0]) + '.c'
+ return ([t], source)
+
+#-----------------------------------------
+# Other functions related to configuration
+#-----------------------------------------
+def CheckBrokenMathlib(context, mathlib):
+ src = """
+/* check whether libm is broken */
+#include <math.h>
+int main(int argc, char *argv[])
+{
+ return exp(-720.) > 1.0; /* typically an IEEE denormal */
+}
+"""
+
+ try:
+ oldLIBS = deepcopy(context.env['LIBS'])
+ except:
+ oldLIBS = []
+
+ try:
+ context.Message("Checking if math lib %s is usable for numpy ... " % mathlib)
+ context.env.AppendUnique(LIBS = mathlib)
+ st = context.TryRun(src, '.c')
+ finally:
+ context.env['LIBS'] = oldLIBS
+
+ if st[0]:
+ context.Result(' Yes !')
+ else:
+ context.Result(' No !')
+ return st[0]
+
+def check_mlib(config, mlib):
+ """Return 1 if mlib is available and usable by numpy, 0 otherwise.
+
+ mlib can be a string (one library), or a list of libraries."""
+ # Check the libraries in mlib are linkable
+ if len(mlib) > 0:
+ # XXX: put an autoadd argument to 0 here and add an autoadd argument to
+ # CheckBroekenMathlib (otherwise we may add bogus libraries, the ones
+ # which do not path the CheckBrokenMathlib test).
+ st = config.CheckLib(mlib)
+ if not st:
+ return 0
+ # Check the mlib is usable by numpy
+ return config.CheckBrokenMathlib(mlib)
+
+def check_mlibs(config, mlibs):
+ for mlib in mlibs:
+ if check_mlib(config, mlib):
+ return mlib
+
+ # No mlib was found.
+ raise SCons.Errors.UserError("No usable mathlib was found: chose another "\
+ "one using the MATHLIB env variable, eg "\
+ "'MATHLIB=m python setup.py build'")
+
+
+def is_npy_no_signal():
+ """Return True if the NPY_NO_SIGNAL symbol must be defined in configuration
+ header."""
+ return sys.platform == 'win32'
+
+def define_no_smp():
+ """Returns True if we should define NPY_NOSMP, False otherwise."""
+ #--------------------------------
+ # Checking SMP and thread options
+ #--------------------------------
+ # Python 2.3 causes a segfault when
+ # trying to re-acquire the thread-state
+ # which is done in error-handling
+ # ufunc code. NPY_ALLOW_C_API and friends
+ # cause the segfault. So, we disable threading
+ # for now.
+ if sys.version[:5] < '2.4.2':
+ nosmp = 1
+ else:
+ # Perhaps a fancier check is in order here.
+ # so that threads are only enabled if there
+ # are actually multiple CPUS? -- but
+ # threaded code can be nice even on a single
+ # CPU so that long-calculating code doesn't
+ # block.
+ try:
+ nosmp = os.environ['NPY_NOSMP']
+ nosmp = 1
+ except KeyError:
+ nosmp = 0
+ return nosmp == 1
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index a8fd46911..869b6926f 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -18,6 +18,36 @@ FUNCTIONS_TO_CHECK = [
('rint', 'HAVE_RINT'),
]
+def is_npy_no_signal():
+ """Return True if the NPY_NO_SIGNAL symbol must be defined in configuration
+ header."""
+ return sys.platform == 'win32'
+
+def is_npy_no_smp():
+ """Return True if the NPY_NO_SMP symbol must be defined in public
+ header (when SMP support cannot be reliably enabled)."""
+ # Python 2.3 causes a segfault when
+ # trying to re-acquire the thread-state
+ # which is done in error-handling
+ # ufunc code. NPY_ALLOW_C_API and friends
+ # cause the segfault. So, we disable threading
+ # for now.
+ if sys.version[:5] < '2.4.2':
+ nosmp = 1
+ else:
+ # Perhaps a fancier check is in order here.
+ # so that threads are only enabled if there
+ # are actually multiple CPUS? -- but
+ # threaded code can be nice even on a single
+ # CPU so that long-calculating code doesn't
+ # block.
+ try:
+ nosmp = os.environ['NPY_NOSMP']
+ nosmp = 1
+ except KeyError:
+ nosmp = 0
+ return nosmp == 1
+
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration,dot_join
from numpy.distutils.system_info import get_info, default_lib_dirs
@@ -53,28 +83,7 @@ def configuration(parent_package='',top_path=None):
raise SystemError,"Failed to test configuration. "\
"See previous error messages for more information."
- # Python 2.3 causes a segfault when
- # trying to re-acquire the thread-state
- # which is done in error-handling
- # ufunc code. NPY_ALLOW_C_API and friends
- # cause the segfault. So, we disable threading
- # for now.
- if sys.version[:5] < '2.4.2':
- nosmp = 1
- else:
- # Perhaps a fancier check is in order here.
- # so that threads are only enabled if there
- # are actually multiple CPUS? -- but
- # threaded code can be nice even on a single
- # CPU so that long-calculating code doesn't
- # block.
- try:
- nosmp = os.environ['NPY_NOSMP']
- nosmp = 1
- except KeyError:
- nosmp = 0
- if nosmp: moredefs = [('NPY_ALLOW_THREADS', '0')]
- else: moredefs = []
+ moredefs = []
#
mathlibs = []
tc = testcode_mathlib()
@@ -102,8 +111,8 @@ def configuration(parent_package='',top_path=None):
if check_func(func_name):
moredefs.append(defsymbol)
- if sys.platform == 'win32':
- moredefs.append('NPY_NO_SIGNAL')
+ if is_npy_no_signal():
+ moredefs.append('__NPY_PRIVATE_NO_SIGNAL')
if sys.platform=='win32' or os.name=='nt':
from distutils.msvccompiler import get_build_architecture
@@ -123,8 +132,6 @@ def configuration(parent_package='',top_path=None):
target_f.write('#define %s\n' % (d))
else:
target_f.write('#define %s %s\n' % (d[0],d[1]))
- if not nosmp: # default is to use WITH_THREAD
- target_f.write('#ifdef WITH_THREAD\n#define NPY_ALLOW_THREADS 1\n#else\n#define NPY_ALLOW_THREADS 0\n#endif\n')
target_f.close()
print 'File:',target
target_f = open(target)
@@ -151,6 +158,39 @@ def configuration(parent_package='',top_path=None):
config.add_data_files((header_dir,target))
return target
+ def generate_numpyconfig_h(ext, build_dir):
+ """Depends on config.h: generate_config_h has to be called before !"""
+ target = join(build_dir,'numpyconfig.h')
+ if newer(__file__,target):
+ config_cmd = config.get_config_cmd()
+ log.info('Generating %s',target)
+ testcode = generate_numpyconfig_code(target)
+
+ from distutils import sysconfig
+ python_include = sysconfig.get_python_inc()
+ python_h = join(python_include, 'Python.h')
+ if not os.path.isfile(python_h):
+ raise SystemError,\
+ "Non-existing %s. Perhaps you need to install"\
+ " python-dev|python-devel." % (python_h)
+
+ config.numpy_include_dirs
+ result = config_cmd.try_run(testcode,
+ include_dirs = [python_include] + \
+ config.numpy_include_dirs,
+ library_dirs = default_lib_dirs)
+
+ if not result:
+ raise SystemError,"Failed to generate numpy configuration. "\
+ "See previous error messages for more information."
+
+ print 'File: %s' % target
+ target_f = open(target)
+ print target_f.read()
+ target_f.close()
+ print 'EOF'
+ return target
+
def generate_api_func(module_name):
def generate_api(ext, build_dir):
script = join(codegen_dir, module_name + '.py')
@@ -205,6 +245,7 @@ def configuration(parent_package='',top_path=None):
config.add_extension('multiarray',
sources = [join('src','multiarraymodule.c'),
generate_config_h,
+ generate_numpyconfig_h,
generate_array_api,
join('src','scalartypes.inc.src'),
join('src','arraytypes.inc.src'),
@@ -216,6 +257,7 @@ def configuration(parent_package='',top_path=None):
config.add_extension('umath',
sources = [generate_config_h,
+ generate_numpyconfig_h,
join('src','umathmodule.c.src'),
generate_umath_c,
generate_ufunc_api,
@@ -231,6 +273,7 @@ def configuration(parent_package='',top_path=None):
config.add_extension('_sort',
sources=[join('src','_sortmodule.c.src'),
generate_config_h,
+ generate_numpyconfig_h,
generate_array_api,
],
)
@@ -238,6 +281,7 @@ def configuration(parent_package='',top_path=None):
config.add_extension('scalarmath',
sources=[join('src','scalarmathmodule.c.src'),
generate_config_h,
+ generate_numpyconfig_h,
generate_array_api,
generate_ufunc_api],
)
@@ -342,6 +386,85 @@ int main(int argc, char **argv)
testcode = '\n'.join(testcode)
return testcode
+def generate_numpyconfig_code(target):
+ """Return the source code as a string of the code to generate the
+ numpyconfig header file."""
+ if sys.platform == 'win32':
+ target = target.replace('\\','\\\\')
+ # Config symbols to prepend
+ prepends = [('NPY_SIZEOF_SHORT', 'SIZEOF_SHORT'),
+ ('NPY_SIZEOF_INT', 'SIZEOF_INT'),
+ ('NPY_SIZEOF_LONG', 'SIZEOF_LONG'),
+ ('NPY_SIZEOF_FLOAT', 'SIZEOF_FLOAT'),
+ ('NPY_SIZEOF_DOUBLE', 'SIZEOF_DOUBLE'),
+ ('NPY_SIZEOF_LONGDOUBLE', 'SIZEOF_LONG_DOUBLE'),
+ ('NPY_SIZEOF_PY_INTPTR_T', 'SIZEOF_PY_INTPTR_T')]
+
+ testcode = ["""
+#include <Python.h>
+#include "config.h"
+
+int main()
+{
+ FILE* f;
+
+ f = fopen("%s", "w");
+ if (f == NULL) {
+ return -1;
+ }
+""" % target]
+
+ testcode.append(r"""
+ fprintf(f, "/*\n * This file is generated by %s. DO NOT EDIT \n */\n");
+""" % __file__)
+
+ # Prepend NPY_ to any SIZEOF defines
+ testcode.extend([r' fprintf(f, "#define ' + i + r' %%d \n", %s);' % j for i, j in prepends])
+
+ # Conditionally define NPY_NO_SIGNAL
+ if is_npy_no_signal():
+ testcode.append(r' fprintf(f, "\n#define NPY_NO_SIGNAL\n");')
+
+ # Define NPY_NOSMP to 1 if explicitely requested, or if we cannot
+ # support thread support reliably
+ if is_npy_no_smp():
+ testcode.append(r' fprintf(f, "#define NPY_NO_SMP 1\n");')
+ else:
+ testcode.append(r' fprintf(f, "#define NPY_NO_SMP 0\n");')
+
+ tmpcode = r"""
+ #ifdef PY_LONG_LONG
+ fprintf(f, "\n#define %s %%d \n", %s);
+ fprintf(f, "#define %s %%d \n", %s);
+ #else
+ fprintf(f, "/* PY_LONG_LONG not defined */ \n");
+ #endif"""
+ testcode.append(tmpcode % ('NPY_SIZEOF_LONGLONG', 'SIZEOF_LONG_LONG',
+ 'NPY_SIZEOF_PY_LONG_LONG', 'SIZEOF_PY_LONG_LONG'))
+
+ testcode.append(r"""
+#ifndef CHAR_BIT
+ {
+ unsigned char var = 2;
+ int i = 0;
+ while (var >= 2) {
+ var = var << 1;
+ i++;
+ }
+ fprintf(f,"#define CHAR_BIT %d\n", i+1);
+ }
+#else
+ fprintf(f, "/* #define CHAR_BIT %d */\n", CHAR_BIT);
+#endif""")
+
+ testcode.append("""
+ fclose(f);
+
+ return 0;
+}
+""")
+ return "\n".join(testcode)
+
if __name__=='__main__':
from numpy.distutils.core import setup
setup(configuration=configuration)
diff --git a/numpy/core/setupscons.py b/numpy/core/setupscons.py
new file mode 100644
index 000000000..7118b1dab
--- /dev/null
+++ b/numpy/core/setupscons.py
@@ -0,0 +1,106 @@
+import os
+import sys
+import glob
+from os.path import join, basename
+
+from numpy.distutils import log
+
+from numscons import get_scons_build_dir
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration,dot_join
+ from numpy.distutils.system_info import get_info, default_lib_dirs
+
+ config = Configuration('core',parent_package,top_path)
+ local_dir = config.local_path
+
+ header_dir = 'include/numpy' # this is relative to config.path_in_package
+
+ config.add_subpackage('code_generators')
+
+ # List of files to register to numpy.distutils
+ dot_blas_src = [join('blasdot', '_dotblas.c'),
+ join('blasdot', 'cblas.h')]
+ api_definition = [join('code_generators', 'array_api_order.txt'),
+ join('code_generators', 'multiarray_api_order.txt'),
+ join('code_generators', 'ufunc_api_order.txt')]
+ core_src = [join('src', basename(i)) for i in glob.glob(join(local_dir,
+ 'src',
+ '*.c'))]
+ core_src += [join('src', basename(i)) for i in glob.glob(join(local_dir,
+ 'src',
+ '*.src'))]
+
+ source_files = dot_blas_src + api_definition + core_src + \
+ [join(header_dir, 'numpyconfig.h.in')]
+
+ # Add generated files to distutils...
+ def add_config_header():
+ scons_build_dir = get_scons_build_dir()
+ # XXX: I really have to think about how to communicate path info
+ # between scons and distutils, and set the options at one single
+ # location.
+ target = join(scons_build_dir, local_dir, 'config.h')
+ incl_dir = os.path.dirname(target)
+ if incl_dir not in config.numpy_include_dirs:
+ config.numpy_include_dirs.append(incl_dir)
+
+ def add_numpyconfig_header():
+ scons_build_dir = get_scons_build_dir()
+ # XXX: I really have to think about how to communicate path info
+ # between scons and distutils, and set the options at one single
+ # location.
+ target = join(scons_build_dir, local_dir, 'numpyconfig.h')
+ incl_dir = os.path.dirname(target)
+ if incl_dir not in config.numpy_include_dirs:
+ config.numpy_include_dirs.append(incl_dir)
+ config.add_data_files((header_dir, target))
+
+ def add_array_api():
+ scons_build_dir = get_scons_build_dir()
+ # XXX: I really have to think about how to communicate path info
+ # between scons and distutils, and set the options at one single
+ # location.
+ h_file = join(scons_build_dir, local_dir, '__multiarray_api.h')
+ t_file = join(scons_build_dir, local_dir, 'multiarray_api.txt')
+ config.add_data_files((header_dir, h_file),
+ (header_dir, t_file))
+
+ def add_ufunc_api():
+ scons_build_dir = get_scons_build_dir()
+ # XXX: I really have to think about how to communicate path info
+ # between scons and distutils, and set the options at one single
+ # location.
+ h_file = join(scons_build_dir, local_dir, '__ufunc_api.h')
+ t_file = join(scons_build_dir, local_dir, 'ufunc_api.txt')
+ config.add_data_files((header_dir, h_file),
+ (header_dir, t_file))
+
+ def add_generated_files():
+ add_config_header()
+ add_numpyconfig_header()
+ add_array_api()
+ add_ufunc_api()
+ config.add_configres()
+
+ config.add_sconscript('SConstruct',
+ post_hook = add_generated_files,
+ source_files = source_files)
+
+ config.add_data_files('include/numpy/*.h')
+ config.add_include_dirs('src')
+
+ config.numpy_include_dirs.extend(config.paths('include'))
+
+ # Don't install fenv unless we need them.
+ if sys.platform == 'cygwin':
+ config.add_data_dir('include/numpy/fenv')
+
+ config.add_data_dir('tests')
+ config.make_svn_version_py()
+
+ return config
+
+if __name__=='__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/core/src/arraytypes.inc.src b/numpy/core/src/arraytypes.inc.src
index 25a149d04..dbee57c33 100644
--- a/numpy/core/src/arraytypes.inc.src
+++ b/numpy/core/src/arraytypes.inc.src
@@ -1,4 +1,5 @@
/* -*- c -*- */
+#include "config.h"
static longlong
MyPyLong_AsLongLong(PyObject *vv)
diff --git a/numpy/core/src/multiarraymodule.c b/numpy/core/src/multiarraymodule.c
index f08847449..40b287715 100644
--- a/numpy/core/src/multiarraymodule.c
+++ b/numpy/core/src/multiarraymodule.c
@@ -7269,7 +7269,7 @@ compare_chararrays(PyObject *dummy, PyObject *args, PyObject *kwds)
}
-#ifndef NPY_NO_SIGNAL
+#ifndef __NPY_PRIVATE_NO_SIGNAL
SIGJMP_BUF _NPY_SIGINT_BUF;
diff --git a/numpy/core/src/umathmodule.c.src b/numpy/core/src/umathmodule.c.src
index ec531e0e5..dfb50aba3 100644
--- a/numpy/core/src/umathmodule.c.src
+++ b/numpy/core/src/umathmodule.c.src
@@ -5,6 +5,7 @@
#define _UMATHMODULE
#include "numpy/ufuncobject.h"
#include "abstract.h"
+#include "config.h"
#include <math.h>
/* A whole slew of basic math functions are provided originally
diff --git a/numpy/distutils/command/build.py b/numpy/distutils/command/build.py
index 1f5c08205..2f5dc31ab 100644
--- a/numpy/distutils/command/build.py
+++ b/numpy/distutils/command/build.py
@@ -32,3 +32,9 @@ class build(old_build):
if build_scripts is None:
self.build_scripts = os.path.join(self.build_base,
'scripts' + plat_specifier)
+
+ def run(self):
+ # Make sure that scons based extensions are complete.
+ self.run_command('scons')
+
+ old_build.run(self)
diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py
index 41c8f4f02..ce42a36e0 100644
--- a/numpy/distutils/command/config.py
+++ b/numpy/distutils/command/config.py
@@ -101,6 +101,21 @@ class config(old_config):
(body, headers, include_dirs,
libraries, library_dirs, lang))
+ def check_decl(self, symbol,
+ headers=None, include_dirs=None):
+ self._check_compiler()
+ body = """
+int main()
+{
+#ifndef %s
+ (void) %s;
+#endif
+ ;
+ return 0;
+}""" % (symbol, symbol)
+
+ return self.try_compile(body, headers, include_dirs)
+
def check_func(self, func,
headers=None, include_dirs=None,
libraries=None, library_dirs=None,
diff --git a/numpy/distutils/command/scons.py b/numpy/distutils/command/scons.py
new file mode 100644
index 000000000..43fe8178f
--- /dev/null
+++ b/numpy/distutils/command/scons.py
@@ -0,0 +1,335 @@
+import os
+import os.path
+from os.path import join as pjoin, dirname as pdirname
+
+from distutils.errors import DistutilsPlatformError
+from distutils.errors import DistutilsExecError, DistutilsSetupError
+
+from numpy.distutils.command.build_ext import build_ext as old_build_ext
+from numpy.distutils.ccompiler import CCompiler
+from numpy.distutils.fcompiler import FCompiler
+from numpy.distutils.exec_command import find_executable
+from numpy.distutils import log
+from numpy.distutils.misc_util import get_numpy_include_dirs
+
+def get_scons_build_dir():
+ """Return the top path where everything produced by scons will be put.
+
+ The path is relative to the top setup.py"""
+ from numscons import get_scons_build_dir
+ return get_scons_build_dir()
+
+def get_scons_configres_dir():
+ """Return the top path where everything produced by scons will be put.
+
+ The path is relative to the top setup.py"""
+ from numscons import get_scons_configres_dir
+ return get_scons_configres_dir()
+
+def get_scons_configres_filename():
+ """Return the top path where everything produced by scons will be put.
+
+ The path is relative to the top setup.py"""
+ from numscons import get_scons_configres_filename
+ return get_scons_configres_filename()
+
+def get_scons_local_path():
+ """This returns the full path where scons.py for scons-local is located."""
+ from numscons import get_scons_path
+ return get_scons_path()
+
+def get_python_exec_invoc():
+ """This returns the python executable from which this file is invocated."""
+ # Do we need to take into account the PYTHONPATH, in a cross platform way,
+ # that is the string returned can be executed directly on supported
+ # platforms, and the sys.path of the executed python should be the same
+ # than the caller ? This may not be necessary, since os.system is said to
+ # take into accound os.environ. This actually also works for my way of
+ # using "local python", using the alias facility of bash.
+ import sys
+ return sys.executable
+
+def dirl_to_str(dirlist):
+ """Given a list of directories, returns a string where the paths are
+ concatenated by the path separator.
+
+ example: ['foo/bar', 'bar/foo'] will return 'foo/bar:bar/foo'."""
+ return os.pathsep.join(dirlist)
+
+def dist2sconscc(compiler):
+ """This converts the name passed to distutils to scons name convention (C
+ compiler). compiler should be a CCompiler instance.
+
+ Example:
+ --compiler=intel -> intelc"""
+ compiler_type = compiler.compiler_type
+ if compiler_type == 'msvc':
+ return 'msvc'
+ elif compiler_type == 'intel':
+ return 'intelc'
+ elif compiler_type == 'mingw32':
+ return 'mingw'
+ else:
+ return compiler.compiler[0]
+
+def dist2sconsfc(compiler):
+ """This converts the name passed to distutils to scons name convention
+ (Fortran compiler). The argument should be a FCompiler instance.
+
+ Example:
+ --fcompiler=intel -> ifort on linux, ifl on windows"""
+ if compiler.compiler_type == 'intel':
+ #raise NotImplementedError('FIXME: intel fortran compiler name ?')
+ return 'ifort'
+ elif compiler.compiler_type == 'gnu':
+ return 'g77'
+ elif compiler.compiler_type == 'gnu95':
+ return 'gfortran'
+ else:
+ # XXX: Just give up for now, and use generic fortran compiler
+ return 'fortran'
+
+def dist2sconscxx(compiler):
+ """This converts the name passed to distutils to scons name convention
+ (C++ compiler). The argument should be a Compiler instance."""
+ if compiler.compiler_type == 'gnu':
+ return 'g++'
+ else:
+ return 'c++'
+ return compiler.compiler_cxx[0]
+
+def get_compiler_executable(compiler):
+ """For any give CCompiler instance, this gives us the name of C compiler
+ (the actual executable).
+
+ NOTE: does NOT work with FCompiler instances."""
+ # Geez, why does distutils has no common way to get the compiler name...
+ if compiler.compiler_type == 'msvc':
+ # this is harcoded in distutils... A bit cleaner way would be to
+ # initialize the compiler instance and then get compiler.cc, but this
+ # may be costly: we really just want a string.
+ # XXX: we need to initialize the compiler anyway, so do not use
+ # hardcoded string
+ #compiler.initialize()
+ #print compiler.cc
+ return 'cl.exe'
+ else:
+ return compiler.compiler[0]
+
+def get_f77_compiler_executable(compiler):
+ """For any give FCompiler instance, this gives us the name of F77 compiler
+ (the actual executable)."""
+ return compiler.compiler_f77[0]
+
+def get_cxxcompiler_executable(compiler):
+ """For any give CCompiler instance, this gives us the name of CXX compiler
+ (the actual executable).
+
+ NOTE: does NOT work with FCompiler instances."""
+ # Geez, why does distutils has no common way to get the compiler name...
+ if compiler.compiler_type == 'msvc':
+ # this is harcoded in distutils... A bit cleaner way would be to
+ # initialize the compiler instance and then get compiler.cc, but this
+ # may be costly: we really just want a string.
+ # XXX: we need to initialize the compiler anyway, so do not use
+ # hardcoded string
+ #compiler.initialize()
+ #print compiler.cc
+ return 'cl.exe'
+ else:
+ return compiler.compiler_cxx[0]
+
+def get_tool_path(compiler):
+ """Given a distutils.ccompiler.CCompiler class, returns the path of the
+ toolset related to C compilation."""
+ fullpath_exec = find_executable(get_compiler_executable(compiler))
+ if fullpath_exec:
+ fullpath = pdirname(fullpath_exec)
+ else:
+ raise DistutilsSetupError("Could not find compiler executable info for scons")
+ return fullpath
+
+def get_f77_tool_path(compiler):
+ """Given a distutils.ccompiler.FCompiler class, returns the path of the
+ toolset related to F77 compilation."""
+ fullpath_exec = find_executable(get_f77_compiler_executable(compiler))
+ if fullpath_exec:
+ fullpath = pdirname(fullpath_exec)
+ else:
+ raise DistutilsSetupError("Could not find F77 compiler executable "\
+ "info for scons")
+ return fullpath
+
+def get_cxx_tool_path(compiler):
+ """Given a distutils.ccompiler.CCompiler class, returns the path of the
+ toolset related to C compilation."""
+ fullpath_exec = find_executable(get_cxxcompiler_executable(compiler))
+ if fullpath_exec:
+ fullpath = pdirname(fullpath_exec)
+ else:
+ raise DistutilsSetupError("Could not find compiler executable info for scons")
+ return fullpath
+
+def protect_path(path):
+ """Convert path (given as a string) to something the shell will have no
+ problem to understand (space, etc... problems)."""
+ # XXX: to this correctly, this is totally bogus for now (does not check for
+ # already quoted path, for example).
+ return '"' + path + '"'
+
+class scons(old_build_ext):
+ # XXX: add an option to the scons command for configuration (auto/force/cache).
+ description = "Scons builder"
+ user_options = old_build_ext.user_options + \
+ [('jobs=', None,
+ "specify number of worker threads when executing scons"),
+ ('scons-tool-path=', None, 'specify additional path '\
+ '(absolute) to look for scons tools'),
+ ('silent=', None, 'specify whether scons output should be silent '\
+ '(1), super silent (2) or not (0, default)')]
+
+ def initialize_options(self):
+ old_build_ext.initialize_options(self)
+ self.jobs = None
+ self.silent = 0
+ self.scons_tool_path = ''
+ # If true, we bypass distutils to find the c compiler altogether. This
+ # is to be used in desperate cases (like incompatible visual studio
+ # version).
+ self._bypass_distutils_cc = False
+ self.scons_compiler = None
+ self.scons_compiler_path = None
+ self.scons_fcompiler = None
+
+ def finalize_options(self):
+ old_build_ext.finalize_options(self)
+ if self.distribution.has_scons_scripts():
+ self.sconscripts = self.distribution.get_scons_scripts()
+ self.pre_hooks = self.distribution.get_scons_pre_hooks()
+ self.post_hooks = self.distribution.get_scons_post_hooks()
+ self.pkg_names = self.distribution.get_scons_parent_names()
+ else:
+ self.sconscripts = []
+ self.pre_hooks = []
+ self.post_hooks = []
+ self.pkg_names = []
+
+ # Try to get the same compiler than the ones used by distutils: this is
+ # non trivial because distutils and scons have totally different
+ # conventions on this one (distutils uses PATH from user's environment,
+ # whereas scons uses standard locations). The way we do it is once we
+ # got the c compiler used, we use numpy.distutils function to get the
+ # full path, and add the path to the env['PATH'] variable in env
+ # instance (this is done in numpy.distutils.scons module).
+
+ # XXX: The logic to bypass distutils is ... not so logic.
+ compiler_type = self.compiler
+ if compiler_type == 'msvc':
+ self._bypass_distutils_cc = True
+ from numpy.distutils.ccompiler import new_compiler
+ try:
+ distutils_compiler = new_compiler(compiler=compiler_type,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force)
+ distutils_compiler.customize(self.distribution)
+ # This initialization seems necessary, sometimes, for find_executable to work...
+ if hasattr(distutils_compiler, 'initialize'):
+ distutils_compiler.initialize()
+ self.scons_compiler = dist2sconscc(distutils_compiler)
+ self.scons_compiler_path = protect_path(get_tool_path(distutils_compiler))
+ except DistutilsPlatformError, e:
+ if not self._bypass_distutils_cc:
+ raise e
+ else:
+ self.scons_compiler = compiler_type
+
+ # We do the same for the fortran compiler ...
+ fcompiler_type = self.fcompiler
+ from numpy.distutils.fcompiler import new_fcompiler
+ self.fcompiler = new_fcompiler(compiler = fcompiler_type,
+ verbose = self.verbose,
+ dry_run = self.dry_run,
+ force = self.force)
+ if self.fcompiler is not None:
+ self.fcompiler.customize(self.distribution)
+
+ # And the C++ compiler
+ cxxcompiler = new_compiler(compiler = compiler_type,
+ verbose = self.verbose,
+ dry_run = self.dry_run,
+ force = self.force)
+ if cxxcompiler is not None:
+ cxxcompiler.customize(self.distribution, need_cxx = 1)
+ cxxcompiler.customize_cmd(self)
+ self.cxxcompiler = cxxcompiler.cxx_compiler()
+ #print self.cxxcompiler.compiler_cxx[0]
+
+ def run(self):
+ if len(self.sconscripts) > 0:
+ try:
+ import numscons
+ except ImportError, e:
+ raise RuntimeError("importing numscons failed (error was %s), using " \
+ "scons within distutils is not possible without "
+ "this package " % str(e))
+ else:
+ # nothing to do, just leave it here.
+ return
+ # XXX: when a scons script is missing, scons only prints warnings, and
+ # does not return a failure (status is 0). We have to detect this from
+ # distutils (this cannot work for recursive scons builds...)
+
+ # XXX: passing everything at command line may cause some trouble where
+ # there is a size limitation ? What is the standard solution in thise
+ # case ?
+
+ scons_exec = get_python_exec_invoc()
+ scons_exec += ' ' + protect_path(pjoin(get_scons_local_path(), 'scons.py'))
+
+ for sconscript, pre_hook, post_hook, pkg_name in zip(self.sconscripts,
+ self.pre_hooks, self.post_hooks,
+ self.pkg_names):
+ if pre_hook:
+ pre_hook()
+
+ cmd = [scons_exec, "-f", sconscript, '-I.']
+ if self.jobs:
+ cmd.append(" --jobs=%d" % int(self.jobs))
+ cmd.append('scons_tool_path="%s"' % self.scons_tool_path)
+ cmd.append('src_dir="%s"' % pdirname(sconscript))
+ cmd.append('pkg_name="%s"' % pkg_name)
+ #cmd.append('distutils_libdir=%s' % protect_path(pjoin(self.build_lib,
+ # pdirname(sconscript))))
+ cmd.append('distutils_libdir=%s' % protect_path(pjoin(self.build_lib)))
+
+ if not self._bypass_distutils_cc:
+ cmd.append('cc_opt=%s' % self.scons_compiler)
+ cmd.append('cc_opt_path=%s' % self.scons_compiler_path)
+ else:
+ cmd.append('cc_opt=%s' % self.scons_compiler)
+
+
+ if self.fcompiler:
+ cmd.append('f77_opt=%s' % dist2sconsfc(self.fcompiler))
+ cmd.append('f77_opt_path=%s' % protect_path(get_f77_tool_path(self.fcompiler)))
+
+ if self.cxxcompiler:
+ cmd.append('cxx_opt=%s' % dist2sconscxx(self.cxxcompiler))
+ cmd.append('cxx_opt_path=%s' % protect_path(get_cxx_tool_path(self.cxxcompiler)))
+
+ cmd.append('include_bootstrap=%s' % dirl_to_str(get_numpy_include_dirs()))
+ if self.silent:
+ if int(self.silent) == 1:
+ cmd.append('-Q')
+ elif int(self.silent) == 2:
+ cmd.append('-s')
+ cmdstr = ' '.join(cmd)
+ log.info("Executing scons command: %s ", cmdstr)
+ st = os.system(cmdstr)
+ if st:
+ print "status is %d" % st
+ raise DistutilsExecError("Error while executing scons command "\
+ "%s (see above)" % cmdstr)
+ if post_hook:
+ post_hook()
diff --git a/numpy/distutils/core.py b/numpy/distutils/core.py
index 19e1b33a3..842f6fbc3 100644
--- a/numpy/distutils/core.py
+++ b/numpy/distutils/core.py
@@ -21,9 +21,10 @@ import distutils.core
import distutils.dist
from numpy.distutils.extension import Extension
+from numpy.distutils.numpy_distribution import NumpyDistribution
from numpy.distutils.command import config, config_compiler, \
build, build_py, build_ext, build_clib, build_src, build_scripts, \
- sdist, install_data, install_headers, install, bdist_rpm
+ sdist, install_data, install_headers, install, bdist_rpm, scons
from numpy.distutils.misc_util import get_data_files, is_sequence, is_string
numpy_cmdclass = {'build': build.build,
@@ -36,6 +37,7 @@ numpy_cmdclass = {'build': build.build,
'build_py': build_py.build_py,
'build_clib': build_clib.build_clib,
'sdist': sdist.sdist,
+ 'scons': scons.scons,
'install_data': install_data.install_data,
'install_headers': install_headers.install_headers,
'install': install.install,
@@ -95,9 +97,10 @@ def get_distribution(always=False):
# class is local to a function in setuptools.command.easy_install
if dist is not None and \
'DistributionWithoutHelpCommands' in repr(dist):
+ raise NotImplementedError("setuptools not supported yet for numpy.scons branch")
dist = None
if always and dist is None:
- dist = distutils.dist.Distribution()
+ dist = NumpyDistribution()
return dist
def _exit_interactive_session(_cache=[]):
@@ -175,6 +178,9 @@ def setup(**attr):
and 'headers' not in new_attr:
new_attr['headers'] = []
+ # Use our custom NumpyDistribution class instead of distutils' one
+ new_attr['distclass'] = NumpyDistribution
+
return old_setup(**new_attr)
def _check_append_library(libraries, item):
diff --git a/numpy/distutils/misc_util.py b/numpy/distutils/misc_util.py
index 79fdd46ec..a698ae415 100644
--- a/numpy/distutils/misc_util.py
+++ b/numpy/distutils/misc_util.py
@@ -112,11 +112,11 @@ def njoin(*path):
return minrelpath(joined)
def get_mathlibs(path=None):
- """Return the MATHLIB line from config.h
+ """Return the MATHLIB line from numpyconfig.h
"""
if path is None:
path = os.path.join(get_numpy_include_dirs()[0], 'numpy')
- config_file = os.path.join(path,'config.h')
+ config_file = os.path.join(path,'numpyconfig.h')
fid = open(config_file)
mathlibs = []
s = '#define MATHLIB'
@@ -574,7 +574,7 @@ def get_frame(level=0):
class Configuration(object):
_list_keys = ['packages', 'ext_modules', 'data_files', 'include_dirs',
- 'libraries', 'headers', 'scripts', 'py_modules']
+ 'libraries', 'headers', 'scripts', 'py_modules', 'scons_data']
_dict_keys = ['package_dir']
_extra_keys = ['name', 'version']
@@ -586,6 +586,7 @@ class Configuration(object):
top_path=None,
package_path=None,
caller_level=1,
+ setup_name='setup.py',
**attrs):
"""Construct configuration instance of a package.
@@ -674,6 +675,8 @@ class Configuration(object):
if caller_instance.options['delegate_options_to_subpackages']:
self.set_options(**caller_instance.options)
+ self.setup_name = setup_name
+
def todict(self):
"""Return configuration distionary suitable for passing
to distutils.core.setup() function.
@@ -795,7 +798,7 @@ class Configuration(object):
else:
subpackage_path = njoin([subpackage_path] + l[:-1])
subpackage_path = self.paths([subpackage_path])[0]
- setup_py = njoin(subpackage_path, 'setup.py')
+ setup_py = njoin(subpackage_path, self.setup_name)
if not self.options['ignore_setup_xxx_py']:
if not os.path.isfile(setup_py):
setup_py = njoin(subpackage_path,
@@ -1165,6 +1168,55 @@ class Configuration(object):
self.warn('distutils distribution has been initialized,'\
' it may be too late to add a library '+ name)
+ def add_sconscript(self, sconscript, subpackage_path=None,
+ standalone = False, pre_hook = None,
+ post_hook = None, source_files = None):
+ """Add a sconscript to configuration.
+
+ pre_hook and post hook should be sequences of callable, which will be
+ use before and after executing scons. """
+ if standalone:
+ parent_name = None
+ else:
+ parent_name = self.name
+
+ dist = self.get_distribution()
+ # Convert the sconscript name to a relative filename (relative from top
+ # setup.py's directory)
+ fullsconsname = self.paths(sconscript)[0]
+
+ # XXX: Think about a way to automatically register source files from
+ # scons...
+ full_source_files = []
+ if source_files:
+ full_source_files.extend([self.paths(i)[0] for i in source_files])
+
+ if dist is not None:
+ dist.scons_data.append((fullsconsname,
+ pre_hook,
+ post_hook,
+ full_source_files,
+ parent_name))
+ self.warn('distutils distribution has been initialized,'\
+ ' it may be too late to add a subpackage '+ subpackage_name)
+ # XXX: we add a fake extension, to correctly initialize some
+ # options in distutils command.
+ dist.add_extension('', sources = [])
+ else:
+ self.scons_data.append((fullsconsname,
+ pre_hook,
+ post_hook,
+ full_source_files,
+ parent_name))
+ # XXX: we add a fake extension, to correctly initialize some
+ # options in distutils command.
+ self.add_extension('', sources = [])
+
+ def add_configres(self):
+ from numscons import get_scons_configres_dir, get_scons_configres_filename
+ file = os.path.join(get_scons_configres_dir(), self.local_path,
+ get_scons_configres_filename())
+
def add_scripts(self,*files):
"""Add scripts to configuration.
"""
@@ -1394,6 +1446,12 @@ class Configuration(object):
"""
self.py_modules.append((self.name,name,generate_config_py))
+ def scons_make_config_py(self, name = '__config__'):
+ """Generate package __config__.py file containing system_info
+ information used during building the package.
+ """
+ self.py_modules.append((self.name, name, scons_generate_config_py))
+
def get_info(self,*names):
"""Get resources information.
"""
@@ -1425,6 +1483,50 @@ def get_numpy_include_dirs():
# else running numpy/core/setup.py
return include_dirs
+def scons_generate_config_py(target):
+ """generate config.py file containing system_info information
+ used during building the package.
+
+ usage:
+ config['py_modules'].append((packagename, '__config__',generate_config_py))
+ """
+ from distutils.dir_util import mkpath
+ from numscons import get_scons_configres_dir, get_scons_configres_filename
+ d = {}
+ mkpath(os.path.dirname(target))
+ f = open(target, 'w')
+ f.write('# this file is generated by %s\n' % (os.path.abspath(sys.argv[0])))
+ f.write('# it contains system_info results at the time of building this package.\n')
+ f.write('__all__ = ["show"]\n\n')
+ confdir = get_scons_configres_dir()
+ confilename = get_scons_configres_filename()
+ for root, dirs, files in os.walk(confdir):
+ if files:
+ file = os.path.join(root, confilename)
+ assert root.startswith(confdir)
+ pkg_name = '.'.join(root[len(confdir)+1:].split(os.sep))
+ fid = open(file, 'r')
+ try:
+ cnt = fid.read()
+ d[pkg_name] = eval(cnt)
+ finally:
+ fid.close()
+ # d is a dictionary whose keys are package names, and values the
+ # corresponding configuration. Each configuration is itself a dictionary
+ # (lib : libinfo)
+ f.write('_config = %s\n' % d)
+ f.write(r'''
+def show():
+ for pkg, config in _config.items():
+ print "package %s configuration:" % pkg
+ for lib, libc in config.items():
+ print ' %s' % lib
+ for line in libc.split('\n'):
+ print '\t%s' % line
+ ''')
+ f.close()
+ return target
+
#########################
def default_config_dict(name = None, parent_name = None, local_path=None):
diff --git a/numpy/distutils/numpy_distribution.py b/numpy/distutils/numpy_distribution.py
new file mode 100644
index 000000000..681b8b316
--- /dev/null
+++ b/numpy/distutils/numpy_distribution.py
@@ -0,0 +1,28 @@
+# XXX: Handle setuptools ?
+from distutils.core import Distribution
+
+# This class is used because we add new files (sconscripts, and so on) with the
+# scons command
+class NumpyDistribution(Distribution):
+ def __init__(self, attrs = None):
+ # A list of (sconscripts, pre_hook, post_hook, src, parent_names)
+ self.scons_data = []
+ Distribution.__init__(self, attrs)
+
+ def has_scons_scripts(self):
+ return bool(self.scons_data)
+
+ def get_scons_scripts(self):
+ return [i[0] for i in self.scons_data]
+
+ def get_scons_pre_hooks(self):
+ return [i[1] for i in self.scons_data]
+
+ def get_scons_post_hooks(self):
+ return [i[2] for i in self.scons_data]
+
+ def get_scons_sources(self):
+ return [i[3] for i in self.scons_data]
+
+ def get_scons_parent_names(self):
+ return [i[4] for i in self.scons_data]
diff --git a/numpy/distutils/setupscons.py b/numpy/distutils/setupscons.py
new file mode 100644
index 000000000..b16225f41
--- /dev/null
+++ b/numpy/distutils/setupscons.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('distutils',parent_package,top_path)
+ config.add_subpackage('command')
+ config.add_subpackage('fcompiler')
+ config.add_data_dir('tests')
+ config.add_data_files('site.cfg')
+ config.make_config_py()
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/f2py/setupscons.py b/numpy/f2py/setupscons.py
new file mode 100755
index 000000000..1b8693df9
--- /dev/null
+++ b/numpy/f2py/setupscons.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+"""
+setup.py for installing F2PY
+
+Usage:
+ python setup.py install
+
+Copyright 2001-2005 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@cens.ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Revision: 1.32 $
+$Date: 2005/01/30 17:22:14 $
+Pearu Peterson
+"""
+
+__version__ = "$Id: setup.py,v 1.32 2005/01/30 17:22:14 pearu Exp $"
+
+import os
+import sys
+from distutils.dep_util import newer
+from numpy.distutils import log
+from numpy.distutils.core import setup
+from numpy.distutils.misc_util import Configuration
+
+from __version__ import version
+
+def configuration(parent_package='',top_path=None):
+ config = Configuration('f2py', parent_package, top_path)
+
+ config.add_subpackage('lib')
+
+ config.add_data_dir('docs')
+
+ config.add_data_files('src/fortranobject.c',
+ 'src/fortranobject.h',
+ 'f2py.1'
+ )
+
+ config.make_svn_version_py()
+
+ def generate_f2py_py(build_dir):
+ f2py_exe = 'f2py'+os.path.basename(sys.executable)[6:]
+ if f2py_exe[-4:]=='.exe':
+ f2py_exe = f2py_exe[:-4] + '.py'
+ if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py':
+ f2py_exe = f2py_exe + '.py'
+ target = os.path.join(build_dir,f2py_exe)
+ if newer(__file__,target):
+ log.info('Creating %s', target)
+ f = open(target,'w')
+ f.write('''\
+#!/usr/bin/env %s
+# See http://cens.ioc.ee/projects/f2py2e/
+import os, sys
+for mode in ["g3-numpy", "2e-numeric", "2e-numarray", "2e-numpy"]:
+ try:
+ i=sys.argv.index("--"+mode)
+ del sys.argv[i]
+ break
+ except ValueError: pass
+os.environ["NO_SCIPY_IMPORT"]="f2py"
+if mode=="g3-numpy":
+ try:
+ from main import main
+ except ImportError:
+ from numpy.f2py.lib.api import main
+elif mode=="2e-numeric":
+ from f2py2e import main
+elif mode=="2e-numarray":
+ sys.argv.append("-DNUMARRAY")
+ from f2py2e import main
+elif mode=="2e-numpy":
+ from numpy.f2py import main
+else:
+ print >> sys.stderr, "Unknown mode:",`mode`
+ sys.exit(1)
+main()
+'''%(os.path.basename(sys.executable)))
+ f.close()
+ return target
+
+ config.add_scripts(generate_f2py_py)
+
+ log.info('F2PY Version %s', config.get_version())
+
+ return config
+
+if __name__ == "__main__":
+
+ config = configuration(top_path='')
+ version = config.get_version()
+ print 'F2PY Version',version
+ config = config.todict()
+
+ if sys.version[:3]>='2.3':
+ config['download_url'] = "http://cens.ioc.ee/projects/f2py2e/2.x"\
+ "/F2PY-2-latest.tar.gz"
+ config['classifiers'] = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Science/Research',
+ 'License :: OSI Approved :: NumPy License',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: C',
+ 'Programming Language :: Fortran',
+ 'Programming Language :: Python',
+ 'Topic :: Scientific/Engineering',
+ 'Topic :: Software Development :: Code Generators',
+ ]
+ setup(version=version,
+ description = "F2PY - Fortran to Python Interface Generaton",
+ author = "Pearu Peterson",
+ author_email = "pearu@cens.ioc.ee",
+ maintainer = "Pearu Peterson",
+ maintainer_email = "pearu@cens.ioc.ee",
+ license = "BSD",
+ platforms = "Unix, Windows (mingw|cygwin), Mac OSX",
+ long_description = """\
+The Fortran to Python Interface Generator, or F2PY for short, is a
+command line tool (f2py) for generating Python C/API modules for
+wrapping Fortran 77/90/95 subroutines, accessing common blocks from
+Python, and calling Python functions from Fortran (call-backs).
+Interfacing subroutines/data from Fortran 90/95 modules is supported.""",
+ url = "http://cens.ioc.ee/projects/f2py2e/",
+ keywords = ['Fortran','f2py'],
+ **config)
diff --git a/numpy/fft/SConstruct b/numpy/fft/SConstruct
new file mode 100644
index 000000000..2a53f6477
--- /dev/null
+++ b/numpy/fft/SConstruct
@@ -0,0 +1,13 @@
+# Last Change: Thu Oct 18 09:00 PM 2007 J
+# vim:syntax=python
+import __builtin__
+__builtin__.__NUMPY_SETUP__ = True
+from numpy.distutils.misc_util import get_numpy_include_dirs
+from numscons import GetNumpyEnvironment, scons_get_paths
+
+env = GetNumpyEnvironment(ARGUMENTS)
+env.Append(CPPPATH = scons_get_paths(env['include_bootstrap']))
+
+fftpack_lite = env.NumpyPythonExtension('fftpack_lite',
+ source = ['fftpack_litemodule.c',
+ 'fftpack.c'])
diff --git a/numpy/fft/setupscons.py b/numpy/fft/setupscons.py
new file mode 100644
index 000000000..2fe9509e8
--- /dev/null
+++ b/numpy/fft/setupscons.py
@@ -0,0 +1,15 @@
+def configuration(parent_package = '', top_path = None):
+ from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
+ config = Configuration('fft', parent_package, top_path)
+
+ config.add_data_dir('tests')
+
+ config.add_sconscript('SConstruct',
+ source_files = ['fftpack_litemodule.c', 'fftpack.c',
+ 'fftpack.h'])
+
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/lib/SConstruct b/numpy/lib/SConstruct
new file mode 100644
index 000000000..84795da48
--- /dev/null
+++ b/numpy/lib/SConstruct
@@ -0,0 +1,12 @@
+# Last Change: Thu Oct 18 09:00 PM 2007 J
+# vim:syntax=python
+import __builtin__
+__builtin__.__NUMPY_SETUP__ = True
+from numpy.distutils.misc_util import get_numpy_include_dirs
+from numscons import GetNumpyEnvironment, scons_get_paths
+
+env = GetNumpyEnvironment(ARGUMENTS)
+env.Append(CPPPATH = scons_get_paths(env['include_bootstrap']))
+
+_compiled_base = env.NumpyPythonExtension('_compiled_base',
+ source = ['src/_compiled_base.c'])
diff --git a/numpy/lib/setupscons.py b/numpy/lib/setupscons.py
new file mode 100644
index 000000000..ab0c304d3
--- /dev/null
+++ b/numpy/lib/setupscons.py
@@ -0,0 +1,16 @@
+from os.path import join
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+
+ config = Configuration('lib',parent_package,top_path)
+
+ config.add_sconscript('SConstruct',
+ source_files = [join('src', '_compiled_base.c')])
+ config.add_data_dir('tests')
+
+ return config
+
+if __name__=='__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/linalg/SConstruct b/numpy/linalg/SConstruct
new file mode 100644
index 000000000..24d648ef7
--- /dev/null
+++ b/numpy/linalg/SConstruct
@@ -0,0 +1,33 @@
+# Last Change: Fri Nov 16 05:00 PM 2007 J
+# vim:syntax=python
+import os.path
+
+import __builtin__
+__builtin__.__NUMPY_SETUP__ = True
+
+from numpy.distutils.misc_util import get_numpy_include_dirs, get_mathlibs
+from numscons import GetNumpyEnvironment, scons_get_paths, \
+ scons_get_mathlib
+from numscons import CheckF77LAPACK
+from numscons import write_info
+
+env = GetNumpyEnvironment(ARGUMENTS)
+env.Append(CPPPATH = scons_get_paths(env['include_bootstrap']))
+
+config = env.NumpyConfigure(custom_tests =
+ {'CheckLAPACK' : CheckF77LAPACK})
+
+use_lapack = config.CheckLAPACK()
+
+mlib = scons_get_mathlib(env)
+env.AppendUnique(LIBS = mlib)
+
+config.Finish()
+write_info(env)
+
+sources = ['lapack_litemodule.c']
+if not use_lapack:
+ sources.extend(['zlapack_lite.c', 'dlapack_lite.c', 'blas_lite.c',
+ 'dlamch.c', 'f2c_lite.c'])
+lapack_lite = env.NumpyPythonExtension('lapack_lite', source = sources)
+
diff --git a/numpy/linalg/setupscons.py b/numpy/linalg/setupscons.py
new file mode 100644
index 000000000..d585bcaae
--- /dev/null
+++ b/numpy/linalg/setupscons.py
@@ -0,0 +1,20 @@
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ from numpy.distutils.system_info import get_info
+ config = Configuration('linalg',parent_package,top_path)
+
+ config.add_data_dir('tests')
+
+ config.add_sconscript('SConstruct',
+ source_files = ['lapack_litemodule.c',
+ 'zlapack_lite.c', 'dlapack_lite.c',
+ 'blas_lite.c', 'dlamch.c',
+ 'f2c_lite.c','f2c.h'],
+ post_hook = config.add_configres)
+
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/numarray/SConstruct b/numpy/numarray/SConstruct
new file mode 100644
index 000000000..aa780be87
--- /dev/null
+++ b/numpy/numarray/SConstruct
@@ -0,0 +1,12 @@
+# Last Change: Fri Oct 19 09:00 AM 2007 J
+# vim:syntax=python
+import __builtin__
+__builtin__.__NUMPY_SETUP__ = True
+from numpy.distutils.misc_util import get_numpy_include_dirs
+from numscons import GetNumpyEnvironment, scons_get_paths
+
+env = GetNumpyEnvironment(ARGUMENTS)
+env.Append(CPPPATH = scons_get_paths(env['include_bootstrap']))
+env.Append(CPPPATH = env['src_dir'])
+
+_capi = env.NumpyPythonExtension('_capi', source = ['_capi.c'])
diff --git a/numpy/numarray/setupscons.py b/numpy/numarray/setupscons.py
new file mode 100644
index 000000000..37d53a8ef
--- /dev/null
+++ b/numpy/numarray/setupscons.py
@@ -0,0 +1,14 @@
+from os.path import join
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('numarray',parent_package,top_path)
+
+ config.add_data_files('numpy/')
+ config.add_sconscript('SConstruct', source_files = ['_capi.c'])
+
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/oldnumeric/setupscons.py b/numpy/oldnumeric/setupscons.py
new file mode 100644
index 000000000..82e8a6201
--- /dev/null
+++ b/numpy/oldnumeric/setupscons.py
@@ -0,0 +1,8 @@
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ return Configuration('oldnumeric',parent_package,top_path)
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/random/SConstruct b/numpy/random/SConstruct
new file mode 100644
index 000000000..95957ccd7
--- /dev/null
+++ b/numpy/random/SConstruct
@@ -0,0 +1,50 @@
+# Last Change: Tue Nov 13 11:00 PM 2007 J
+# vim:syntax=python
+import os
+
+import __builtin__
+__builtin__.__NUMPY_SETUP__ = True
+
+from numpy.distutils.misc_util import get_numpy_include_dirs, get_mathlibs
+from numscons import GetNumpyEnvironment, scons_get_paths, \
+ scons_get_mathlib
+
+def CheckWincrypt(context):
+ from copy import deepcopy
+ src = """\
+/* check to see if _WIN32 is defined */
+int main(int argc, char *argv[])
+{
+#ifdef _WIN32
+ return 0;
+#else
+ return 1;
+#endif
+}
+"""
+
+ context.Message("Checking if using wincrypt ... ")
+ st = context.env.TryRun(src, '.C')
+ if st[0] == 0:
+ context.Result('No')
+ else:
+ context.Result('Yes')
+ return st[0]
+
+env = GetNumpyEnvironment(ARGUMENTS)
+env.Append(CPPPATH = scons_get_paths(env['include_bootstrap']))
+
+mlib = scons_get_mathlib(env)
+env.AppendUnique(LIBS = mlib)
+
+# On windows, see if we should use Advapi32
+if os.name == 'nt':
+ config = env.NumpyConfigure(custom_tests = {'CheckWincrypt' : CheckWincrypt})
+ if config.CheckWincrypt:
+ config.env.AppendUnique(LIBS = 'Advapi32')
+
+sources = [os.path.join('mtrand', x) for x in
+ ['mtrand.c', 'randomkit.c', 'initarray.c', 'distributions.c']]
+
+# XXX: Pyrex dependency
+mtrand = env.NumpyPythonExtension('mtrand', source = sources)
diff --git a/numpy/random/setupscons.py b/numpy/random/setupscons.py
new file mode 100644
index 000000000..969300ff6
--- /dev/null
+++ b/numpy/random/setupscons.py
@@ -0,0 +1,40 @@
+import glob
+from os.path import join, split
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration, get_mathlibs
+ config = Configuration('random',parent_package,top_path)
+
+ source_files = [join('mtrand', i) for i in ['mtrand.c',
+ 'mtrand.pyx',
+ 'numpy.pxi',
+ 'randomkit.c',
+ 'randomkit.h',
+ 'Python.pxi',
+ 'initarray.c',
+ 'initarray.h',
+ 'distributions.c',
+ 'distributions.h',
+ ]]
+ config.add_sconscript('SConstruct', source_files = source_files)
+ config.add_data_files(('.', join('mtrand', 'randomkit.h')))
+ config.add_data_dir('tests')
+
+ return config
+
+def testcode_wincrypt():
+ return """\
+/* check to see if _WIN32 is defined */
+int main(int argc, char *argv[])
+{
+#ifdef _WIN32
+ return 0;
+#else
+ return 1;
+#endif
+}
+"""
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/setupscons.py b/numpy/setupscons.py
new file mode 100644
index 000000000..5c235d2ad
--- /dev/null
+++ b/numpy/setupscons.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('numpy',parent_package,top_path, setup_name = 'setupscons.py')
+ config.add_subpackage('distutils')
+ config.add_subpackage('testing')
+ config.add_subpackage('f2py')
+ config.add_subpackage('core')
+ config.add_subpackage('lib')
+ config.add_subpackage('oldnumeric')
+ config.add_subpackage('numarray')
+ config.add_subpackage('fft')
+ config.add_subpackage('linalg')
+ config.add_subpackage('random')
+ config.add_data_dir('doc')
+ config.add_data_dir('tests')
+ config.scons_make_config_py() # installs __config__.py
+ return config
+
+if __name__ == '__main__':
+ print 'This is the wrong setup.py file to run'
diff --git a/numpy/testing/setupscons.py b/numpy/testing/setupscons.py
new file mode 100755
index 000000000..ad248d27f
--- /dev/null
+++ b/numpy/testing/setupscons.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('testing',parent_package,top_path)
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(maintainer = "NumPy Developers",
+ maintainer_email = "numpy-dev@numpy.org",
+ description = "NumPy test module",
+ url = "http://www.numpy.org",
+ license = "NumPy License (BSD Style)",
+ configuration = configuration,
+ )
diff --git a/setupscons.py b/setupscons.py
new file mode 100755
index 000000000..802f4f907
--- /dev/null
+++ b/setupscons.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+"""NumPy: array processing for numbers, strings, records, and objects.
+
+NumPy is a general-purpose array-processing package designed to
+efficiently manipulate large multi-dimensional arrays of arbitrary
+records without sacrificing too much speed for small multi-dimensional
+arrays. NumPy is built on the Numeric code base and adds features
+introduced by numarray as well as an extended C-API and the ability to
+create arrays of arbitrary type which also makes NumPy suitable for
+interfacing with general-purpose data-base applications.
+
+There are also basic facilities for discrete fourier transform,
+basic linear algebra and random number generation.
+"""
+
+DOCLINES = __doc__.split("\n")
+
+import __builtin__
+import os
+import sys
+
+CLASSIFIERS = """\
+Development Status :: 4 - Beta
+Intended Audience :: Science/Research
+Intended Audience :: Developers
+License :: OSI Approved
+Programming Language :: C
+Programming Language :: Python
+Topic :: Software Development
+Topic :: Scientific/Engineering
+Operating System :: Microsoft :: Windows
+Operating System :: POSIX
+Operating System :: Unix
+Operating System :: MacOS
+"""
+
+# BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
+# update it when the contents of directories change.
+if os.path.exists('MANIFEST'): os.remove('MANIFEST')
+
+# This is a bit hackish: we are setting a global variable so that the main
+# numpy __init__ can detect if it is being loaded by the setup routine, to
+# avoid attempting to load components that aren't built yet. While ugly, it's
+# a lot more robust than what was previously being used.
+__builtin__.__NUMPY_SETUP__ = True
+
+# DO NOT REMOVE numpy.distutils IMPORT ! This is necessary for numpy.distutils'
+# monkey patching to work.
+import numpy.distutils
+from distutils.errors import DistutilsError
+try:
+ import numscons
+except ImportError, e:
+ msg = ["You cannot build numpy with scons without the numscons package "]
+ msg.append("(Failure was: %s)" % e)
+ raise DistutilsError('\n'.join(msg))
+
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+
+ config = Configuration(None, parent_package, top_path, setup_name = 'setupscons.py')
+ config.set_options(ignore_setup_xxx_py=True,
+ assume_default_configuration=True,
+ delegate_options_to_subpackages=True,
+ quiet=True)
+
+ config.add_subpackage('numpy')
+
+ config.add_data_files(('numpy','*.txt'),
+ ('numpy','COMPATIBILITY'),
+ ('numpy','site.cfg.example'),
+ ('numpy','setup.py'))
+
+ config.get_version('numpy/version.py') # sets config.version
+
+ return config
+
+def setup_package():
+
+ from numpy.distutils.core import setup
+
+ old_path = os.getcwd()
+ local_path = os.path.dirname(os.path.abspath(sys.argv[0]))
+ os.chdir(local_path)
+ sys.path.insert(0,local_path)
+
+ try:
+ setup(
+ name = 'numpy',
+ maintainer = "NumPy Developers",
+ maintainer_email = "numpy-discussion@lists.sourceforge.net",
+ description = DOCLINES[0],
+ long_description = "\n".join(DOCLINES[2:]),
+ url = "http://numeric.scipy.org",
+ download_url = "http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103",
+ license = 'BSD',
+ classifiers=filter(None, CLASSIFIERS.split('\n')),
+ author = "Travis E. Oliphant, et.al.",
+ author_email = "oliphant@ee.byu.edu",
+ platforms = ["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"],
+ configuration=configuration )
+ finally:
+ del sys.path[0]
+ os.chdir(old_path)
+ return
+
+if __name__ == '__main__':
+ setup_package()
diff --git a/test.sh b/test.sh
new file mode 100644
index 000000000..46aad9cbc
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,18 @@
+# PREFIX=$PWD
+# rm -rf $PREFIX/build
+# rm -rf $PREFIX/tmp
+# MKL=None python setupscons.py scons --jobs=4 install --prefix=$PREFIX/tmp
+# (cd $PREFIX/tmp && PYTHONPATH=$PREFIX/tmp/lib/python2.5/site-packages python -c "import numpy; print numpy; numpy.test(level = 9999); numpy.show_config()")
+
+PREFIX=$PWD
+rm -rf $PREFIX/build
+rm -rf $PREFIX/tmp
+python setupscons.py scons --jobs=4 install --prefix=$PREFIX/tmp
+(cd $PREFIX/tmp && PYTHONPATH=$PREFIX/tmp/lib/python2.5/site-packages python -c "import numpy; print numpy; numpy.test(level = 9999); numpy.show_config()")
+
+# PREFIX=$PWD
+# #rm -rf $PREFIX/build
+# #rm -rf $PREFIX/tmp
+# MKL=None python setupscons.py scons --jobs=4 --silent=2 install --prefix=$PREFIX/tmp
+# (cd $PREFIX/tmp/lib/python2.5/site-packages/numpy/distutils/scons/tests/f2pyext/ && \
+# PYTHONPATH=$PREFIX/tmp/lib/python2.5/site-packages python setup.py scons)