From 72ee7fa59242f3ec8f009c3e96674cd1d6538f47 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Tue, 7 Oct 2014 11:51:50 +0200 Subject: [PATCH 01/12] Made the ndarray wrapper x64-compatible. --- boost/numpy/ndarray.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/boost/numpy/ndarray.hpp b/boost/numpy/ndarray.hpp index ee5800c..374e4dd 100644 --- a/boost/numpy/ndarray.hpp +++ b/boost/numpy/ndarray.hpp @@ -10,6 +10,8 @@ * @brief Object manager and various utilities for numpy.ndarray. */ +#include + #include #include #include @@ -87,10 +89,10 @@ class ndarray : public python::object ndarray copy() const; /// @brief Return the size of the nth dimension. - int const shape(int n) const { return get_shape()[n]; } + std::size_t const shape(int n) const { return get_shape()[n]; } /// @brief Return the stride of the nth dimension. - int const strides(int n) const { return get_strides()[n]; } + std::size_t const strides(int n) const { return get_strides()[n]; } /** * @brief Return the array's raw data pointer. From 13955ba9ae03b8ef08bb976f5f9b9d075e3cbc3c Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Tue, 7 Oct 2014 16:22:11 +0200 Subject: [PATCH 02/12] Completed Windows build support. --- .gitmodules | 4 + SConsChecks | 1 + SConscript | 230 +++++++------------------------------ SConstruct | 9 +- libs/numpy/src/SConscript | 19 +-- libs/numpy/test/SConscript | 19 ++- 6 files changed, 58 insertions(+), 224 deletions(-) create mode 100644 .gitmodules create mode 160000 SConsChecks diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1ed9635 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "SConsChecks"] + path = SConsChecks + url = https://github.com/ChrislS/SConsChecks.git + branch = master diff --git a/SConsChecks b/SConsChecks new file mode 160000 index 0000000..f25cd51 --- /dev/null +++ b/SConsChecks @@ -0,0 +1 @@ +Subproject commit f25cd518ca91150aa63b3a3ab6800618b41d9999 diff --git a/SConscript b/SConscript index 8867bdf..13894e0 100644 --- a/SConscript +++ b/SConscript @@ -6,192 +6,21 @@ # http://www.boost.org/LICENSE_1_0.txt) # Big thanks to Mike Jarvis for help with the configuration prescriptions below. +# Integration of SConsChecks for platform independent building +# by Christoph Lassner. from __future__ import print_function import os import sys import subprocess +import sysconfig from SCons.SConf import CheckContext +from SConsChecks import AddLibOptions, GetLibChecks -def setupPaths(env, prefix, include, lib): - if prefix is not None: - if include is None: - include = os.path.join(prefix, "include") - if lib is None: - lib = os.path.join(prefix, "lib") - if include: - env.PrependUnique(CPPPATH=[include]) - if lib: - env.PrependUnique(LIBPATH=[lib]) -AddMethod(Environment, setupPaths) - -def checkLibs(context, try_libs, source_file): - init_libs = context.env.get('LIBS', []) - context.env.PrependUnique(LIBS=[try_libs]) - result = context.TryLink(source_file, '.cpp') - if not result : - context.env.Replace(LIBS=init_libs) - return result -AddMethod(CheckContext, checkLibs) - -def CheckPython(context): - python_source_file = """ -#include "Python.h" -int main() -{ - Py_Initialize(); - Py_Finalize(); - return 0; -} -""" - context.Message('Checking if we can build against Python... ') - try: - import distutils.sysconfig - except ImportError: - context.Result(0) - print('Failed to import distutils.sysconfig.') - return False - context.env.AppendUnique(CPPPATH=[distutils.sysconfig.get_python_inc()]) - libDir = distutils.sysconfig.get_config_var("LIBDIR") - context.env.AppendUnique(LIBPATH=[libDir]) - libfile = distutils.sysconfig.get_config_var("LIBRARY") - import re - match = re.search("(python.*)\.(a|so|dylib)", libfile) - if match: - context.env.AppendUnique(LIBS=[match.group(1)]) - if match.group(2) == 'a': - flags = distutils.sysconfig.get_config_var('LINKFORSHARED') - if flags is not None: - context.env.AppendUnique(LINKFLAGS=flags.split()) - flags = [f for f in " ".join(distutils.sysconfig.get_config_vars("MODLIBS", "SHLIBS")).split() - if f != "-L"] - context.env.MergeFlags(" ".join(flags)) - result, output = context.TryRun(python_source_file,'.cpp') - if not result and context.env["PLATFORM"] == 'darwin': - # Sometimes we need some extra stuff on Mac OS - frameworkDir = libDir # search up the libDir tree for the proper home for frameworks - while frameworkDir and frameworkDir != "/": - frameworkDir, d2 = os.path.split(frameworkDir) - if d2 == "Python.framework": - if not "Python" in os.listdir(os.path.join(frameworkDir, d2)): - context.Result(0) - print(( - "Expected to find Python in framework directory %s, but it isn't there" - % frameworkDir)) - return False - break - context.env.AppendUnique(LINKFLAGS="-F%s" % frameworkDir) - result, output = context.TryRun(python_source_file,'.cpp') - if not result: - context.Result(0) - print("Cannot run program built with Python.") - return False - if context.env["PLATFORM"] == "darwin": - context.env["LDMODULESUFFIX"] = ".so" - context.Result(1) - return True - -def CheckNumPy(context): - numpy_source_file = """ -#include "Python.h" -#include "numpy/arrayobject.h" -#if PY_MAJOR_VERSION == 2 -static void wrap_import_array() { - import_array(); -} -#else -static void * wrap_import_array() { - import_array(); -} -#endif -void doImport() { - wrap_import_array(); -} -int main() -{ - int result = 0; - Py_Initialize(); - doImport(); - if (PyErr_Occurred()) { - result = 1; - } else { - npy_intp dims = 2; - PyObject * a = PyArray_SimpleNew(1, &dims, NPY_INT); - if (!a) result = 1; - Py_DECREF(a); - } - Py_Finalize(); - return result; -} -""" - context.Message('Checking if we can build against NumPy... ') - try: - import numpy - except ImportError: - context.Result(0) - print('Failed to import numpy.') - print('Things to try:') - print('1) Check that the command line python (with which you probably installed numpy):') - print(' ', end=' ') - sys.stdout.flush() - subprocess.call('which python',shell=True) - print(' is the same as the one used by SCons:') - print(' ',sys.executable) - print(' If not, then you probably need to reinstall numpy with %s.' % sys.executable) - print(' Alternatively, you can reinstall SCons with your preferred python.') - print('2) Check that if you open a python session from the command line,') - print(' import numpy is successful there.') - return False - context.env.Append(CPPPATH=numpy.get_include()) - result = context.checkLibs([''],numpy_source_file) - if not result: - context.Result(0) - print("Cannot build against NumPy.") - return False - result, output = context.TryRun(numpy_source_file,'.cpp') - if not result: - context.Result(0) - print("Cannot run program built with NumPy.") - return False - context.Result(1) - return True - -def CheckBoostPython(context): - bp_source_file = """ -#include "boost/python.hpp" -class Foo { public: Foo() {} }; -int main() -{ - Py_Initialize(); - boost::python::object obj; - boost::python::class_< Foo >("Foo", boost::python::init<>()); - Py_Finalize(); - return 0; -} -""" - context.Message('Checking if we can build against Boost.Python... ') - context.env.setupPaths( - prefix = GetOption("boost_prefix"), - include = GetOption("boost_include"), - lib = GetOption("boost_lib") - ) - boost_python_lib = GetOption ('boost_python_lib') - result = ( - context.checkLibs([''], bp_source_file) or - context.checkLibs([boost_python_lib], bp_source_file) or - context.checkLibs([boost_python_lib+'_mt'], bp_source_file) - ) - if not result: - context.Result(0) - print("Cannot build against Boost.Python.") - return False - result, output = context.TryRun(bp_source_file, '.cpp') - if not result: - context.Result(0) - print ("Cannot run program built against Boost.Python.") - return False - context.Result(1) - return True +_libs = ['boost.python', + 'python', + 'numpy'] +_checks = GetLibChecks(_libs) # Setup command-line options def setupOptions(): @@ -205,15 +34,18 @@ def setupOptions(): metavar="DIR", default=os.environ.get("BOOST_DIR"), help="prefix for Boost libraries; should have 'include' and 'lib' subdirectories") AddOption("--with-boost-include", dest="boost_include", type="string", nargs=1, action="store", - metavar="DIR", help="location of Boost header files") + metavar="DIR", help="location of Boost header files", default=os.environ.get("BOOST_DIR")) AddOption("--with-boost-lib", dest="boost_lib", type="string", nargs=1, action="store", - metavar="DIR", help="location of Boost libraries") + metavar="DIR", help="location of Boost libraries", default=os.path.join(os.environ.get("BOOST_DIR"), 'stage', 'lib')) AddOption("--rpath", dest="custom_rpath", type="string", action="append", help="runtime link paths to add to libraries and executables; may be passed more than once") AddOption("--boost-python-lib", dest="boost_python_lib", type="string", action="store", help="name of boost_python_lib", default='boost_python') variables = Variables() - variables.Add("CCFLAGS", default=os.environ.get("CCFLAGS", "-O2 -g"), help="compiler flags") + defaultflags = "-O2 -g" + if os.name == 'nt': + defaultflags = "/O2 /DEBUG" + variables.Add("CCFLAGS", default=os.environ.get("CCFLAGS", defaultflags), help="compiler flags") return variables def makeEnvironment(variables): @@ -227,15 +59,33 @@ def makeEnvironment(variables): custom_rpath = GetOption("custom_rpath") if custom_rpath is not None: env.AppendUnique(RPATH=custom_rpath) - boost_lib = GetOption ('boost_lib') - if boost_lib is not None: - env.PrependUnique(LIBPATH=boost_lib) + if env['CC'] == 'cl': + env.AppendUnique(CPPFLAGS=['/MD', '/EHsc']) return env def setupTargets(env, root="."): - lib = SConscript(os.path.join(root, "libs", "numpy", "src", "SConscript"), exports='env') - example = SConscript(os.path.join(root, "libs", "numpy", "example", "SConscript"), exports='env') - test = SConscript(os.path.join(root, "libs", "numpy", "test", "SConscript"), exports='env') + # Determine file extensions. + VERSION = sys.version_info.major + if os.name == 'nt': + EXT_SUFFIX = '.dll' + LIB_SUFFIX = '.lib' + PY_SUFFIX = '.pyd' + else: + EXT_SUFFIX = sysconfig.get_config_var("EXT_SUFFIX") + if VERSION == 2 and EXT_SUFFIX == 'None' or EXT_SUFFIX==None: + EXT_SUFFIX = '.so' + elif VERSION == 3 and EXT_SUFFIX == b'None' or EXT_SUFFIX==None: + EXT_SUFFIX = '.so' + LIB_SUFFIX = EXT_SUFFIX + PY_SUFFIX = EXT_SUFFIX + OBJ_SUFFIX = EXT_SUFFIX.replace ('.so', '.os') + + lib = SConscript(os.path.join(root, "libs", "numpy", "src", "SConscript"), + exports=['env', 'EXT_SUFFIX', 'LIB_SUFFIX', 'OBJ_SUFFIX']) + example = SConscript(os.path.join(root, "libs", "numpy", "example", "SConscript"), + exports='env') + test = SConscript(os.path.join(root, "libs", "numpy", "test", "SConscript"), + exports=['env', 'lib', 'EXT_SUFFIX', 'LIB_SUFFIX', 'OBJ_SUFFIX', 'PY_SUFFIX']) prefix = Dir(GetOption("prefix")).abspath install_headers = GetOption('install_headers') install_lib = GetOption('install_lib') @@ -252,6 +102,4 @@ def setupTargets(env, root="."): env.Alias("install", env.Install(os.path.join(install_headers, "boost"), os.path.join(root, "boost", "numpy.hpp"))) -checks = {"CheckPython": CheckPython, "CheckNumPy": CheckNumPy, "CheckBoostPython": CheckBoostPython} - -Return("setupOptions", "makeEnvironment", "setupTargets", "checks") +Return("setupOptions", "makeEnvironment", "setupTargets", "_checks", "_libs") diff --git a/SConstruct b/SConstruct index f80ee9c..2c66da5 100644 --- a/SConstruct +++ b/SConstruct @@ -5,7 +5,9 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -setupOptions, makeEnvironment, setupTargets, checks = SConscript("SConscript") +from SConsChecks import GetLibChecks + +setupOptions, makeEnvironment, setupTargets, checks, libnames = SConscript("SConscript") variables = setupOptions() @@ -14,8 +16,9 @@ env.AppendUnique(CPPPATH="#.") if not GetOption("help") and not GetOption("clean"): config = env.Configure(custom_tests=checks) - if not (config.CheckPython() and config.CheckNumPy() and config.CheckBoostPython()): - Exit(1) + checknames = GetLibChecks(libnames).keys() + if False in (config.__dict__[checkname]() for checkname in checknames): + Exit(1) env = config.Finish() setupTargets(env) diff --git a/libs/numpy/src/SConscript b/libs/numpy/src/SConscript index 4601a0a..ef7a093 100644 --- a/libs/numpy/src/SConscript +++ b/libs/numpy/src/SConscript @@ -7,24 +7,7 @@ import sys import os -VERSION = sys.version_info.major -import sysconfig -if os.name == 'nt': - EXT_SUFFIX = '.dll' - LIB_SUFFIX = '.lib' -else: - EXT_SUFFIX = sysconfig.get_config_var("EXT_SUFFIX") - LIB_SUFFIX = EXT_SUFFIX - -if VERSION == 2 and EXT_SUFFIX == 'None' or EXT_SUFFIX==None: - EXT_SUFFIX = '.so' -elif VERSION == 3 and EXT_SUFFIX == b'None' or EXT_SUFFIX==None: - EXT_SUFFIX = '.so' -print ('EXT:', EXT_SUFFIX) - -OBJ_SUFFIX = EXT_SUFFIX.replace ('.so', '.os') - -Import("env") +Import(['env', 'EXT_SUFFIX', 'LIB_SUFFIX', 'OBJ_SUFFIX']) LIB_BOOST_NUMPY = ('boost_numpy' + LIB_SUFFIX) mods = [g.name.replace('.cpp', '') for g in Glob("*.cpp")] diff --git a/libs/numpy/test/SConscript b/libs/numpy/test/SConscript index b2366b1..311842b 100644 --- a/libs/numpy/test/SConscript +++ b/libs/numpy/test/SConscript @@ -5,7 +5,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -Import("env") +Import(['env', 'lib', 'EXT_SUFFIX', 'LIB_SUFFIX', 'OBJ_SUFFIX', 'PY_SUFFIX']) import os import sys @@ -15,17 +15,7 @@ lib_path = os.path.abspath(os.path.join("..", "src")) test_env.Append(LIBPATH=[lib_path]) test_env.Append(RPATH=[lib_path]) test_env.Append(LINKFLAGS = ["$__RPATH"]) # workaround for SCons bug #1644t -import sys; -VERSION = sys.version_info.major -print (VERSION) - -import sysconfig -EXT_SUFFIX = sysconfig.get_config_var("EXT_SUFFIX") - -if VERSION == 2: - test_env.Append(LIBS=["boost_numpy"]) -elif VERSION == 3: - test_env.Append(LIBS=["boost_numpy"+EXT_SUFFIX.replace('.so', '')]) +test_env.AppendUnique(LIBS=lib) test = [] def RunPythonUnitTest(target, source, env): @@ -39,6 +29,11 @@ def PythonUnitTest(env, script, dependencies): for name in ("dtype", "ufunc", "templates", "ndarray", "indexing", "shapes"): mod = test_env.LoadableModule("%s_mod" % name, "%s_mod.cpp" % name, LDMODULEPREFIX="") + if os.name == 'nt': + # Move the module to have the correct name. + mod = env.Command(os.path.join('#libs', 'numpy', 'test', "%s_mod.pyd" % (name)), + mod, + Move(os.path.join('libs', 'numpy', 'test', "%s_mod.pyd" % (name)), mod[0])) test.extend(PythonUnitTest(test_env, "%s.py" % name, mod)) Return("test") From 229f28582105d0779ca7b044f341aa31f085299c Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Wed, 8 Oct 2014 18:55:10 +0200 Subject: [PATCH 03/12] * Debug symbols are built by default on Windows. * Test libraries are created in test folder independent of SConstruct file location. --- SConscript | 3 ++- libs/numpy/test/SConscript | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/SConscript b/SConscript index 13894e0..54c907d 100644 --- a/SConscript +++ b/SConscript @@ -61,6 +61,7 @@ def makeEnvironment(variables): env.AppendUnique(RPATH=custom_rpath) if env['CC'] == 'cl': env.AppendUnique(CPPFLAGS=['/MD', '/EHsc']) + env.AppendUnique(LINKFLAGS=['/DEBUG']) return env def setupTargets(env, root="."): @@ -94,7 +95,7 @@ def setupTargets(env, root="."): if not install_lib: install_lib = os.path.join(prefix, "lib") env.Alias("install", env.Install(install_lib, lib)) - for header in ("dtype.hpp", "invoke_matching.hpp", "matrix.hpp", + for header in ("dtype.hpp", "invoke_matching.hpp", "matrix.hpp", "ndarray.hpp", "numpy_object_mgr_traits.hpp", "scalars.hpp", "ufunc.hpp",): env.Alias("install", env.Install(os.path.join(install_headers, "boost", "numpy"), diff --git a/libs/numpy/test/SConscript b/libs/numpy/test/SConscript index 311842b..ef9db47 100644 --- a/libs/numpy/test/SConscript +++ b/libs/numpy/test/SConscript @@ -31,9 +31,9 @@ for name in ("dtype", "ufunc", "templates", "ndarray", "indexing", "shapes"): mod = test_env.LoadableModule("%s_mod" % name, "%s_mod.cpp" % name, LDMODULEPREFIX="") if os.name == 'nt': # Move the module to have the correct name. - mod = env.Command(os.path.join('#libs', 'numpy', 'test', "%s_mod.pyd" % (name)), + mod = env.Command(os.path.join(Dir('.').srcnode().abspath, "%s_mod.pyd" % (name)), mod, - Move(os.path.join('libs', 'numpy', 'test', "%s_mod.pyd" % (name)), mod[0])) + Move(os.path.join(Dir('.').srcnode().abspath, "%s_mod.pyd" % (name)), mod[0])) test.extend(PythonUnitTest(test_env, "%s.py" % name, mod)) Return("test") From 9765e15dcb474f7afd5897b98b2c3c355c0d8394 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Thu, 9 Oct 2014 09:42:34 +0200 Subject: [PATCH 04/12] Fixed unsigned long test error. --- libs/numpy/test/dtype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/numpy/test/dtype.py b/libs/numpy/test/dtype.py index 4dadb80..a280cc3 100644 --- a/libs/numpy/test/dtype.py +++ b/libs/numpy/test/dtype.py @@ -49,7 +49,7 @@ def testFloats(self): c = numpy.complex128 self.assertEquivalent(dtype_mod.accept_float64(f(numpy.pi)), numpy.dtype(f)) self.assertEquivalent(dtype_mod.accept_complex128(c(1+2j)), numpy.dtype(c)) - if hasattr(numpy, "longdouble"): + if hasattr(numpy, "longdouble") and hasattr(dtype_mod, "accept_longdouble"): f = numpy.longdouble c = numpy.clongdouble self.assertEquivalent(dtype_mod.accept_longdouble(f(numpy.pi)), numpy.dtype(f)) From d97ed7f5579b985f823c37682fb30e527e3d318d Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Thu, 9 Oct 2014 14:38:16 +0200 Subject: [PATCH 05/12] All tests passing on Linux. --- SConscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SConscript b/SConscript index 54c907d..41a8946 100644 --- a/SConscript +++ b/SConscript @@ -36,7 +36,7 @@ def setupOptions(): AddOption("--with-boost-include", dest="boost_include", type="string", nargs=1, action="store", metavar="DIR", help="location of Boost header files", default=os.environ.get("BOOST_DIR")) AddOption("--with-boost-lib", dest="boost_lib", type="string", nargs=1, action="store", - metavar="DIR", help="location of Boost libraries", default=os.path.join(os.environ.get("BOOST_DIR"), 'stage', 'lib')) + metavar="DIR", help="location of Boost libraries") AddOption("--rpath", dest="custom_rpath", type="string", action="append", help="runtime link paths to add to libraries and executables; may be passed more than once") AddOption("--boost-python-lib", dest="boost_python_lib", type="string", action="store", @@ -103,4 +103,4 @@ def setupTargets(env, root="."): env.Alias("install", env.Install(os.path.join(install_headers, "boost"), os.path.join(root, "boost", "numpy.hpp"))) -Return("setupOptions", "makeEnvironment", "setupTargets", "_checks", "_libs") +Return("setupOptions", "makeEnvironment", "setupTargets", "_checks", "_libs") \ No newline at end of file From b0c912025929b9a9f001c5411970fb29f8907a84 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Thu, 9 Oct 2014 14:44:16 +0200 Subject: [PATCH 06/12] Updated SConsChecks --- SConsChecks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConsChecks b/SConsChecks index f25cd51..18bc19f 160000 --- a/SConsChecks +++ b/SConsChecks @@ -1 +1 @@ -Subproject commit f25cd518ca91150aa63b3a3ab6800618b41d9999 +Subproject commit 18bc19f17ef2aa1ad03e106addfd2661ef26284d From 2e279d455ad51de6f9aaae569bb7f22c2dd10a49 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Thu, 9 Oct 2014 15:26:15 +0200 Subject: [PATCH 07/12] Included submodule initialization hint. --- README | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README b/README index b24d4ba..ac6bb86 100644 --- a/README +++ b/README @@ -26,7 +26,11 @@ Linux and CMake on Windows. Building with SCons should be as simple as running "scons" and "scons install", but you may need to use the "--with-boost*" options (see "scons --help") to specify where to find Boost. The Python that is -used by SCons will be the one built against. +used by SCons will be the one built against. Additionally, the +SConsChecks submodule must be initialized by git before building +by running + + git submodule update --init Please see libs/numpy/doc/cmakeBuild.rst for more information on building with CMake. From a681a03a510adf917902968c81580c8a4e9bdfb3 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Fri, 17 Oct 2014 15:26:41 +0200 Subject: [PATCH 08/12] * Cleaned up MSVC flags. * Resolved dtype equivalence issue in MSVC. * Adjusted return values of strides and shape as discussed. --- SConscript | 9 ++++++--- boost/numpy/ndarray.hpp | 4 ++-- libs/numpy/src/dtype.cpp | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/SConscript b/SConscript index 41a8946..0d870e1 100644 --- a/SConscript +++ b/SConscript @@ -44,7 +44,7 @@ def setupOptions(): variables = Variables() defaultflags = "-O2 -g" if os.name == 'nt': - defaultflags = "/O2 /DEBUG" + defaultflags = "/O2" variables.Add("CCFLAGS", default=os.environ.get("CCFLAGS", defaultflags), help="compiler flags") return variables @@ -60,8 +60,11 @@ def makeEnvironment(variables): if custom_rpath is not None: env.AppendUnique(RPATH=custom_rpath) if env['CC'] == 'cl': - env.AppendUnique(CPPFLAGS=['/MD', '/EHsc']) - env.AppendUnique(LINKFLAGS=['/DEBUG']) + # C++ exception handling, + # multithread-supporting, dynamically linked system libraries, + # generate debug information, + # dynamic link library. + env.AppendUnique(CPPFLAGS=['/EHsc', '/MD', '/Zi', '/LD']) return env def setupTargets(env, root="."): diff --git a/boost/numpy/ndarray.hpp b/boost/numpy/ndarray.hpp index 374e4dd..f2a951c 100644 --- a/boost/numpy/ndarray.hpp +++ b/boost/numpy/ndarray.hpp @@ -89,10 +89,10 @@ class ndarray : public python::object ndarray copy() const; /// @brief Return the size of the nth dimension. - std::size_t const shape(int n) const { return get_shape()[n]; } + std::size_t const shape(int n) const { return static_cast(get_shape()[n]); } /// @brief Return the stride of the nth dimension. - std::size_t const strides(int n) const { return get_strides()[n]; } + Py_ssize_t const strides(int n) const { return get_strides()[n]; } /** * @brief Return the array's raw data pointer. diff --git a/libs/numpy/src/dtype.cpp b/libs/numpy/src/dtype.cpp index b734b7a..58d31da 100644 --- a/libs/numpy/src/dtype.cpp +++ b/libs/numpy/src/dtype.cpp @@ -2,7 +2,9 @@ // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) - +#ifdef _MSC_VER +#include +#endif #define BOOST_NUMPY_INTERNAL #include @@ -88,10 +90,32 @@ python::detail::new_reference dtype::convert(python::object const & arg, bool al int dtype::get_itemsize() const { return reinterpret_cast(ptr())->elsize;} bool equivalent(dtype const & a, dtype const & b) { + // On Windows x64, the behaviour described on + // http://docs.scipy.org/doc/numpy/reference/c-api.array.html for + // PyArray_EquivTypes unfortunately does not extend as expected: + // "For example, on 32-bit platforms, NPY_LONG and NPY_INT are equivalent". + // This should also hold for 64-bit platforms (and does on Linux), but not + // on Windows. Implement an alternative: +#ifdef _MSC_VER + if (sizeof(long) == sizeof(int) && + // Manually take care of the type equivalence. + ((a == dtype::get_builtin() || a == dtype::get_builtin()) && + (b == dtype::get_builtin() || b == dtype::get_builtin()) || + (a == dtype::get_builtin() || a == dtype::get_builtin()) && + (b == dtype::get_builtin() || b == dtype::get_builtin()))) { + return true; + } else { + return PyArray_EquivTypes( + reinterpret_cast(a.ptr()), + reinterpret_cast(b.ptr()) + ); + } +#else return PyArray_EquivTypes( reinterpret_cast(a.ptr()), reinterpret_cast(b.ptr()) ); +#endif } namespace { @@ -153,6 +177,13 @@ void dtype::register_scalar_converters() { array_scalar_converter::declare(); array_scalar_converter::declare(); array_scalar_converter::declare(); +#ifdef _MSC_VER + // Since the npy_(u)int32 types are defined as long types and treated + // as being different from the int32 types, these converters must be declared + // explicitely. + array_scalar_converter::declare(); + array_scalar_converter::declare(); +#endif array_scalar_converter::declare(); array_scalar_converter::declare(); array_scalar_converter::declare(); From 7739fb2d74648f125b14d080ddd9080012c40b57 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Sat, 25 Oct 2014 00:37:38 +0200 Subject: [PATCH 09/12] Changes as discussed (verification on Win pending) --- SConsChecks | 2 +- boost/numpy/ndarray.hpp | 2 +- libs/numpy/src/dtype.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SConsChecks b/SConsChecks index 18bc19f..4d4ff92 160000 --- a/SConsChecks +++ b/SConsChecks @@ -1 +1 @@ -Subproject commit 18bc19f17ef2aa1ad03e106addfd2661ef26284d +Subproject commit 4d4ff92d708646f730a99077a6df1416d0c73520 diff --git a/boost/numpy/ndarray.hpp b/boost/numpy/ndarray.hpp index f2a951c..49bfe76 100644 --- a/boost/numpy/ndarray.hpp +++ b/boost/numpy/ndarray.hpp @@ -89,7 +89,7 @@ class ndarray : public python::object ndarray copy() const; /// @brief Return the size of the nth dimension. - std::size_t const shape(int n) const { return static_cast(get_shape()[n]); } + Py_ssize_t const shape(int n) const { return get_shape()[n]; } /// @brief Return the stride of the nth dimension. Py_ssize_t const strides(int n) const { return get_strides()[n]; } diff --git a/libs/numpy/src/dtype.cpp b/libs/numpy/src/dtype.cpp index 58d31da..51fc916 100644 --- a/libs/numpy/src/dtype.cpp +++ b/libs/numpy/src/dtype.cpp @@ -3,7 +3,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifdef _MSC_VER -#include +#include #endif #define BOOST_NUMPY_INTERNAL #include @@ -181,8 +181,8 @@ void dtype::register_scalar_converters() { // Since the npy_(u)int32 types are defined as long types and treated // as being different from the int32 types, these converters must be declared // explicitely. - array_scalar_converter::declare(); - array_scalar_converter::declare(); + array_scalar_converter::declare(); + array_scalar_converter::declare(); #endif array_scalar_converter::declare(); array_scalar_converter::declare(); From 915781fc8e44eb3d109b8e2adc2ff5933eb0d1ad Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Wed, 12 Nov 2014 16:08:35 +0100 Subject: [PATCH 10/12] SConscript for Windows also works with the Intel compiler. --- SConsChecks | 2 +- libs/numpy/src/SConscript | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/SConsChecks b/SConsChecks index 4d4ff92..9000598 160000 --- a/SConsChecks +++ b/SConsChecks @@ -1 +1 @@ -Subproject commit 4d4ff92d708646f730a99077a6df1416d0c73520 +Subproject commit 9000598871f7b216cd29b35e555ae1eb4a32913c diff --git a/libs/numpy/src/SConscript b/libs/numpy/src/SConscript index ef7a093..eb9f2b3 100644 --- a/libs/numpy/src/SConscript +++ b/libs/numpy/src/SConscript @@ -10,12 +10,13 @@ import os Import(['env', 'EXT_SUFFIX', 'LIB_SUFFIX', 'OBJ_SUFFIX']) LIB_BOOST_NUMPY = ('boost_numpy' + LIB_SUFFIX) -mods = [g.name.replace('.cpp', '') for g in Glob("*.cpp")] -for m in mods: - env.SharedObject (target=m+OBJ_SUFFIX, source=m+'.cpp') +sourcefiles = Glob("*.cpp") if os.name == 'nt': - lib = env.StaticLibrary(LIB_BOOST_NUMPY, source=[m+OBJ_SUFFIX for m in mods]) + lib = env.StaticLibrary(LIB_BOOST_NUMPY, source=sourcefiles) else: + mods = [g.name.replace('.cpp', '') for g in sourcefiles] + for m in mods: + env.SharedObject (target=m+OBJ_SUFFIX, source=m+'.cpp') lib = env.SharedLibrary(LIB_BOOST_NUMPY, source=[m+OBJ_SUFFIX for m in mods]) Return("lib") From 9f9efeaa752db21507b2625fc0e6df49d0e683e3 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Tue, 25 Nov 2014 11:21:00 +0100 Subject: [PATCH 11/12] Updated build system behaviour and comments for the --with-boost option. --- SConsChecks | 2 +- SConscript | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SConsChecks b/SConsChecks index 9000598..b2af1e0 160000 --- a/SConsChecks +++ b/SConsChecks @@ -1 +1 @@ -Subproject commit 9000598871f7b216cd29b35e555ae1eb4a32913c +Subproject commit b2af1e08ea4b887810184cef611572f11dbda8f7 diff --git a/SConscript b/SConscript index 0d870e1..a7cf885 100644 --- a/SConscript +++ b/SConscript @@ -32,7 +32,7 @@ def setupOptions(): metavar="DIR", help="location to install libraries (overrides --prefix for libraries)") AddOption("--with-boost", dest="boost_prefix", type="string", nargs=1, action="store", metavar="DIR", default=os.environ.get("BOOST_DIR"), - help="prefix for Boost libraries; should have 'include' and 'lib' subdirectories") + help="prefix for Boost libraries; should have 'include' and 'lib' subdirectories, 'boost' and 'stage\\lib' subdirectories on Windows") AddOption("--with-boost-include", dest="boost_include", type="string", nargs=1, action="store", metavar="DIR", help="location of Boost header files", default=os.environ.get("BOOST_DIR")) AddOption("--with-boost-lib", dest="boost_lib", type="string", nargs=1, action="store", @@ -106,4 +106,4 @@ def setupTargets(env, root="."): env.Alias("install", env.Install(os.path.join(install_headers, "boost"), os.path.join(root, "boost", "numpy.hpp"))) -Return("setupOptions", "makeEnvironment", "setupTargets", "_checks", "_libs") \ No newline at end of file +Return("setupOptions", "makeEnvironment", "setupTargets", "_checks", "_libs") From 8e563eb40a0f1b36aa2c09a560d4a8e504b55064 Mon Sep 17 00:00:00 2001 From: Christoph Lassner Date: Tue, 25 Nov 2014 11:44:29 +0100 Subject: [PATCH 12/12] Removed unnecessary defaults. --- SConscript | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SConscript b/SConscript index a7cf885..0548d7c 100644 --- a/SConscript +++ b/SConscript @@ -34,7 +34,7 @@ def setupOptions(): metavar="DIR", default=os.environ.get("BOOST_DIR"), help="prefix for Boost libraries; should have 'include' and 'lib' subdirectories, 'boost' and 'stage\\lib' subdirectories on Windows") AddOption("--with-boost-include", dest="boost_include", type="string", nargs=1, action="store", - metavar="DIR", help="location of Boost header files", default=os.environ.get("BOOST_DIR")) + metavar="DIR", help="location of Boost header files") AddOption("--with-boost-lib", dest="boost_lib", type="string", nargs=1, action="store", metavar="DIR", help="location of Boost libraries") AddOption("--rpath", dest="custom_rpath", type="string", action="append", @@ -62,9 +62,8 @@ def makeEnvironment(variables): if env['CC'] == 'cl': # C++ exception handling, # multithread-supporting, dynamically linked system libraries, - # generate debug information, - # dynamic link library. - env.AppendUnique(CPPFLAGS=['/EHsc', '/MD', '/Zi', '/LD']) + # generate debug information. + env.AppendUnique(CPPFLAGS=['/EHsc', '/MD', '/Zi']) return env def setupTargets(env, root="."):