Changqing Li | 583901a | 2020-03-04 08:22:40 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Travis Oliphant | da9c6da | 2006-01-04 17:31:07 | [diff] [blame] | 2 | """ |
Sebastian Berg | dab7572 | 2022-11-25 12:43:09 | [diff] [blame] | 3 | Numpy build options can be modified with a site.cfg file. |
hannah | 6c2fa30 | 2022-11-01 16:28:36 | [diff] [blame] | 4 | See site.cfg.example for a template and more information. |
| 5 | """ |
Pearu Peterson | c415fd1 | 2002-11-18 22:39:31 | [diff] [blame] | 6 | |
Pearu Peterson | e8fa013 | 2003-03-07 18:08:28 | [diff] [blame] | 7 | import os |
hannah | ce57eea | 2022-10-31 03:00:03 | [diff] [blame] | 8 | from pathlib import Path |
Pearu Peterson | e8fa013 | 2003-03-07 18:08:28 | [diff] [blame] | 9 | import sys |
David Cournapeau | 5623a7c | 2009-04-02 16:21:30 | [diff] [blame] | 10 | import subprocess |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 11 | import textwrap |
Hugo van Kemenade | f3a6b33 | 2020-10-04 09:09:52 | [diff] [blame] | 12 | import warnings |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 13 | import builtins |
Charles Harris | 9a37cd9 | 2021-05-25 19:35:42 | [diff] [blame] | 14 | import re |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 15 | import tempfile |
Pearu Peterson | c415fd1 | 2002-11-18 22:39:31 | [diff] [blame] | 16 | |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 17 | from distutils.errors import CompileError |
Ralf Gommers | f66d5db | 2020-12-22 20:11:50 | [diff] [blame] | 18 | |
| 19 | # Python supported version checks. Keep right after stdlib imports to ensure we |
| 20 | # get a sensible error for older Python versions |
mattip | 40a920d | 2023-01-26 06:18:20 | [diff] [blame] | 21 | if sys.version_info[:2] < (3, 9): |
| 22 | raise RuntimeError("Python version >= 3.9 required.") |
Ralf Gommers | f66d5db | 2020-12-22 20:11:50 | [diff] [blame] | 23 | |
| 24 | |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 25 | # This is a bit hackish: we are setting a global variable so that the main |
| 26 | # numpy __init__ can detect if it is being loaded by the setup routine, to |
| 27 | # avoid attempting to load components that aren't built yet. While ugly, it's |
| 28 | # a lot more robust than what was previously being used. |
| 29 | builtins.__NUMPY_SETUP__ = True |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 30 | |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 31 | # Needed for backwards code compatibility below and in some CI scripts. |
| 32 | # The version components are changed from ints to strings, but only VERSION |
| 33 | # seems to matter outside of this module and it was already a str. |
Stefan van der Walt | 7eb8cd9 | 2023-08-11 20:40:16 | [diff] [blame] | 34 | FULLVERSION = subprocess.check_output([ |
| 35 | sys.executable, |
| 36 | 'numpy/_build_utils/gitversion.py' |
| 37 | ]).strip().decode('ascii') |
| 38 | |
| 39 | # Write git version to disk |
| 40 | subprocess.check_output([ |
| 41 | sys.executable, |
| 42 | 'numpy/_build_utils/gitversion.py', '--write', 'numpy/version.py' |
| 43 | ]) |
Charles Harris | 9a37cd9 | 2021-05-25 19:35:42 | [diff] [blame] | 44 | |
| 45 | # Capture the version string: |
| 46 | # 1.22.0.dev0+ ... -> ISRELEASED == False, VERSION == 1.22.0 |
| 47 | # 1.22.0rc1+ ... -> ISRELEASED == False, VERSION == 1.22.0 |
| 48 | # 1.22.0 ... -> ISRELEASED == True, VERSION == 1.22.0 |
| 49 | # 1.22.0rc1 ... -> ISRELEASED == True, VERSION == 1.22.0 |
| 50 | ISRELEASED = re.search(r'(dev|\+)', FULLVERSION) is None |
Matthew Brett | 9db73b5 | 2021-10-23 11:05:31 | [diff] [blame] | 51 | _V_MATCH = re.match(r'(\d+)\.(\d+)\.(\d+)', FULLVERSION) |
| 52 | if _V_MATCH is None: |
| 53 | raise RuntimeError(f'Cannot parse version {FULLVERSION}') |
| 54 | MAJOR, MINOR, MICRO = _V_MATCH.groups() |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 55 | VERSION = '{}.{}.{}'.format(MAJOR, MINOR, MICRO) |
| 56 | |
Dimitri Papadopoulos Orfanos | 3cf2ca1 | 2022-10-07 19:34:47 | [diff] [blame] | 57 | # The first version not in the `Programming Language :: Python :: ...` classifiers below |
Charles Harris | f06a315 | 2022-08-17 14:36:04 | [diff] [blame] | 58 | if sys.version_info >= (3, 12): |
Charles Harris | ca11e4e | 2020-12-12 15:17:01 | [diff] [blame] | 59 | fmt = "NumPy {} may not yet support Python {}.{}." |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 60 | warnings.warn( |
Charles Harris | ca11e4e | 2020-12-12 15:17:01 | [diff] [blame] | 61 | fmt.format(VERSION, *sys.version_info[:2]), |
| 62 | RuntimeWarning) |
| 63 | del fmt |
David Cournapeau | 2b51769 | 2009-12-03 15:53:29 | [diff] [blame] | 64 | |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 65 | # BEFORE importing setuptools, remove MANIFEST. Otherwise it may not be |
| 66 | # properly updated when the contents of directories change (true for distutils, |
| 67 | # not sure about setuptools). |
| 68 | if os.path.exists('MANIFEST'): |
| 69 | os.remove('MANIFEST') |
| 70 | |
| 71 | # We need to import setuptools here in order for it to persist in sys.modules. |
Charles Harris | fed2509 | 2020-12-10 18:58:47 | [diff] [blame] | 72 | # Its presence/absence is used in subclassing setup in numpy/distutils/core.py. |
| 73 | # However, we need to run the distutils version of sdist, so import that first |
| 74 | # so that it is in sys.modules |
| 75 | import numpy.distutils.command.sdist |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 76 | import setuptools |
Charles Harris | c62e1db | 2022-01-06 23:51:20 | [diff] [blame] | 77 | if int(setuptools.__version__.split('.')[0]) >= 60: |
Andrew J. Hesford | dedc095 | 2022-02-01 15:34:26 | [diff] [blame] | 78 | # setuptools >= 60 switches to vendored distutils by default; this |
| 79 | # may break the numpy build, so make sure the stdlib version is used |
| 80 | try: |
| 81 | setuptools_use_distutils = os.environ['SETUPTOOLS_USE_DISTUTILS'] |
| 82 | except KeyError: |
| 83 | os.environ['SETUPTOOLS_USE_DISTUTILS'] = "stdlib" |
| 84 | else: |
| 85 | if setuptools_use_distutils != "stdlib": |
| 86 | raise RuntimeError("setuptools versions >= '60.0.0' require " |
| 87 | "SETUPTOOLS_USE_DISTUTILS=stdlib in the environment") |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 88 | |
Travis Oliphant | da9c6da | 2006-01-04 17:31:07 | [diff] [blame] | 89 | CLASSIFIERS = """\ |
Robert Kern | 19da971 | 2008-06-18 22:53:44 | [diff] [blame] | 90 | Development Status :: 5 - Production/Stable |
Travis Oliphant | da9c6da | 2006-01-04 17:31:07 | [diff] [blame] | 91 | Intended Audience :: Science/Research |
| 92 | Intended Audience :: Developers |
johnthagen | 5cb80d6 | 2020-10-22 12:43:03 | [diff] [blame] | 93 | License :: OSI Approved :: BSD License |
Travis Oliphant | da9c6da | 2006-01-04 17:31:07 | [diff] [blame] | 94 | Programming Language :: C |
| 95 | Programming Language :: Python |
rgommers | cdac120 | 2011-01-25 14:02:40 | [diff] [blame] | 96 | Programming Language :: Python :: 3 |
Hugo van Kemenade | 79a8e16 | 2020-10-04 11:59:53 | [diff] [blame] | 97 | Programming Language :: Python :: 3.9 |
Charles Harris | 9a176d0 | 2021-08-13 15:53:41 | [diff] [blame] | 98 | Programming Language :: Python :: 3.10 |
Charles Harris | f06a315 | 2022-08-17 14:36:04 | [diff] [blame] | 99 | Programming Language :: Python :: 3.11 |
Jon Dufresne | 334201d | 2019-08-27 04:18:35 | [diff] [blame] | 100 | Programming Language :: Python :: 3 :: Only |
Alex Willmer | 193668a | 2015-08-05 09:29:39 | [diff] [blame] | 101 | Programming Language :: Python :: Implementation :: CPython |
Travis Oliphant | da9c6da | 2006-01-04 17:31:07 | [diff] [blame] | 102 | Topic :: Software Development |
| 103 | Topic :: Scientific/Engineering |
Bas van Beek | e592c27 | 2020-10-04 13:10:42 | [diff] [blame] | 104 | Typing :: Typed |
Travis Oliphant | da9c6da | 2006-01-04 17:31:07 | [diff] [blame] | 105 | Operating System :: Microsoft :: Windows |
| 106 | Operating System :: POSIX |
| 107 | Operating System :: Unix |
| 108 | Operating System :: MacOS |
| 109 | """ |
| 110 | |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 111 | def configuration(parent_package='', top_path=None): |
Pearu Peterson | 471196b | 2006-03-31 08:59:36 | [diff] [blame] | 112 | from numpy.distutils.misc_util import Configuration |
| 113 | |
Pearu Peterson | 17d7cfe | 2006-04-04 12:26:14 | [diff] [blame] | 114 | config = Configuration(None, parent_package, top_path) |
Pearu Peterson | 471196b | 2006-03-31 08:59:36 | [diff] [blame] | 115 | config.set_options(ignore_setup_xxx_py=True, |
| 116 | assume_default_configuration=True, |
| 117 | delegate_options_to_subpackages=True, |
| 118 | quiet=True) |
Jarrod Millman | 0b77f0e | 2007-10-29 14:58:18 | [diff] [blame] | 119 | |
Pearu Peterson | 471196b | 2006-03-31 08:59:36 | [diff] [blame] | 120 | config.add_subpackage('numpy') |
Charles Harris | 054d93a | 2017-11-29 18:53:21 | [diff] [blame] | 121 | config.add_data_files(('numpy', 'LICENSE.txt')) |
scoder | e1211b8 | 2020-08-05 04:28:30 | [diff] [blame] | 122 | config.add_data_files(('numpy', 'numpy/*.pxd')) |
Jarrod Millman | 0b77f0e | 2007-10-29 14:58:18 | [diff] [blame] | 123 | |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 124 | config.get_version('numpy/version.py') # sets config.version |
Travis Oliphant | 00a3587 | 2007-05-31 04:57:01 | [diff] [blame] | 125 | |
Pearu Peterson | 471196b | 2006-03-31 08:59:36 | [diff] [blame] | 126 | return config |
| 127 | |
Ralf Gommers | 4b0ed79 | 2015-12-29 10:29:38 | [diff] [blame] | 128 | |
Julian Taylor | 4cd7274 | 2014-01-29 21:59:19 | [diff] [blame] | 129 | def check_submodules(): |
| 130 | """ verify that the submodules are checked out and clean |
| 131 | use `git submodule update --init`; on failure |
| 132 | """ |
| 133 | if not os.path.exists('.git'): |
| 134 | return |
| 135 | with open('.gitmodules') as f: |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 136 | for line in f: |
| 137 | if 'path' in line: |
| 138 | p = line.split('=')[-1].strip() |
Julian Taylor | 4cd7274 | 2014-01-29 21:59:19 | [diff] [blame] | 139 | if not os.path.exists(p): |
Wojciech Rzadkowski | dabf31c | 2020-05-22 15:43:08 | [diff] [blame] | 140 | raise ValueError('Submodule {} missing'.format(p)) |
Julian Taylor | 4cd7274 | 2014-01-29 21:59:19 | [diff] [blame] | 141 | |
Julian Taylor | 4cd7274 | 2014-01-29 21:59:19 | [diff] [blame] | 142 | proc = subprocess.Popen(['git', 'submodule', 'status'], |
| 143 | stdout=subprocess.PIPE) |
| 144 | status, _ = proc.communicate() |
| 145 | status = status.decode("ascii", "replace") |
| 146 | for line in status.splitlines(): |
| 147 | if line.startswith('-') or line.startswith('+'): |
Wojciech Rzadkowski | dabf31c | 2020-05-22 15:43:08 | [diff] [blame] | 148 | raise ValueError('Submodule not clean: {}'.format(line)) |
Julian Taylor | 4cd7274 | 2014-01-29 21:59:19 | [diff] [blame] | 149 | |
Ralf Gommers | 4b0ed79 | 2015-12-29 10:29:38 | [diff] [blame] | 150 | |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 151 | class concat_license_files(): |
Ralf Gommers | 3341590 | 2019-05-07 09:00:50 | [diff] [blame] | 152 | """Merge LICENSE.txt and LICENSES_bundled.txt for sdist creation |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 153 | |
| 154 | Done this way to keep LICENSE.txt in repo as exact BSD 3-clause (see |
| 155 | gh-13447). This makes GitHub state correctly how NumPy is licensed. |
| 156 | """ |
| 157 | def __init__(self): |
| 158 | self.f1 = 'LICENSE.txt' |
Ralf Gommers | 3341590 | 2019-05-07 09:00:50 | [diff] [blame] | 159 | self.f2 = 'LICENSES_bundled.txt' |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 160 | |
| 161 | def __enter__(self): |
Ralf Gommers | 3341590 | 2019-05-07 09:00:50 | [diff] [blame] | 162 | """Concatenate files and remove LICENSES_bundled.txt""" |
Mike Taves | 080cf82 | 2022-10-28 09:37:29 | [diff] [blame] | 163 | with open(self.f1) as f1: |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 164 | self.bsd_text = f1.read() |
| 165 | |
| 166 | with open(self.f1, 'a') as f1: |
Mike Taves | 080cf82 | 2022-10-28 09:37:29 | [diff] [blame] | 167 | with open(self.f2) as f2: |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 168 | self.bundled_text = f2.read() |
| 169 | f1.write('\n\n') |
| 170 | f1.write(self.bundled_text) |
| 171 | |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 172 | def __exit__(self, exception_type, exception_value, traceback): |
| 173 | """Restore content of both files""" |
| 174 | with open(self.f1, 'w') as f: |
| 175 | f.write(self.bsd_text) |
| 176 | |
Charles Harris | fed2509 | 2020-12-10 18:58:47 | [diff] [blame] | 177 | # Need to inherit from versioneer version of sdist to get the encoded |
| 178 | # version information. |
Stefan van der Walt | 7eb8cd9 | 2023-08-11 20:40:16 | [diff] [blame] | 179 | class sdist_checked: |
Julian Taylor | 4cd7274 | 2014-01-29 21:59:19 | [diff] [blame] | 180 | """ check submodules on sdist to prevent incomplete tarballs """ |
| 181 | def run(self): |
| 182 | check_submodules() |
Ralf Gommers | a08fb60 | 2019-05-03 14:44:23 | [diff] [blame] | 183 | with concat_license_files(): |
Charles Harris | fed2509 | 2020-12-10 18:58:47 | [diff] [blame] | 184 | super().run() |
Travis Oliphant | 14db419 | 2005-09-14 22:08:46 | [diff] [blame] | 185 | |
Ralf Gommers | 4b0ed79 | 2015-12-29 10:29:38 | [diff] [blame] | 186 | |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 187 | def get_build_overrides(): |
| 188 | """ |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 189 | Custom build commands to add std flags if required to compilation |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 190 | """ |
| 191 | from numpy.distutils.command.build_clib import build_clib |
| 192 | from numpy.distutils.command.build_ext import build_ext |
Sebastian Berg | dab7572 | 2022-11-25 12:43:09 | [diff] [blame] | 193 | from numpy._utils import _pep440 |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 194 | |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 195 | def try_compile(compiler, file, flags = [], verbose=False): |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 196 | bk_ver = getattr(compiler, 'verbose', False) |
| 197 | compiler.verbose = verbose |
| 198 | try: |
| 199 | compiler.compile([file], extra_postargs=flags) |
| 200 | return True, '' |
| 201 | except CompileError as e: |
| 202 | return False, str(e) |
| 203 | finally: |
| 204 | compiler.verbose = bk_ver |
mattip | 10dcfb0 | 2020-07-28 08:56:35 | [diff] [blame] | 205 | |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 206 | def flags_is_required(compiler, is_cpp, flags, code): |
| 207 | if is_cpp: |
| 208 | compiler = compiler.cxx_compiler() |
| 209 | suf = '.cpp' |
| 210 | else: |
| 211 | suf = '.c' |
| 212 | with tempfile.TemporaryDirectory() as temp_dir: |
| 213 | tmp_file = os.path.join(temp_dir, "test" + suf) |
| 214 | with open(tmp_file, "w+") as f: |
| 215 | f.write(code) |
| 216 | # without specify any flags in case of the required |
| 217 | # standard already supported by default, then there's |
| 218 | # no need for passing the flags |
| 219 | comp = try_compile(compiler, tmp_file) |
| 220 | if not comp[0]: |
| 221 | comp = try_compile(compiler, tmp_file, flags) |
| 222 | if not comp[0]: |
| 223 | # rerun to verbose the error |
| 224 | try_compile(compiler, tmp_file, flags, True) |
| 225 | if is_cpp: |
| 226 | raise RuntimeError( |
| 227 | "Broken toolchain during testing C++ compiler. \n" |
| 228 | "A compiler with support for C++17 language " |
| 229 | "features is required.\n" |
| 230 | f"Triggered the following error: {comp[1]}." |
| 231 | ) |
| 232 | else: |
| 233 | raise RuntimeError( |
| 234 | "Broken toolchain during testing C compiler. \n" |
| 235 | "A compiler with support for C99 language " |
| 236 | "features is required.\n" |
| 237 | f"Triggered the following error: {comp[1]}." |
| 238 | ) |
| 239 | return True |
| 240 | return False |
mattip | 10dcfb0 | 2020-07-28 08:56:35 | [diff] [blame] | 241 | |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 242 | def std_cxx_flags(cmd): |
| 243 | compiler = cmd.compiler |
| 244 | flags = getattr(compiler, '__np_cache_cpp_flags', None) |
| 245 | if flags is not None: |
| 246 | return flags |
| 247 | flags = dict( |
| 248 | msvc = ['/std:c++17'] |
| 249 | ).get(compiler.compiler_type, ['-std=c++17']) |
| 250 | # These flags are used to compile any C++ source within Numpy. |
| 251 | # They are chosen to have very few runtime dependencies. |
| 252 | extra_flags = dict( |
| 253 | # to update #def __cplusplus with enabled C++ version |
| 254 | msvc = ['/Zc:__cplusplus'] |
| 255 | ).get(compiler.compiler_type, [ |
| 256 | # The following flag is used to avoid emit any extra code |
| 257 | # from STL since extensions are build by C linker and |
| 258 | # without C++ runtime dependencies. |
| 259 | '-fno-threadsafe-statics', |
| 260 | '-D__STDC_VERSION__=0', # for compatibility with C headers |
| 261 | '-fno-exceptions', # no exception support |
| 262 | '-fno-rtti' # no runtime type information |
| 263 | ]) |
| 264 | if not flags_is_required(compiler, True, flags, textwrap.dedent(''' |
| 265 | #include <type_traits> |
| 266 | template<typename ...T> |
| 267 | constexpr bool test_fold = (... && std::is_const_v<T>); |
| 268 | int main() |
| 269 | { |
Sayed Adel | bcc9c51 | 2023-04-24 09:24:03 | [diff] [blame] | 270 | if (test_fold<int, const int>) { |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 271 | return 0; |
| 272 | } |
| 273 | else { |
| 274 | return -1; |
| 275 | } |
| 276 | } |
| 277 | ''')): |
| 278 | flags.clear() |
| 279 | flags += extra_flags |
| 280 | setattr(compiler, '__np_cache_cpp_flags', flags) |
| 281 | return flags |
| 282 | |
| 283 | def std_c_flags(cmd): |
| 284 | compiler = cmd.compiler |
| 285 | flags = getattr(compiler, '__np_cache_c_flags', None) |
| 286 | if flags is not None: |
| 287 | return flags |
| 288 | flags = dict( |
| 289 | msvc = [] |
| 290 | ).get(compiler.compiler_type, ['-std=c99']) |
| 291 | |
| 292 | if not flags_is_required(compiler, False, flags, textwrap.dedent(''' |
Andrew Nelson | c9229a3 | 2023-04-07 23:53:26 | [diff] [blame] | 293 | inline static int test_inline() { return 0; } |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 294 | int main(void) |
| 295 | { return test_inline(); } |
| 296 | ''')): |
| 297 | flags.clear() |
| 298 | |
| 299 | setattr(compiler, '__np_cache_c_flags', flags) |
| 300 | return flags |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 301 | |
| 302 | class new_build_clib(build_clib): |
| 303 | def build_a_library(self, build_info, lib_name, libraries): |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 304 | build_info['extra_cflags'] = std_c_flags(self) |
| 305 | build_info['extra_cxxflags'] = std_cxx_flags(self) |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 306 | build_clib.build_a_library(self, build_info, lib_name, libraries) |
| 307 | |
| 308 | class new_build_ext(build_ext): |
| 309 | def build_extension(self, ext): |
Sayed Adel | d183edf | 2023-03-15 19:24:04 | [diff] [blame] | 310 | ext.extra_c_compile_args += std_c_flags(self) |
| 311 | ext.extra_cxx_compile_args += std_cxx_flags(self) |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 312 | build_ext.build_extension(self, ext) |
| 313 | return new_build_clib, new_build_ext |
| 314 | |
Julian Taylor | c9fd634 | 2014-04-05 11:13:13 | [diff] [blame] | 315 | def generate_cython(): |
Charles Harris | df8d1fd | 2022-02-04 23:21:58 | [diff] [blame] | 316 | # Check Cython version |
Sebastian Berg | dab7572 | 2022-11-25 12:43:09 | [diff] [blame] | 317 | from numpy._utils import _pep440 |
Charles Harris | df8d1fd | 2022-02-04 23:21:58 | [diff] [blame] | 318 | try: |
| 319 | # try the cython in the installed python first (somewhat related to |
| 320 | # scipy/scipy#2397) |
| 321 | import Cython |
| 322 | from Cython.Compiler.Version import version as cython_version |
| 323 | except ImportError as e: |
| 324 | # The `cython` command need not point to the version installed in the |
| 325 | # Python running this script, so raise an error to avoid the chance of |
| 326 | # using the wrong version of Cython. |
| 327 | msg = 'Cython needs to be installed in Python as a module' |
| 328 | raise OSError(msg) from e |
| 329 | else: |
| 330 | # Note: keep in sync with that in pyproject.toml |
Mariusz Felisiak | 73a9e8e | 2022-05-16 11:43:33 | [diff] [blame] | 331 | # Update for Python 3.11 |
Mariusz Felisiak | c0696c5f2 | 2022-05-18 05:19:02 | [diff] [blame] | 332 | required_version = '0.29.30' |
Charles Harris | df8d1fd | 2022-02-04 23:21:58 | [diff] [blame] | 333 | |
| 334 | if _pep440.parse(cython_version) < _pep440.Version(required_version): |
| 335 | cython_path = Cython.__file__ |
| 336 | msg = 'Building NumPy requires Cython >= {}, found {} at {}' |
| 337 | msg = msg.format(required_version, cython_version, cython_path) |
| 338 | raise RuntimeError(msg) |
| 339 | |
| 340 | # Process files |
Julian Taylor | c9fd634 | 2014-04-05 11:13:13 | [diff] [blame] | 341 | cwd = os.path.abspath(os.path.dirname(__file__)) |
| 342 | print("Cythonizing sources") |
mattip | 4e6a812 | 2019-05-23 04:54:47 | [diff] [blame] | 343 | for d in ('random',): |
mattip | fa8af41 | 2019-03-20 10:39:53 | [diff] [blame] | 344 | p = subprocess.call([sys.executable, |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 345 | os.path.join(cwd, 'tools', 'cythonize.py'), |
| 346 | 'numpy/{0}'.format(d)], |
| 347 | cwd=cwd) |
mattip | fa8af41 | 2019-03-20 10:39:53 | [diff] [blame] | 348 | if p != 0: |
| 349 | raise RuntimeError("Running cythonize failed!") |
Julian Taylor | c9fd634 | 2014-04-05 11:13:13 | [diff] [blame] | 350 | |
Ralf Gommers | 4b0ed79 | 2015-12-29 10:29:38 | [diff] [blame] | 351 | |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 352 | def parse_setuppy_commands(): |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 353 | """Check the commands and respond appropriately. Disable broken commands. |
| 354 | |
| 355 | Return a boolean value for whether or not to run the build or not (avoid |
| 356 | parsing Cython and template files if False). |
| 357 | """ |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 358 | args = sys.argv[1:] |
| 359 | |
| 360 | if not args: |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 361 | # User forgot to give an argument probably, let setuptools handle that. |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 362 | return True |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 363 | |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 364 | info_commands = ['--help-commands', '--name', '--version', '-V', |
| 365 | '--fullname', '--author', '--author-email', |
| 366 | '--maintainer', '--maintainer-email', '--contact', |
| 367 | '--contact-email', '--url', '--license', '--description', |
| 368 | '--long-description', '--platforms', '--classifiers', |
Charles Harris | 9b3f650 | 2020-12-20 23:35:37 | [diff] [blame] | 369 | '--keywords', '--provides', '--requires', '--obsoletes', |
| 370 | 'version',] |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 371 | |
| 372 | for command in info_commands: |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 373 | if command in args: |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 374 | return False |
| 375 | |
| 376 | # Note that 'alias', 'saveopts' and 'setopt' commands also seem to work |
| 377 | # fine as they are, but are usually used together with one of the commands |
| 378 | # below and not standalone. Hence they're not added to good_commands. |
| 379 | good_commands = ('develop', 'sdist', 'build', 'build_ext', 'build_py', |
Ralf Gommers | ab5c6d0 | 2016-01-16 14:21:23 | [diff] [blame] | 380 | 'build_clib', 'build_scripts', 'bdist_wheel', 'bdist_rpm', |
Ralf Gommers | 491d26b | 2021-01-27 21:48:58 | [diff] [blame] | 381 | 'bdist_wininst', 'bdist_msi', 'bdist_mpkg', 'build_src', |
| 382 | 'bdist_egg') |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 383 | |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 384 | for command in good_commands: |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 385 | if command in args: |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 386 | return True |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 387 | |
Ralf Gommers | ab5c6d0 | 2016-01-16 14:21:23 | [diff] [blame] | 388 | # The following commands are supported, but we need to show more |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 389 | # useful messages to the user |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 390 | if 'install' in args: |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 391 | print(textwrap.dedent(""" |
| 392 | Note: if you need reliable uninstall behavior, then install |
| 393 | with pip instead of using `setup.py install`: |
| 394 | |
| 395 | - `pip install .` (from a git repo or downloaded source |
| 396 | release) |
Nihaal Sangha | 5ab126b | 2022-01-20 16:58:11 | [diff] [blame] | 397 | - `pip install numpy` (last NumPy release on PyPI) |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 398 | |
| 399 | """)) |
| 400 | return True |
| 401 | |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 402 | if '--help' in args or '-h' in sys.argv[1]: |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 403 | print(textwrap.dedent(""" |
Pierre de Buyl | 3f6672a | 2016-09-06 12:54:08 | [diff] [blame] | 404 | NumPy-specific help |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 405 | ------------------- |
| 406 | |
Pierre de Buyl | 3f6672a | 2016-09-06 12:54:08 | [diff] [blame] | 407 | To install NumPy from here with reliable uninstall, we recommend |
| 408 | that you use `pip install .`. To install the latest NumPy release |
Nihaal Sangha | 5ab126b | 2022-01-20 16:58:11 | [diff] [blame] | 409 | from PyPI, use `pip install numpy`. |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 410 | |
| 411 | For help with build/installation issues, please ask on the |
| 412 | numpy-discussion mailing list. If you are sure that you have run |
| 413 | into a bug, please report it at https://github.com/numpy/numpy/issues. |
| 414 | |
| 415 | Setuptools commands help |
| 416 | ------------------------ |
| 417 | """)) |
| 418 | return False |
| 419 | |
| 420 | # The following commands aren't supported. They can only be executed when |
| 421 | # the user explicitly adds a --force command-line argument. |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 422 | bad_commands = dict( |
| 423 | test=""" |
| 424 | `setup.py test` is not supported. Use one of the following |
| 425 | instead: |
| 426 | |
| 427 | - `python runtests.py` (to build and test) |
| 428 | - `python runtests.py --no-build` (to test installed numpy) |
| 429 | - `>>> numpy.test()` (run tests for installed numpy |
| 430 | from within an interpreter) |
| 431 | """, |
| 432 | upload=""" |
| 433 | `setup.py upload` is not supported, because it's insecure. |
| 434 | Instead, build what you want to upload and upload those files |
| 435 | with `twine upload -s <filenames>` instead. |
| 436 | """, |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 437 | clean=""" |
| 438 | `setup.py clean` is not supported, use one of the following instead: |
| 439 | |
| 440 | - `git clean -xdf` (cleans all files) |
| 441 | - `git clean -Xdf` (cleans all versioned files, doesn't touch |
| 442 | files that aren't checked into the git repo) |
| 443 | """, |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 444 | build_sphinx=""" |
| 445 | `setup.py build_sphinx` is not supported, use the |
| 446 | Makefile under doc/""", |
| 447 | flake8="`setup.py flake8` is not supported, use flake8 standalone", |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 448 | ) |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 449 | bad_commands['nosetests'] = bad_commands['test'] |
Luca Mussi | 69d2cc8 | 2016-04-07 11:24:49 | [diff] [blame] | 450 | for command in ('upload_docs', 'easy_install', 'bdist', 'bdist_dumb', |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 451 | 'register', 'check', 'install_data', 'install_headers', |
| 452 | 'install_lib', 'install_scripts', ): |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 453 | bad_commands[command] = "`setup.py %s` is not supported" % command |
| 454 | |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 455 | for command in bad_commands.keys(): |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 456 | if command in args: |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 457 | print(textwrap.dedent(bad_commands[command]) + |
| 458 | "\nAdd `--force` to your command to use it anyway if you " |
| 459 | "must (unsupported).\n") |
| 460 | sys.exit(1) |
| 461 | |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 462 | # Commands that do more than print info, but also don't need Cython and |
| 463 | # template parsing. |
Charles Harris | 9b3f650 | 2020-12-20 23:35:37 | [diff] [blame] | 464 | other_commands = ['egg_info', 'install_egg_info', 'rotate', 'dist_info'] |
Eric Wieser | b8b2a0e | 2018-03-12 08:29:52 | [diff] [blame] | 465 | for command in other_commands: |
| 466 | if command in args: |
| 467 | return False |
| 468 | |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 469 | # If we got here, we didn't detect what setup.py command was given |
Charles Harris | 9b3f650 | 2020-12-20 23:35:37 | [diff] [blame] | 470 | raise RuntimeError("Unrecognized setuptools command: {}".format(args)) |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 471 | |
| 472 | |
Eric Wieser | fb47ba6 | 2020-06-20 16:28:51 | [diff] [blame] | 473 | def get_docs_url(): |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 474 | if 'dev' in VERSION: |
Eric Wieser | fb47ba6 | 2020-06-20 16:28:51 | [diff] [blame] | 475 | return "https://numpy.org/devdocs" |
| 476 | else: |
Nihaal Sangha | 5ab126b | 2022-01-20 16:58:11 | [diff] [blame] | 477 | # For releases, this URL ends up on PyPI. |
Eric Wieser | fb47ba6 | 2020-06-20 16:28:51 | [diff] [blame] | 478 | # By pinning the version, users looking at old PyPI releases can get |
| 479 | # to the associated docs easily. |
| 480 | return "https://numpy.org/doc/{}.{}".format(MAJOR, MINOR) |
| 481 | |
| 482 | |
Stefan van der Walt | 7eb8cd9 | 2023-08-11 20:40:16 | [diff] [blame] | 483 | from numpy.distutils.core import numpy_cmdclass as cmdclass |
| 484 | |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 485 | def setup_package(): |
mattip | 8b26655 | 2019-07-03 22:24:42 | [diff] [blame] | 486 | src_path = os.path.dirname(os.path.abspath(__file__)) |
Pauli Virtanen | 6815943 | 2009-12-06 11:56:18 | [diff] [blame] | 487 | old_path = os.getcwd() |
| 488 | os.chdir(src_path) |
| 489 | sys.path.insert(0, src_path) |
| 490 | |
Charles Harris | f22a33b | 2018-08-22 17:57:48 | [diff] [blame] | 491 | # The f2py scripts that will be installed |
| 492 | if sys.platform == 'win32': |
| 493 | f2py_cmds = [ |
| 494 | 'f2py = numpy.f2py.f2py2e:main', |
| 495 | ] |
| 496 | else: |
| 497 | f2py_cmds = [ |
| 498 | 'f2py = numpy.f2py.f2py2e:main', |
| 499 | 'f2py%s = numpy.f2py.f2py2e:main' % sys.version_info[:1], |
| 500 | 'f2py%s.%s = numpy.f2py.f2py2e:main' % sys.version_info[:2], |
| 501 | ] |
| 502 | |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 503 | metadata = dict( |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 504 | name='numpy', |
| 505 | maintainer="NumPy Developers", |
| 506 | maintainer_email="numpy-discussion@python.org", |
hannah | 6c2fa30 | 2022-11-01 16:28:36 | [diff] [blame] | 507 | description="Fundamental package for array computing in Python", |
| 508 | long_description=Path("README.md").read_text(encoding="utf-8"), |
hannah | ce57eea | 2022-10-31 03:00:03 | [diff] [blame] | 509 | long_description_content_type="text/markdown", |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 510 | url="https://www.numpy.org", |
| 511 | author="Travis E. Oliphant et al.", |
| 512 | download_url="https://pypi.python.org/pypi/numpy", |
Jarrod Millman | 0486b6d | 2019-04-12 01:11:21 | [diff] [blame] | 513 | project_urls={ |
| 514 | "Bug Tracker": "https://github.com/numpy/numpy/issues", |
Eric Wieser | fb47ba6 | 2020-06-20 16:28:51 | [diff] [blame] | 515 | "Documentation": get_docs_url(), |
Jarrod Millman | 0486b6d | 2019-04-12 01:11:21 | [diff] [blame] | 516 | "Source Code": "https://github.com/numpy/numpy", |
| 517 | }, |
Frazer McLean | 033503c | 2022-10-28 16:53:09 | [diff] [blame] | 518 | license='BSD-3-Clause', |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 519 | classifiers=[_f for _f in CLASSIFIERS.split('\n') if _f], |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 520 | platforms=["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"], |
Charles Harris | b3b6cc0 | 2020-05-18 22:26:10 | [diff] [blame] | 521 | test_suite='pytest', |
Stefan van der Walt | 7eb8cd9 | 2023-08-11 20:40:16 | [diff] [blame] | 522 | version=VERSION, |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 523 | cmdclass=cmdclass, |
Clément Robert | e570c6f | 2023-03-14 10:24:19 | [diff] [blame] | 524 | python_requires='>=3.9', |
Nathaniel J. Smith | f46e716 | 2018-01-23 08:02:04 | [diff] [blame] | 525 | zip_safe=False, |
Charles Harris | f22a33b | 2018-08-22 17:57:48 | [diff] [blame] | 526 | entry_points={ |
Matthew Barber | df6d285 | 2021-08-31 09:23:14 | [diff] [blame] | 527 | 'console_scripts': f2py_cmds, |
| 528 | 'array_api': ['numpy = numpy.array_api'], |
bwoodsend | bac9d0e | 2022-01-06 00:55:16 | [diff] [blame] | 529 | 'pyinstaller40': ['hook-dirs = numpy:_pyinstaller_hooks_dir'], |
Charles Harris | f22a33b | 2018-08-22 17:57:48 | [diff] [blame] | 530 | }, |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 531 | ) |
| 532 | |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 533 | if "--force" in sys.argv: |
| 534 | run_build = True |
Ralf Gommers | 20c3c2a | 2017-06-20 10:09:40 | [diff] [blame] | 535 | sys.argv.remove('--force') |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 536 | else: |
| 537 | # Raise errors for unsupported commands, improve help output, etc. |
| 538 | run_build = parse_setuppy_commands() |
Ralf Gommers | b9f4809 | 2015-12-29 11:05:30 | [diff] [blame] | 539 | |
Charles Harris | 9b3f650 | 2020-12-20 23:35:37 | [diff] [blame] | 540 | if run_build: |
Mike Taves | 07bf33f | 2020-02-04 19:21:51 | [diff] [blame] | 541 | # patches distutils, even though we don't use it |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 542 | #from setuptools import setup |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 543 | from numpy.distutils.core import setup |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 544 | |
Hugo van Kemenade | 2ebb453 | 2020-10-04 09:41:47 | [diff] [blame] | 545 | if 'sdist' not in sys.argv: |
Ralf Gommers | d630d96 | 2019-09-08 05:01:41 | [diff] [blame] | 546 | # Generate Cython sources, unless we're generating an sdist |
Julian Taylor | c9fd634 | 2014-04-05 11:13:13 | [diff] [blame] | 547 | generate_cython() |
Ralf Gommers | 4b0ed79 | 2015-12-29 10:29:38 | [diff] [blame] | 548 | |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 549 | metadata['configuration'] = configuration |
mattip | 18af8e0 | 2020-01-04 20:47:47 | [diff] [blame] | 550 | # Customize extension building |
| 551 | cmdclass['build_clib'], cmdclass['build_ext'] = get_build_overrides() |
Ralf Gommers | 99e99e9 | 2015-12-29 14:24:22 | [diff] [blame] | 552 | else: |
Charles Harris | 40fd17e | 2020-12-02 20:06:51 | [diff] [blame] | 553 | #from numpy.distutils.core import setup |
Mike Taves | 07bf33f | 2020-02-04 19:21:51 | [diff] [blame] | 554 | from setuptools import setup |
Stefan van der Walt | fe31f6b | 2022-11-29 18:38:53 | [diff] [blame] | 555 | # workaround for broken --no-build-isolation with newer setuptools, |
| 556 | # see gh-21288 |
Ralf Gommers | bf148bf | 2022-11-29 11:04:04 | [diff] [blame] | 557 | metadata["packages"] = [] |
Pauli Virtanen | 6815943 | 2009-12-06 11:56:18 | [diff] [blame] | 558 | |
Pearu Peterson | e8fa013 | 2003-03-07 18:08:28 | [diff] [blame] | 559 | try: |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 560 | setup(**metadata) |
Pearu Peterson | e8fa013 | 2003-03-07 18:08:28 | [diff] [blame] | 561 | finally: |
| 562 | del sys.path[0] |
| 563 | os.chdir(old_path) |
Travis Oliphant | 14db419 | 2005-09-14 22:08:46 | [diff] [blame] | 564 | return |
Pearu Peterson | c415fd1 | 2002-11-18 22:39:31 | [diff] [blame] | 565 | |
Ralf Gommers | 17716d7 | 2013-12-06 19:45:40 | [diff] [blame] | 566 | |
Travis Oliphant | 14db419 | 2005-09-14 22:08:46 | [diff] [blame] | 567 | if __name__ == '__main__': |
Pearu Peterson | e8fa013 | 2003-03-07 18:08:28 | [diff] [blame] | 568 | setup_package() |
Ralf Gommers | bbee747 | 2016-08-21 05:23:35 | [diff] [blame] | 569 | # This may avoid problems where numpy is installed via ``*_requires`` by |
| 570 | # setuptools, the global namespace isn't reset properly, and then numpy is |
| 571 | # imported later (which will then fail to load numpy extension modules). |
| 572 | # See gh-7956 for details |
| 573 | del builtins.__NUMPY_SETUP__ |