Skip to content

Commit 0a14016

Browse files
committed
TST: refactor testing/extbuild to use meson on-the-fly
1 parent 2e00441 commit 0a14016

File tree

3 files changed

+41
-52
lines changed

3 files changed

+41
-52
lines changed

numpy/random/tests/test_extending.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import importlib
1+
from importlib.util import spec_from_file_location, module_from_spec
22
import os
33
import pathlib
44
import pytest
@@ -60,7 +60,9 @@ def test_cython(tmp_path):
6060
# We don't want a wheel build, so do the steps in a controlled way
6161
# The meson.build file is not copied as part of the build, so generate it
6262
with open(build_dir / "meson.build", "wt", encoding="utf-8") as fid:
63-
fid.write(textwrap.dedent("""\
63+
get_inc = ('import os; os.chdir(".."); import numpy; '
64+
'print(os.path.abspath(numpy.get_include() + "../../.."))')
65+
fid.write(textwrap.dedent(f"""\
6466
project('random-build-examples', 'c', 'cpp', 'cython')
6567
6668
# https://mesonbuild.com/Python-module.html
@@ -77,10 +79,8 @@ def test_cython(tmp_path):
7779
error('tests requires Cython >= 0.29.35')
7880
endif
7981
80-
_numpy_abs = run_command(py3,
81-
['-c', 'import os; os.chdir(".."); import numpy; print(os.path.abspath(numpy.get_include() + "../../.."))'],
82-
check: true
83-
).stdout().strip()
82+
_numpy_abs = run_command(py3, ['-c', '{get_inc}'],
83+
check: true).stdout().strip()
8484
8585
npymath_path = _numpy_abs / 'core' / 'lib'
8686
npy_include_path = _numpy_abs / 'core' / 'include'
@@ -123,11 +123,11 @@ def test_cython(tmp_path):
123123
# import without adding the directory to sys.path
124124
so1 = sorted(glob.glob(str(target_dir / "extending.*")))[0]
125125
so2 = sorted(glob.glob(str(target_dir / "extending_distributions.*")))[0]
126-
spec1 = importlib.util.spec_from_file_location("extending", so1)
127-
spec2 = importlib.util.spec_from_file_location("extending_distributions", so2)
128-
extending = importlib.util.module_from_spec(spec1)
126+
spec1 = spec_from_file_location("extending", so1)
127+
spec2 = spec_from_file_location("extending_distributions", so2)
128+
extending = module_from_spec(spec1)
129129
spec1.loader.exec_module(extending)
130-
extending_distributions = importlib.util.module_from_spec(spec2)
130+
extending_distributions = module_from_spec(spec2)
131131
spec2.loader.exec_module(extending_distributions)
132132
# actually test the cython c-extension
133133
from numpy.random import PCG64

numpy/testing/_private/extbuild.py

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
import os
88
import pathlib
9+
import subprocess
910
import sys
1011
import sysconfig
12+
import textwrap
1113

1214
__all__ = ['build_and_import_extension', 'compile_extension_module']
1315

@@ -51,8 +53,6 @@ def build_and_import_extension(
5153
>>> assert not mod.test_bytes(u'abc')
5254
>>> assert mod.test_bytes(b'abc')
5355
"""
54-
from distutils.errors import CompileError
55-
5656
body = prologue + _make_methods(functions, modname)
5757
init = """PyObject *mod = PyModule_Create(&moduledef);
5858
"""
@@ -67,7 +67,7 @@ def build_and_import_extension(
6767
try:
6868
mod_so = compile_extension_module(
6969
modname, build_dir, include_dirs, source_string)
70-
except CompileError as e:
70+
except Exception as e:
7171
# shorten the exception chain
7272
raise RuntimeError(f"could not compile in {build_dir}:") from e
7373
import importlib.util
@@ -186,9 +186,9 @@ def _c_compile(cfile, outputfilename, include_dirs=[], libraries=[],
186186
elif sys.platform.startswith('linux'):
187187
compile_extra = [
188188
"-O0", "-g", "-Werror=implicit-function-declaration", "-fPIC"]
189-
link_extra = None
189+
link_extra = []
190190
else:
191-
compile_extra = link_extra = None
191+
compile_extra = link_extra = []
192192
pass
193193
if sys.platform == 'win32':
194194
link_extra = link_extra + ['/DEBUG'] # generate .pdb file
@@ -202,49 +202,37 @@ def _c_compile(cfile, outputfilename, include_dirs=[], libraries=[],
202202
library_dirs.append(s + 'lib')
203203

204204
outputfilename = outputfilename.with_suffix(get_so_suffix())
205-
saved_environ = os.environ.copy()
206-
try:
207-
build(
208-
cfile, outputfilename,
209-
compile_extra, link_extra,
210-
include_dirs, libraries, library_dirs)
211-
finally:
212-
# workaround for a distutils bugs where some env vars can
213-
# become longer and longer every time it is used
214-
for key, value in saved_environ.items():
215-
if os.environ.get(key) != value:
216-
os.environ[key] = value
205+
build(
206+
cfile, outputfilename,
207+
compile_extra, link_extra,
208+
include_dirs, libraries, library_dirs)
217209
return outputfilename
218210

219211

220212
def build(cfile, outputfilename, compile_extra, link_extra,
221213
include_dirs, libraries, library_dirs):
222-
"cd into the directory where the cfile is, use distutils to build"
223-
from numpy.distutils.ccompiler import new_compiler
224-
225-
compiler = new_compiler(force=1, verbose=2)
226-
compiler.customize('')
227-
objects = []
228-
229-
old = os.getcwd()
230-
os.chdir(cfile.parent)
231-
try:
232-
res = compiler.compile(
233-
[str(cfile.name)],
234-
include_dirs=include_dirs,
235-
extra_preargs=compile_extra
214+
"use meson to build"
215+
216+
build_dir = cfile.parent / "build"
217+
os.makedirs(build_dir, exist_ok=True)
218+
so_name = outputfilename.parts[-1]
219+
with open(cfile.parent / "meson.build", "wt") as fid:
220+
includes = ['-I' + d for d in include_dirs]
221+
link_dirs = ['-L' + d for d in library_dirs]
222+
fid.write(textwrap.dedent(f"""\
223+
project('foo', 'c')
224+
shared_module('{so_name}', '{cfile.parts[-1]}',
225+
c_args: {includes} + {compile_extra},
226+
link_args: {link_dirs} + {link_extra},
227+
link_with: {libraries},
228+
name_prefix: '',
229+
name_suffix: 'dummy',
236230
)
237-
objects += [str(cfile.parent / r) for r in res]
238-
finally:
239-
os.chdir(old)
240-
241-
compiler.link_shared_object(
242-
objects, str(outputfilename),
243-
libraries=libraries,
244-
extra_preargs=link_extra,
245-
library_dirs=library_dirs)
246-
247-
231+
"""))
232+
subprocess.check_call(["meson", "setup", "--vsenv", ".."], cwd=build_dir)
233+
subprocess.check_call(["meson", "compile"], cwd=build_dir)
234+
os.rename(str(build_dir / so_name) + ".dummy", cfile.parent / so_name)
235+
248236
def get_so_suffix():
249237
ret = sysconfig.get_config_var('EXT_SUFFIX')
250238
assert ret

test_requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ hypothesis==6.81.1
66
pytest==7.4.0
77
pytz==2023.3
88
pytest-cov==4.1.0
9+
meson
910
pytest-xdist
1011
# for numpy.random.test.test_extending
1112
cffi; python_version < '3.10'

0 commit comments

Comments
 (0)