You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some Linux distributions encourage users to install more than one python version. For example, RHEL 8 has python3.6 as "system python", but also provides python3.9 in their repository.
When building a python extension via mesons extension_module, it is crucial to provide the calling python version to pymod.find_installation. Otherwise, meson will always use the first version in finds.
Note that, since meson is called as a subprocess in mesonpy, meson itself is not necessarily called with the same python version as pip/build.
One fix would be to pass an option, for example -Dbuild_python=python3.9, to meson that indicates which version called pip/build.
That way one can use
Thanks for opening the issue @llohse. This indeed seems to be a bit of an issue in general, however a meson-python-specific option to work around the problem doesn't seem desirable to me. That way you get different behavior for using Meson directly (e.g., meson setup ... meson install) vs. using meson-python.
Another way to look at this is that meson-python is only for sdists and wheels. And for that use case, adding meson as a build dependency in pyproject.toml already must be done anyway.
Back to Meson itself, and the ways to ensure you get the right Python version:
If you're developing a Python package, you always want to install Meson into your development environment (conda/virtual environment). That way this should be robust:
If you're on a plain Linux distro without any separate development environment but with two Pythons installed: now you have an issue. Short of editing your meson.build file to use the Python version you want like so: `py_mod = import('python-3.9'), I don't think there are any good options. That said, you don't want to be developing with a distro-installed Python outside of a virtualenv anyway, that's inherently fragile. So I think the "fix" here is documenting "don't do that!".
Hi @llohse, thank you for opening this issue. We currently force Meson to use the Python interpreter that was used to invoke the build backend by passing a cross file. This should make sure Meson is actually using the correct Python interpreter to build the module.
Can you provide some example where this appears to be broken, or problematic?
Thanks for the clarification. This indeed sounds like an elegant solution. My assumption that Meson had no way of knowing the correct python version turns out to be invalid, then.
In order for this to work, one must not pass a path to python.find_installation in meson.build. (Would be nice to document this.)
We currently force Meson to use the Python interpreter that was used to invoke the build backend by passing a cross file. This should make sure Meson is actually using the correct Python interpreter to build the module.
I might have a use case, where this either seems to not work or is incorrectly covered in the tests:
I want to migrate the openSUSE RPM package of SciPy from the deprecated distutils build to the new meson build. Instead of calling SciPy's dev.py or meson directly, I wanted to give the meson-python PEP517 approach a try and found out that there is currently no openSUSE RPM package for it. So I started to package python-meson-python as well. Now openSUSE Tumbleweed is a bit special in that we package python packages for multiple Python versions. So there should be a python38-meson-python, a python39-meson-python and a python310-meson-python which have the files for the respecive sitelibs. However, meson itself is, as of now, only available as a single command and installed into the python3.10 sitelib. The system-wide /usr/bin/python3/ is hardcoded to Python3.10. This results in the following failure of the test suite:
[ 12s] + python_flavor=python39
[ 12s] + PYTHONPATH=/home/abuild/rpmbuild/BUILDROOT/python-meson-python-0.8.1-0.x86_64/usr/lib/python3.9/site-packages
[ 12s] + PYTHONDONTWRITEBYTECODE=1
[ 12s] + pytest-3.9 --ignore=_build.python39 --ignore=_build.python310 -v -vv
[ 12s] ============================= test session starts ==============================
[ 12s] platform linux -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0 -- /usr/bin/python3.9
[ 12s] cachedir: .pytest_cache
[ 12s] rootdir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1, configfile: setup.cfg
[ 12s] plugins: mock-3.6.1
[ 12s] collecting ... collected 47 items
[ 12s]
[ 13s] tests/test_metadata.py::test_no_pep621 PASSED [ 2%]
[ 13s] tests/test_metadata.py::test_pep621 PASSED [ 4%]
[ 14s] tests/test_metadata.py::test_dynamic_version PASSED [ 6%]
[ 14s] tests/test_output.py::test_colors[False-env0-False] PASSED [ 8%]
[ 14s] tests/test_output.py::test_colors[True-env1-True] PASSED [ 10%]
[ 14s] tests/test_output.py::test_colors[False-env2-False] PASSED [ 12%]
[ 14s] tests/test_output.py::test_colors[True-env3-False] PASSED [ 14%]
[ 14s] tests/test_output.py::test_colors[False-env4-True] PASSED [ 17%]
[ 14s] tests/test_output.py::test_colors[True-env5-True] PASSED [ 19%]
[ 14s] tests/test_output.py::test_colors_conflict PASSED [ 21%]
[ 15s] tests/test_pep517.py::test_get_requires_for_build_wheel[pure-True-expected0] PASSED [ 23%]
[ 15s] tests/test_pep517.py::test_get_requires_for_build_wheel[library-True-expected1] PASSED [ 25%]
[ 16s] tests/test_pep517.py::test_get_requires_for_build_wheel[pure-False-expected2] PASSED [ 27%]
[ 16s] tests/test_pep517.py::test_get_requires_for_build_wheel[library-False-expected3] PASSED [ 29%]
[ 17s] tests/test_project.py::test_name[library] PASSED [ 31%]
[ 17s] tests/test_project.py::test_name[library-pep621] PASSED [ 34%]
[ 18s] tests/test_project.py::test_version[library] PASSED [ 36%]
[ 18s] tests/test_project.py::test_version[library-pep621] PASSED [ 38%]
[ 18s] tests/test_project.py::test_unsupported_dynamic PASSED [ 40%]
[ 18s] tests/test_project.py::test_unsupported_python_version PASSED [ 42%]
[ 18s] tests/test_sdist.py::test_contents PASSED [ 44%]
[ 19s] tests/test_sdist.py::test_contents_subdirs PASSED [ 46%]
[ 20s] tests/test_sdist.py::test_contents_unstaged PASSED [ 48%]
[ 20s] tests/test_tags.py::test_stable_abi_tag[abi3-3-abi3-None] PASSED [ 51%]
[ 20s] tests/test_tags.py::test_stable_abi_tag[abi4-4-abi4-None] PASSED [ 53%]
[ 20s] tests/test_tags.py::test_stable_abi_tag_invalid PASSED [ 55%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[cpython-37-x86_64-linux-gnu-cpython-37-additional0-cp37-cp37] PASSED [ 57%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[cpython-310-x86_64-linux-gnu-cpython-310-additional1-cp310-cp310] PASSED [ 59%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[cpython-310-cpython-310-additional2-cp310-cp310] PASSED [ 61%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[cpython-310-special-cpython-310-additional3-cp310-cp310] PASSED [ 63%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[pypy-41-pypy-41-additional4-pypy_41-pp39] PASSED [ 65%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[pypy3-72-x86_64-linux-gnu-pypy3-72-additional5-pypy3_72-pp39] PASSED [ 68%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag[cpython-310-x86_64-linux-gnu-cpython-310-additional6-cp310-cp310] PASSED [ 70%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag_invalid[-Invalid PEP 3149 interpreter tag, expected at least 2 parts but got 1] PASSED [ 72%]
[ 20s] tests/test_tags.py::test_linux_interpreter_tag_invalid[invalid-Invalid PEP 3149 interpreter tag, expected at least 2 parts but got 1] PASSED [ 74%]
[ 20s] tests/test_tags.py::test_windows_interpreter_tag[cp310-win_amd64-parts0-cp310-cp310] PASSED [ 76%]
[ 20s] tests/test_tags.py::test_windows_interpreter_tag[cp38-win32-parts1-cp38-cp38] PASSED [ 78%]
[ 20s] tests/test_tags.py::test_windows_interpreter_tag_warn[] PASSED [ 80%]
[ 20s] tests/test_tags.py::test_windows_interpreter_tag_warn[unknown] PASSED [ 82%]
[ 20s] tests/test_tags.py::test_windows_interpreter_tag_warn[too-much-information] PASSED [ 85%]
[ 22s] tests/test_wheel.py::test_contents PASSED [ 87%]
[ 23s] tests/test_wheel.py::test_purelib_and_platlib XFAIL (Meson bug) [ 89%]
[ 24s] tests/test_wheel.py::test_pure PASSED [ 91%]
[ 25s] tests/test_wheel.py::test_configure_data FAILED [ 93%]
[ 25s] tests/test_wheel.py::test_interpreter_abi_tag XFAIL (Meson bug) [ 95%]
[ 31s] tests/test_wheel.py::test_local_lib FAILED [ 97%]
[ 32s] tests/test_wheel.py::test_contents_license_file PASSED [100%]
[ 32s]
[ 32s] =================================== FAILURES ===================================
[ 32s] _____________________________ test_configure_data ______________________________
[ 32s]
[ 32s] wheel_configure_data = PosixPath('/tmp/pytest-of-abuild/pytest-5/test0/mesonpy-test-fxmfkngg/configure_data-1.0.0-py3-none-any.whl')
[ 32s]
[ 32s] def test_configure_data(wheel_configure_data):
[ 32s] artifact = wheel.wheelfile.WheelFile(wheel_configure_data)
[ 32s]
[ 32s] > assert wheel_contents(artifact) == {
[ 32s] 'configure_data-1.0.0.data/platlib/configure_data.py',
[ 32s] 'configure_data-1.0.0.dist-info/METADATA',
[ 32s] 'configure_data-1.0.0.dist-info/RECORD',
[ 32s] 'configure_data-1.0.0.dist-info/WHEEL',
[ 32s] }
[ 32s] E AssertionError: assert {'configure_data-1.0.0.dist-info/METADATA',\n 'configure_data-1.0.0.dist-info/RECORD',\n 'configure_data-1.0.0.dist-info/WHEEL'} == {'configure_data-1.0.0.data/platlib/configure_data.py',\n 'configure_data-1.0.0.dist-info/METADATA',\n 'configure_data-1.0.0.dist-info/RECORD',\n 'configure_data-1.0.0.dist-info/WHEEL'}
[ 32s] E Extra items in the right set:
[ 32s] E 'configure_data-1.0.0.data/platlib/configure_data.py'
[ 32s] E Full diff:
[ 32s] E {
[ 32s] E - 'configure_data-1.0.0.data/platlib/configure_data.py',
[ 32s] E 'configure_data-1.0.0.dist-info/METADATA',
[ 32s] E 'configure_data-1.0.0.dist-info/RECORD',
[ 32s] E 'configure_data-1.0.0.dist-info/WHEEL',
[ 32s] E }
[ 32s]
[ 32s] tests/test_wheel.py:103: AssertionError
[ 32s] ---------------------------- Captured stdout setup -----------------------------
[ 32s] ! Using Meson to generate the project metadata (no `project` section in pyproject.toml)
[ 32s] + meson setup --native-file=/home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-native-file.ini -Ddebug=false -Doptimization=2 --prefix=/usr /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/build
[ 32s] The Meson build system
[ 32s] Version: 0.63.1
[ 32s] Source dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data
[ 32s] Build dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/build
[ 32s] Build type: native build
[ 32s] Project name: configure-data
[ 32s] Project version: 1.0.0
[ 32s] Host machine cpu family: x86_64
[ 32s] Host machine cpu: x86_64
[ 32s] Program python3 found: YES (/usr/bin/python3)
[ 32s] Configuring configure_data.py using configuration
[ 32s] Build targets in project: 0
[ 32s]
[ 32s] configure-data 1.0.0
[ 32s]
[ 32s] User defined options
[ 32s] Native files: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-native-file.ini
[ 32s] debug : false
[ 32s] optimization: 2
[ 32s] prefix : /usr
[ 32s]
[ 32s] Found ninja-1.11.0 at /usr/bin/ninja
[ 32s] + meson compile
[ 32s] ninja: no work to do.
[ 32s] + meson install --destdir /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/install
[ 32s] ninja: Entering directory `/home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/build'
[ 32s] ninja: no work to do.
[ 32s] Installing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/build/configure_data.py to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/install/usr/lib/python3.10/site-packages
[ 32s] WARNING Using heuristics to map files to wheel, this may result in incorrect locations
[ 32s] WARNING File could not be mapped to an equivalent wheel directory: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/configure-data/.mesonpy-4nmr53n1/install/usr/lib/python3.10/site-packages/configure_data.py (/usr/lib/python3.10/site-packages/configure_data.py)
[ 32s] Copying files to wheel...
[ 32s] ________________________________ test_local_lib ________________________________
[ 32s]
[ 32s] virtual_env = PosixPath('/tmp/mesonpy-test-venv-qsgs3rw4/bin/python')
[ 32s] wheel_link_against_local_lib = PosixPath('/tmp/pytest-of-abuild/pytest-5/test0/mesonpy-test-fxmfkngg/link_against_local_lib-1.0.0-py3-none-linux_x86_64.whl')
[ 32s]
[ 32s] @pytest.mark.skipif(platform.system() != 'Linux', reason='Unsupported on this platform for now')
[ 32s] @pytest.mark.xfail(
[ 32s] sys.version_info >= (3, 9) and os.environ.get('GITHUB_ACTIONS') == 'true',
[ 32s] reason='github actions',
[ 32s] strict=True,
[ 32s] )
[ 32s] def test_local_lib(virtual_env, wheel_link_against_local_lib):
[ 32s] subprocess.check_call([virtual_env, '-m', 'pip', 'install', wheel_link_against_local_lib])
[ 32s] > subprocess.check_output([
[ 32s] virtual_env, '-c', 'import example; print(example.example_sum(1, 2))'
[ 32s] ]).decode() == '3'
[ 32s]
[ 32s] tests/test_wheel.py:125:
[ 32s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 32s] /usr/lib64/python3.9/subprocess.py:424: in check_output
[ 32s] return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
[ 32s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 32s]
[ 32s] input = None, capture_output = False, timeout = None, check = True
[ 32s] popenargs = ([PosixPath('/tmp/mesonpy-test-venv-qsgs3rw4/bin/python'), '-c', 'import example; print(example.example_sum(1, 2))'],)
[ 32s] kwargs = {'stdout': -1}
[ 32s] process = <Popen: returncode: 1 args: [PosixPath('/tmp/mesonpy-test-venv-qsgs3rw4/bin/...>
[ 32s] stdout = b'', stderr = None, retcode = 1
[ 32s]
[ 32s] def run(*popenargs,
[ 32s] input=None, capture_output=False, timeout=None, check=False, **kwargs):
[ 32s] """Run command with arguments and return a CompletedProcess instance.
[ 32s]
[ 32s] The returned instance will have attributes args, returncode, stdout and
[ 32s] stderr. By default, stdout and stderr are not captured, and those attributes
[ 32s] will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.
[ 32s]
[ 32s] If check is True and the exit code was non-zero, it raises a
[ 32s] CalledProcessError. The CalledProcessError object will have the return code
[ 32s] in the returncode attribute, and output & stderr attributes if those streams
[ 32s] were captured.
[ 32s]
[ 32s] If timeout is given, and the process takes too long, a TimeoutExpired
[ 32s] exception will be raised.
[ 32s]
[ 32s] There is an optional argument "input", allowing you to
[ 32s] pass bytes or a string to the subprocess's stdin. If you use this argument
[ 32s] you may not also use the Popen constructor's "stdin" argument, as
[ 32s] it will be used internally.
[ 32s]
[ 32s] By default, all communication is in bytes, and therefore any "input" should
[ 32s] be bytes, and the stdout and stderr will be bytes. If in text mode, any
[ 32s] "input" should be a string, and stdout and stderr will be strings decoded
[ 32s] according to locale encoding, or by "encoding" if set. Text mode is
[ 32s] triggered by setting any of text, encoding, errors or universal_newlines.
[ 32s]
[ 32s] The other arguments are the same as for the Popen constructor.
[ 32s] """
[ 32s] if input is not None:
[ 32s] if kwargs.get('stdin') is not None:
[ 32s] raise ValueError('stdin and input arguments may not both be used.')
[ 32s] kwargs['stdin'] = PIPE
[ 32s]
[ 32s] if capture_output:
[ 32s] if kwargs.get('stdout') is not None or kwargs.get('stderr') is not None:
[ 32s] raise ValueError('stdout and stderr arguments may not be used '
[ 32s] 'with capture_output.')
[ 32s] kwargs['stdout'] = PIPE
[ 32s] kwargs['stderr'] = PIPE
[ 32s]
[ 32s] with Popen(*popenargs, **kwargs) as process:
[ 32s] try:
[ 32s] stdout, stderr = process.communicate(input, timeout=timeout)
[ 32s] except TimeoutExpired as exc:
[ 32s] process.kill()
[ 32s] if _mswindows:
[ 32s] # Windows accumulates the output in a single blocking
[ 32s] # read() call run on child threads, with the timeout
[ 32s] # being done in a join() on those threads. communicate()
[ 32s] # _after_ kill() is required to collect that and add it
[ 32s] # to the exception.
[ 32s] exc.stdout, exc.stderr = process.communicate()
[ 32s] else:
[ 32s] # POSIX _communicate already populated the output so
[ 32s] # far into the TimeoutExpired exception.
[ 32s] process.wait()
[ 32s] raise
[ 32s] except: # Including KeyboardInterrupt, communicate handled that.
[ 32s] process.kill()
[ 32s] # We don't call process.wait() as .__exit__ does that for us.
[ 32s] raise
[ 32s] retcode = process.poll()
[ 32s] if check and retcode:
[ 32s] > raise CalledProcessError(retcode, process.args,
[ 32s] output=stdout, stderr=stderr)
[ 32s] E subprocess.CalledProcessError: Command '[PosixPath('/tmp/mesonpy-test-venv-qsgs3rw4/bin/python'), '-c', 'import example; print(example.example_sum(1, 2))']' returned non-zero exit status 1.
[ 32s]
[ 32s] /usr/lib64/python3.9/subprocess.py:528: CalledProcessError
[ 32s] ---------------------------- Captured stdout setup -----------------------------
[ 32s] ! Using Meson to generate the project metadata (no `project` section in pyproject.toml)
[ 32s] + meson setup --native-file=/home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-native-file.ini -Ddebug=false -Doptimization=2 --prefix=/usr /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/build
[ 32s] The Meson build system
[ 32s] Version: 0.63.1
[ 32s] Source dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib
[ 32s] Build dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/build
[ 32s] Build type: native build
[ 32s] Project name: link-against-local-lib
[ 32s] Project version: 1.0.0
[ 32s] C compiler for the host machine: cc (gcc 12.2.1 "cc (SUSE Linux) 12.2.1 20220830 [revision e927d1cf141f221c5a32574bde0913307e140984]")
[ 32s] C linker for the host machine: cc ld.bfd 2.39.0.20220810-1
[ 32s] Host machine cpu family: x86_64
[ 32s] Host machine cpu: x86_64
[ 32s] Found pkg-config: /usr/bin/pkg-config (1.8.0)
[ 32s] Run-time dependency python3 found: YES 3.10
[ 32s] Program python3 found: YES (/usr/bin/python3)
[ 32s] Build targets in project: 2
[ 32s]
[ 32s] link-against-local-lib 1.0.0
[ 32s]
[ 32s] User defined options
[ 32s] Native files: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-native-file.ini
[ 32s] debug : false
[ 32s] optimization: 2
[ 32s] prefix : /usr
[ 32s]
[ 32s] Found ninja-1.11.0 at /usr/bin/ninja
[ 32s] + meson compile
[ 32s] [1/5] Compiling C object libexample.so.p/examplelib.c.o
[ 32s] [2/5] Linking target libexample.so
[ 32s] [3/5] Compiling C object example.cpython-310-x86_64-linux-gnu.so.p/examplemod.c.o
[ 32s] [4/5] Generating symbol file libexample.so.p/libexample.so.symbols
[ 32s] [5/5] Linking target example.cpython-310-x86_64-linux-gnu.so
[ 32s] + meson install --destdir /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/install
[ 32s] ninja: Entering directory `/home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/build'
[ 32s] ninja: no work to do.
[ 32s] Installing libexample.so to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/install/usr/lib64
[ 32s] Installing example.cpython-310-x86_64-linux-gnu.so to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/install/usr/lib64/python3.10/site-packages
[ 32s] WARNING Using heuristics to map files to wheel, this may result in incorrect locations
[ 32s] WARNING File could not be mapped to an equivalent wheel directory: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/tests/packages/link-against-local-lib/.mesonpy-6mynj858/install/usr/lib64/python3.10/site-packages/example.cpython-310-x86_64-linux-gnu.so (/usr/lib64/python3.10/site-packages/example.cpython-310-x86_64-linux-gnu.so)
[ 32s] Copying files to wheel...
[ 32s] [0/0] .link_against_local_lib.mesonpy.libs/libexample.so
[ 32s] ----------------------------- Captured stdout call -----------------------------
[ 32s] Processing /tmp/pytest-of-abuild/pytest-5/test0/mesonpy-test-fxmfkngg/link_against_local_lib-1.0.0-py3-none-linux_x86_64.whl
[ 32s] Installing collected packages: link-against-local-lib
[ 32s] Successfully installed link-against-local-lib-1.0.0
[ 32s] ----------------------------- Captured stderr call -----------------------------
[ 32s] Traceback (most recent call last):
[ 32s] File "<string>", line 1, in <module>
[ 32s] ModuleNotFoundError: No module named 'example'
[ 32s] =========================== short test summary info ============================
[ 32s] FAILED tests/test_wheel.py::test_configure_data - AssertionError: assert {'co...
[ 32s] FAILED tests/test_wheel.py::test_local_lib - subprocess.CalledProcessError: C...
[ 32s] =================== 2 failed, 43 passed, 2 xfailed in 19.86s ===================
[ 32s] error: Bad exit status from /var/tmp/rpm-tmp.ZYPCaB (%check)
Note that despite being called from Python 3.9 Pytest, meson finds Python 3.10 and fails to create wheels or links to Python 3.9
If this is just a quirk of the tests, I am happy to skip them. However, unless there is a guarantee for ABI3 or pure wheels, we need a way to build wheels for every Python version.
However, meson itself is, as of now, only available as a single command and installed into the python3.10 sitelib. The system-wide /usr/bin/python3/ is hardcoded to Python3.10.
Note that despite being called from Python 3.9 Pytest, meson finds Python 3.10 and fails to create wheels or links to Python 3.9
python39-meson-python should be configuring the meson program to override the python binary to whatever is sys.executable of python39-meson-python itself.
In this case, that should be import venv; venv.create(tempdir); run(tempdir / 'bin' / 'python', '-m', 'pip', ...), so whatever pytest's sys.executable is should be used as the basis of the venv.
That's the thing. meson-python assumes meson being provided as command in the venv without checking that it is the case. Especially during the test suite.
Why does it matter which version of the command line utility meson is found in PATH? One of the command line arguments to the meson utility (wherever it may be found) is a cfg file specifying what python executable mesonpy (this project) would like meson to use instead of looking for one.
Again: this may be a mesonpy bug, or just a project testsuite bug, I don't know (I haven't diagnosed it) but it's definitely not a "the wrong Meson in PATH was used".
Meson is fully capable of being run with a py3.10 shebang but using a machine config file (--native-file) pointing at 3.9 instead, and thus building code for 3.9. In theory, mesonpy already does exactly this, hardcoding the version of python that mesonpy uses. The vehicle it uses for doing this is mesonpy's sys.executable. I cannot see how pytest might mess that up, but it's even less likely that pip would mess that up, so if I had to choose something to suspect and take a closer look at, I would look at the tests.
Why does it matter which version of the command line utility meson is found in PATH? One of the command line arguments to the meson utility (wherever it may be found) is a cfg file specifying what python executable mesonpy (this project) would like meson to use instead of looking for one.
Could you please point me to the command line argument? And additionally, is there any way to tell meson-python to use it? I can't find anything documented. --python.install-env is not it.
Find a python installation matching name_or_path.
That argument is optional, if not provided then the returned python installation will be the one used to run Meson.
So short of patching the meson.build of a package from pymod.find_installation() to pymod.find_installation('/my/own/custom/python3.9'), a meson from /usr/bin/meson will always find the /usr/bin/python3 of the entry-point shebang. I don't say this is wrong or a bug (except for the test suite maybe), but I am missing the functionality to override this unexpected behavior.
Hi @llohse, thank you for opening this issue. We currently force Meson to use the Python interpreter that was used to invoke the build backend by passing a cross file. This should make sure Meson is actually using the correct Python interpreter to build the module.
The binaries section contains a list of binaries. These can be used internally by Meson, or by the find_program function.
The binaries section of a machine file (as passed by mesonpy) will be used internally by the find_installation() method as well.
...
Again, your version of Meson (and/or what version of python it's running with) is irrelevant. The only question is whether the internal mesonpy functionality of passing that native file, is passing the correct location:
in real world scenarios
in pytest
I would probably add debug prints to mesonpy to see what data it is writing into that native file.
We currently force Meson to use the Python interpreter that was used to invoke the build backend by passing a cross file. This should make sure Meson is actually using the correct Python interpreter to build the module.
I might have a use case, where this either seems to not work or is incorrectly covered in the tests:
Can you test whether that fixes openSUSE? It's indeed a bug in mesonpy (and not Meson), the functionality to override the python installation to build against, just didn't work.
Activity
rgommers commentedon May 9, 2022
Thanks for opening the issue @llohse. This indeed seems to be a bit of an issue in general, however a
meson-python-specific option to work around the problem doesn't seem desirable to me. That way you get different behavior for using Meson directly (e.g.,meson setup...meson install) vs. usingmeson-python.Another way to look at this is that
meson-pythonis only for sdists and wheels. And for that use case, addingmesonas a build dependency inpyproject.tomlalready must be done anyway.Back to Meson itself, and the ways to ensure you get the right Python version:
meson.buildfile to use the Python version you want like so: `py_mod = import('python-3.9'), I don't think there are any good options. That said, you don't want to be developing with a distro-installed Python outside of a virtualenv anyway, that's inherently fragile. So I think the "fix" here is documenting "don't do that!".llohse commentedon May 9, 2022
Thanks for your comment @rgommers.
Omitting the version in
find_installationand installing meson into the build environment sounds like a good idea. I'll verify this works for me.FFY00 commentedon May 9, 2022
Hi @llohse, thank you for opening this issue. We currently force Meson to use the Python interpreter that was used to invoke the build backend by passing a cross file. This should make sure Meson is actually using the correct Python interpreter to build the module.
Can you provide some example where this appears to be broken, or problematic?
llohse commentedon May 9, 2022
Thanks for the clarification. This indeed sounds like an elegant solution. My assumption that Meson had no way of knowing the correct python version turns out to be invalid, then.
In order for this to work, one must not pass a path to
python.find_installationinmeson.build. (Would be nice to document this.)FFY00 commentedon May 9, 2022
Yes, that's true. We should definitely document this.
bnavigator commentedon Sep 10, 2022
Hi,
I might have a use case, where this either seems to not work or is incorrectly covered in the tests:
I want to migrate the openSUSE RPM package of SciPy from the deprecated distutils build to the new meson build. Instead of calling SciPy's
dev.pyormesondirectly, I wanted to give the meson-python PEP517 approach a try and found out that there is currently no openSUSE RPM package for it. So I started to packagepython-meson-pythonas well. Now openSUSE Tumbleweed is a bit special in that we package python packages for multiple Python versions. So there should be apython38-meson-python, apython39-meson-pythonand apython310-meson-pythonwhich have the files for the respecive sitelibs. However, meson itself is, as of now, only available as a single command and installed into the python3.10 sitelib. The system-wide/usr/bin/python3/is hardcoded to Python3.10. This results in the following failure of the test suite:Note that despite being called from Python 3.9 Pytest, meson finds Python 3.10 and fails to create wheels or links to Python 3.9
If this is just a quirk of the tests, I am happy to skip them. However, unless there is a guarantee for ABI3 or pure wheels, we need a way to build wheels for every Python version.
eli-schwartz commentedon Sep 11, 2022
@bnavigator,
python39-meson-python should be configuring the
mesonprogram to override the python binary to whatever is sys.executable of python39-meson-python itself.In this case, that should be
import venv; venv.create(tempdir); run(tempdir / 'bin' / 'python', '-m', 'pip', ...), so whatever pytest's sys.executable is should be used as the basis of the venv.bnavigator commentedon Sep 11, 2022
That's the thing.
meson-pythonassumesmesonbeing provided as command in the venv without checking that it is the case. Especially during the test suite.eli-schwartz commentedon Sep 11, 2022
Why does it matter which version of the command line utility
mesonis found in PATH? One of the command line arguments to themesonutility (wherever it may be found) is a cfg file specifying what python executable mesonpy (this project) would likemesonto use instead of looking for one.Again: this may be a mesonpy bug, or just a project testsuite bug, I don't know (I haven't diagnosed it) but it's definitely not a "the wrong Meson in PATH was used".
Meson is fully capable of being run with a py3.10 shebang but using a machine config file (
--native-file) pointing at 3.9 instead, and thus building code for 3.9. In theory, mesonpy already does exactly this, hardcoding the version of python that mesonpy uses. The vehicle it uses for doing this is mesonpy's sys.executable. I cannot see how pytest might mess that up, but it's even less likely that pip would mess that up, so if I had to choose something to suspect and take a closer look at, I would look at the tests.bnavigator commentedon Sep 12, 2022
Could you please point me to the command line argument? And additionally, is there any way to tell meson-python to use it? I can't find anything documented.
--python.install-envis not it.Specifically there is this:
https://mesonbuild.com/Python-module.html#find_installation
So short of patching the
meson.buildof a package frompymod.find_installation()topymod.find_installation('/my/own/custom/python3.9'), amesonfrom/usr/bin/mesonwill always find the/usr/bin/python3of the entry-point shebang. I don't say this is wrong or a bug (except for the test suite maybe), but I am missing the functionality to override this unexpected behavior.eli-schwartz commentedon Sep 12, 2022
https://github.com/FFY00/meson-python/issues/51#issuecomment-1121193585
https://github.com/FFY00/meson-python/blob/2510cde44342f3167c44ea05d650c8a524a43879/mesonpy/__init__.py#L615-L618
https://github.com/FFY00/meson-python/blob/2510cde44342f3167c44ea05d650c8a524a43879/mesonpy/__init__.py#L665-L667
https://mesonbuild.com/Machine-files.html#binaries
The binaries section of a machine file (as passed by mesonpy) will be used internally by the
find_installation()method as well....
Again, your version of Meson (and/or what version of python it's running with) is irrelevant. The only question is whether the internal mesonpy functionality of passing that native file, is passing the correct location:
I would probably add debug prints to mesonpy to see what data it is writing into that native file.
bnavigator commentedon Sep 12, 2022
It obviously does not work as you describe.
bnavigator commentedon Sep 12, 2022
Neither one. Pytest, see above. "Real world": meson-python's own build:
eli-schwartz commentedon Sep 12, 2022
While here, I noticed:
... this is a typo, the fix is https://github.com/FFY00/meson-python/pull/137
Can you test whether that fixes openSUSE? It's indeed a bug in mesonpy (and not Meson), the functionality to override the python installation to build against, just didn't work.
bnavigator commentedon Sep 12, 2022
Confirmed! Thanks!
Although I must admit that I find the whole override mechanism to be a bit fragile. The
pythonbinary is not documented in https://mesonbuild.com/Machine-files.html#binaries or in https://mesonbuild.com/Python-module.html#find_installation that it uses thepythonname. Note the 'python3' string in Meson's report when not providing the binary entry in the native file.dnicolodi commentedon Nov 24, 2022
The only actionable issue here is to document the requirements on how
import('python').find_installation()is called. I moved that into #233.ENH: Specify python version in extbuild.
MAINT: testing: specify python executable to use in extbuild (#28183)