summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson.build2
-rw-r--r--numpy/core/setup.py42
-rw-r--r--numpy/core/src/npymath/npy_math_private.h4
-rw-r--r--numpy/distutils/ccompiler_opt.py11
-rw-r--r--numpy/distutils/command/build_clib.py1
-rw-r--r--numpy/distutils/command/build_ext.py1
-rw-r--r--numpy/linalg/setup.py2
-rwxr-xr-xsetup.py138
8 files changed, 123 insertions, 78 deletions
diff --git a/meson.build b/meson.build
index c1fc1dad8..47e71efc0 100644
--- a/meson.build
+++ b/meson.build
@@ -11,7 +11,7 @@ project(
'buildtype=debugoptimized',
'b_ndebug=if-release',
'c_std=c99',
- 'cpp_std=c++14',
+ 'cpp_std=c++17',
'blas=openblas',
'lapack=openblas',
'pkgconfig.relocatable=true',
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 77561827a..680c2a5f6 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -405,7 +405,6 @@ def configuration(parent_package='',top_path=None):
exec_mod_from_location)
from numpy.distutils.system_info import (get_info, blas_opt_info,
lapack_opt_info)
- from numpy.distutils.ccompiler_opt import NPY_CXX_FLAGS
from numpy.version import release as is_released
config = Configuration('core', parent_package, top_path)
@@ -658,44 +657,6 @@ def configuration(parent_package='',top_path=None):
# but we cannot use add_installed_pkg_config here either, so we only
# update the substitution dictionary during npymath build
config_cmd = config.get_config_cmd()
- # Check that the toolchain works, to fail early if it doesn't
- # (avoid late errors with MATHLIB which are confusing if the
- # compiler does not work).
- for lang, test_code, note in (
- ('c', 'int main(void) { return 0;}', ''),
- ('c++', (
- 'int main(void)'
- '{ auto x = 0.0; return static_cast<int>(x); }'
- ), (
- 'note: A compiler with support for C++11 language '
- 'features is required.'
- )
- ),
- ):
- is_cpp = lang == 'c++'
- if is_cpp:
- # this a workaround to get rid of invalid c++ flags
- # without doing big changes to config.
- # c tested first, compiler should be here
- bk_c = config_cmd.compiler
- config_cmd.compiler = bk_c.cxx_compiler()
-
- # Check that Linux compiler actually support the default flags
- if hasattr(config_cmd.compiler, 'compiler'):
- config_cmd.compiler.compiler.extend(NPY_CXX_FLAGS)
- config_cmd.compiler.compiler_so.extend(NPY_CXX_FLAGS)
-
- st = config_cmd.try_link(test_code, lang=lang)
- if not st:
- # rerun the failing command in verbose mode
- config_cmd.compiler.verbose = True
- config_cmd.try_link(test_code, lang=lang)
- raise RuntimeError(
- f"Broken toolchain: cannot link a simple {lang.upper()} "
- f"program. {note}"
- )
- if is_cpp:
- config_cmd.compiler = bk_c
mlibs = check_mathlib(config_cmd)
posix_mlib = ' '.join(['-l%s' % l for l in mlibs])
@@ -1067,8 +1028,7 @@ def configuration(parent_package='',top_path=None):
common_deps,
libraries=['npymath'],
extra_objects=svml_objs,
- extra_info=extra_info,
- extra_cxx_compile_args=NPY_CXX_FLAGS)
+ extra_info=extra_info)
#######################################################################
# umath_tests module #
diff --git a/numpy/core/src/npymath/npy_math_private.h b/numpy/core/src/npymath/npy_math_private.h
index a474b3de3..20c94f98a 100644
--- a/numpy/core/src/npymath/npy_math_private.h
+++ b/numpy/core/src/npymath/npy_math_private.h
@@ -21,6 +21,7 @@
#include <Python.h>
#ifdef __cplusplus
#include <cmath>
+#include <complex>
using std::isgreater;
using std::isless;
#else
@@ -494,8 +495,9 @@ do { \
* Microsoft C defines _MSC_VER
* Intel compiler does not use MSVC complex types, but defines _MSC_VER by
* default.
+ * since c++17 msvc is no longer support them.
*/
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+#if !defined(__cplusplus) && defined(_MSC_VER) && !defined(__INTEL_COMPILER)
typedef union {
npy_cdouble npy_z;
_Dcomplex c99_z;
diff --git a/numpy/distutils/ccompiler_opt.py b/numpy/distutils/ccompiler_opt.py
index 4904dd3dd..6ba4cd816 100644
--- a/numpy/distutils/ccompiler_opt.py
+++ b/numpy/distutils/ccompiler_opt.py
@@ -16,15 +16,6 @@ import re
import subprocess
import textwrap
-# These flags are used to compile any C++ source within Numpy.
-# They are chosen to have very few runtime dependencies.
-NPY_CXX_FLAGS = [
- '-std=c++11', # Minimal standard version
- '-D__STDC_VERSION__=0', # for compatibility with C headers
- '-fno-exceptions', # no exception support
- '-fno-rtti'] # no runtime type information
-
-
class _Config:
"""An abstract class holds all configurable attributes of `CCompilerOpt`,
these class attributes can be used to change the default behavior
@@ -1000,7 +991,7 @@ class _CCompiler:
)
detect_args = (
("cc_has_debug", ".*(O0|Od|ggdb|coverage|debug:full).*", ""),
- ("cc_has_native",
+ ("cc_has_native",
".*(-march=native|-xHost|/QxHost|-mcpu=a64fx).*", ""),
# in case if the class run with -DNPY_DISABLE_OPTIMIZATION
("cc_noopt", ".*DISABLE_OPT.*", ""),
diff --git a/numpy/distutils/command/build_clib.py b/numpy/distutils/command/build_clib.py
index 45201f98f..11999dae2 100644
--- a/numpy/distutils/command/build_clib.py
+++ b/numpy/distutils/command/build_clib.py
@@ -307,6 +307,7 @@ class build_clib(old_build_clib):
# problem, msvc uses its own convention :(
c_sources += cxx_sources
cxx_sources = []
+ extra_cflags += extra_cxxflags
# filtering C dispatch-table sources when optimization is not disabled,
# otherwise treated as normal sources.
diff --git a/numpy/distutils/command/build_ext.py b/numpy/distutils/command/build_ext.py
index 6dc6b4265..d24162a42 100644
--- a/numpy/distutils/command/build_ext.py
+++ b/numpy/distutils/command/build_ext.py
@@ -407,6 +407,7 @@ class build_ext (old_build_ext):
if cxx_sources:
# Needed to compile kiva.agg._agg extension.
extra_args.append('/Zm1000')
+ extra_cflags += extra_cxxflags
# this hack works around the msvc compiler attributes
# problem, msvc uses its own convention :(
c_sources += cxx_sources
diff --git a/numpy/linalg/setup.py b/numpy/linalg/setup.py
index 1c4e1295e..6f72635ab 100644
--- a/numpy/linalg/setup.py
+++ b/numpy/linalg/setup.py
@@ -4,7 +4,6 @@ import sysconfig
def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration
- from numpy.distutils.ccompiler_opt import NPY_CXX_FLAGS
from numpy.distutils.system_info import get_info, system_info
config = Configuration('linalg', parent_package, top_path)
@@ -81,7 +80,6 @@ def configuration(parent_package='', top_path=None):
sources=['umath_linalg.cpp', get_lapack_lite_sources],
depends=['lapack_lite/f2c.h'],
extra_info=lapack_info,
- extra_cxx_compile_args=NPY_CXX_FLAGS,
libraries=['npymath'],
)
config.add_data_files('*.pyi')
diff --git a/setup.py b/setup.py
index 671df90fd..edd8c4d6d 100755
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,9 @@ import textwrap
import warnings
import builtins
import re
+import tempfile
+from distutils.errors import CompileError
# Python supported version checks. Keep right after stdlib imports to ensure we
# get a sensible error for older Python versions
@@ -184,45 +186,135 @@ class sdist_checked(cmdclass['sdist']):
def get_build_overrides():
"""
- Custom build commands to add `-std=c99` to compilation
+ Custom build commands to add std flags if required to compilation
"""
from numpy.distutils.command.build_clib import build_clib
from numpy.distutils.command.build_ext import build_ext
from numpy._utils import _pep440
- def _needs_gcc_c99_flag(obj):
- if obj.compiler.compiler_type != 'unix':
- return False
+ def try_compile(compiler, file, flags = [], verbose=False):
+ # To bypass trapping warnings by Travis CI
+ if getattr(compiler, 'compiler_type', '') == 'unix':
+ flags = ['-Werror'] + flags
+ bk_ver = getattr(compiler, 'verbose', False)
+ compiler.verbose = verbose
+ try:
+ compiler.compile([file], extra_postargs=flags)
+ return True, ''
+ except CompileError as e:
+ return False, str(e)
+ finally:
+ compiler.verbose = bk_ver
+
+ def flags_is_required(compiler, is_cpp, flags, code):
+ if is_cpp:
+ compiler = compiler.cxx_compiler()
+ suf = '.cpp'
+ else:
+ suf = '.c'
+ with tempfile.TemporaryDirectory() as temp_dir:
+ tmp_file = os.path.join(temp_dir, "test" + suf)
+ with open(tmp_file, "w+") as f:
+ f.write(code)
+ # without specify any flags in case of the required
+ # standard already supported by default, then there's
+ # no need for passing the flags
+ comp = try_compile(compiler, tmp_file)
+ if not comp[0]:
+ comp = try_compile(compiler, tmp_file, flags)
+ if not comp[0]:
+ # rerun to verbose the error
+ try_compile(compiler, tmp_file, flags, True)
+ if is_cpp:
+ raise RuntimeError(
+ "Broken toolchain during testing C++ compiler. \n"
+ "A compiler with support for C++17 language "
+ "features is required.\n"
+ f"Triggered the following error: {comp[1]}."
+ )
+ else:
+ raise RuntimeError(
+ "Broken toolchain during testing C compiler. \n"
+ "A compiler with support for C99 language "
+ "features is required.\n"
+ f"Triggered the following error: {comp[1]}."
+ )
+ return True
+ return False
- cc = obj.compiler.compiler[0]
- if "gcc" not in cc:
- return False
-
- # will print something like '4.2.1\n'
- out = subprocess.run([cc, '-dumpversion'],
- capture_output=True, text=True)
- # -std=c99 is default from this version on
- if _pep440.parse(out.stdout) >= _pep440.Version('5.0'):
- return False
- return True
+ def std_cxx_flags(cmd):
+ compiler = cmd.compiler
+ flags = getattr(compiler, '__np_cache_cpp_flags', None)
+ if flags is not None:
+ return flags
+ flags = dict(
+ msvc = ['/std:c++17']
+ ).get(compiler.compiler_type, ['-std=c++17'])
+ # These flags are used to compile any C++ source within Numpy.
+ # They are chosen to have very few runtime dependencies.
+ extra_flags = dict(
+ # to update #def __cplusplus with enabled C++ version
+ msvc = ['/Zc:__cplusplus']
+ ).get(compiler.compiler_type, [
+ # The following flag is used to avoid emit any extra code
+ # from STL since extensions are build by C linker and
+ # without C++ runtime dependencies.
+ '-fno-threadsafe-statics',
+ '-D__STDC_VERSION__=0', # for compatibility with C headers
+ '-fno-exceptions', # no exception support
+ '-fno-rtti' # no runtime type information
+ ])
+ if not flags_is_required(compiler, True, flags, textwrap.dedent('''
+ #include <type_traits>
+ template<typename ...T>
+ constexpr bool test_fold = (... && std::is_const_v<T>);
+ int main()
+ {
+ if constexpr (test_fold<int, const int>) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+ ''')):
+ flags.clear()
+ flags += extra_flags
+ setattr(compiler, '__np_cache_cpp_flags', flags)
+ return flags
+
+ def std_c_flags(cmd):
+ compiler = cmd.compiler
+ flags = getattr(compiler, '__np_cache_c_flags', None)
+ if flags is not None:
+ return flags
+ flags = dict(
+ msvc = []
+ ).get(compiler.compiler_type, ['-std=c99'])
+
+ if not flags_is_required(compiler, False, flags, textwrap.dedent('''
+ inline int test_inline() { return 0; }
+ int main(void)
+ { return test_inline(); }
+ ''')):
+ flags.clear()
+
+ setattr(compiler, '__np_cache_c_flags', flags)
+ return flags
class new_build_clib(build_clib):
def build_a_library(self, build_info, lib_name, libraries):
- from numpy.distutils.ccompiler_opt import NPY_CXX_FLAGS
- if _needs_gcc_c99_flag(self):
- build_info['extra_cflags'] = ['-std=c99']
- build_info['extra_cxxflags'] = NPY_CXX_FLAGS
+ build_info['extra_cflags'] = std_c_flags(self)
+ build_info['extra_cxxflags'] = std_cxx_flags(self)
build_clib.build_a_library(self, build_info, lib_name, libraries)
class new_build_ext(build_ext):
def build_extension(self, ext):
- if _needs_gcc_c99_flag(self):
- if '-std=c99' not in ext.extra_compile_args:
- ext.extra_compile_args.append('-std=c99')
+ ext.extra_c_compile_args += std_c_flags(self)
+ ext.extra_cxx_compile_args += std_cxx_flags(self)
build_ext.build_extension(self, ext)
return new_build_clib, new_build_ext
-
def generate_cython():
# Check Cython version
from numpy._utils import _pep440