Skip to content

Pass the calling python version to meson #51

Closed

Description

@llohse

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

pymod = import('python')
python = pymod.find_installation(get_option('build_python'), ...)

in meson.build.

Activity

  1. rgommers commented on May 9, 2022

    @rgommers
    Contributor

    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:
    py_mod = import('python')
    py3 = py_mod.find_installation()
    py3_dep = py3.dependency()
    • 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!".
  2. llohse commented on May 9, 2022

    @llohse
    Author

    Thanks for your comment @rgommers.

    Omitting the version in find_installation and installing meson into the build environment sounds like a good idea. I'll verify this works for me.

  3. FFY00 commented on May 9, 2022

    @FFY00
    Member

    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?

  4. llohse commented on May 9, 2022

    @llohse
    Author

    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.)

  5. FFY00 commented on May 9, 2022

    @FFY00
    Member

    Yes, that's true. We should definitely document this.

  6. bnavigator commented on Sep 10, 2022

    @bnavigator
    Contributor

    Hi,

    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.

  7. eli-schwartz commented on Sep 11, 2022

    @eli-schwartz
    Member

    @bnavigator,

    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.

  8. bnavigator commented on Sep 11, 2022

    @bnavigator
    Contributor

    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.

  9. eli-schwartz commented on Sep 11, 2022

    @eli-schwartz
    Member

    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.

  10. bnavigator commented on Sep 12, 2022

    @bnavigator
    Contributor

    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.

    Specifically there is this:
    https://mesonbuild.com/Python-module.html#find_installation

    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.

  11. eli-schwartz commented on Sep 12, 2022

    @eli-schwartz
    Member

    https://github.com/FFY00/meson-python/issues/51#issuecomment-1121193585

    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.

    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 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.

  12. bnavigator commented on Sep 12, 2022

    @bnavigator
    Contributor

    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:

    It obviously does not work as you describe.

  13. bnavigator commented on Sep 12, 2022

    @bnavigator
    Contributor

    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

    Neither one. Pytest, see above. "Real world": meson-python's own build:

    [   35s] + python3.8 -mpip wheel --no-deps --disable-pip-version-check --use-pep517 --no-build-isolation --progress-bar off --verbose . -w build/
    [   36s] Processing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1
    [   36s]   Preparing metadata (pyproject.toml): started
    [   36s]   Running command Preparing metadata (pyproject.toml)
    [   37s]   The Meson build system
    [   37s]   Version: 0.63.1
    [   37s]   Source dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1
    [   37s]   Build dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/build
    [   37s]   Build type: native build
    [   37s]   Project name: mesonpy
    [   37s]   Project version: 0.8.1
    [   37s]   Host machine cpu family: x86_64
    [   37s]   Host machine cpu: x86_64
    [   37s]   Program python3 found: YES (/usr/bin/python3)
    [   37s]   Build targets in project: 0
    [   37s] 
    [   37s]   mesonpy 0.8.1
    [   37s] 
    [   37s]     User defined options
    [   37s]       Native files: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-native-file.ini
    [   37s]       debug       : false
    [   37s]       optimization: 2
    [   37s]       prefix      : /usr
    [   37s] 
    [   37s]   Found ninja-1.11.0 at /usr/bin/ninja
    [   38s]   ninja: no work to do.
    [   39s]   ninja: Entering directory `/home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/build'
    [   39s]   ninja: no work to do.
    [   39s]   Installing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/mesonpy/__init__.py to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/install/usr/lib/python3.10/site-packages/mesonpy
    [   39s]   Installing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/mesonpy/_compat.py to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/install/usr/lib/python3.10/site-packages/mesonpy
    [   39s]   Installing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/mesonpy/_elf.py to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/install/usr/lib/python3.10/site-packages/mesonpy
    [   39s]   Installing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/mesonpy/_tags.py to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/install/usr/lib/python3.10/site-packages/mesonpy
    [   39s]   Installing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/mesonpy/_util.py to /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/install/usr/lib/python3.10/site-packages/mesonpy
    [   39s]   + meson setup --native-file=/home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-native-file.ini -Ddebug=false -Doptimization=2 --prefix=/usr /home/abuild/rpmbuild/BUILD/meson_python-0.8.1 /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/build
    [   39s]   + meson compile
    [   39s]   + meson install --destdir /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-sk45kwgz/install
    [   39s]   Copying files to wheel...
    [   39s]   [0/4] mesonpy/__init__.py
    [   39s]   [1/4] mesonpy/_compat.py
    [   39s]   [2/4] mesonpy/_elf.py
    [   39s]   [3/4] mesonpy/_tags.py
    [   39s]   [4/4] mesonpy/_util.py
    [   39s]   Preparing metadata (pyproject.toml): finished with status 'done'
    [   39s] Building wheels for collected packages: meson-python
    [   39s]   Building wheel for meson-python (pyproject.toml): started
    [   39s]   Running command Building wheel for meson-python (pyproject.toml)
    [   39s]   Building wheel for meson-python (pyproject.toml): finished with status 'done'
    [   39s]   Created wheel for meson-python: filename=meson_python-0.8.1-py3-none-any.whl size=17969 sha256=bed0ddeea8c077fcdeec3ced6320ddfd3ef3ed7ac0bcb2f801777ab2af5394fc
    [   39s]   Stored in directory: /home/abuild/.cache/pip/wheels/c9/81/10/006b221fad68ccad4f34f106ec8a0de8eb56000d184a5793fb
    [   39s] Successfully built meson-python
    
  14. eli-schwartz commented on Sep 12, 2022

    @eli-schwartz
    Member

    While here, I noticed:

                 python3 = '{sys.executable}' 
    

    ... 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.

  15. bnavigator commented on Sep 12, 2022

    @bnavigator
    Contributor

    Confirmed! Thanks!

    [    4s] + python3.8 -mpip wheel --no-deps --disable-pip-version-check --use-pep517 --no-build-isolation --progress-bar off --verbose . -w build/
    [    4s] Processing /home/abuild/rpmbuild/BUILD/meson_python-0.8.1
    [    4s]   Preparing metadata (pyproject.toml): started
    [    4s]   Running command Preparing metadata (pyproject.toml)
    [    5s]   The Meson build system
    [    5s]   Version: 0.63.1
    [    5s]   Source dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1
    [    5s]   Build dir: /home/abuild/rpmbuild/BUILD/meson_python-0.8.1/.mesonpy-p96zaqkz/build
    [    5s]   Build type: native build
    [    5s]   Project name: mesonpy
    [    5s]   Project version: 0.8.1
    [    5s]   Host machine cpu family: x86_64
    [    5s]   Host machine cpu: x86_64
    [    5s]   Program python found: YES (/usr/bin/python3.8)
    [    5s]   Build targets in project: 0
    ...
    [   13s] + pytest-3.8 --ignore=_build.python38 --ignore=_build.python39 --ignore=_build.python310 -v
    [   14s] ============================= test session starts ==============================
    [   14s] platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0 -- /usr/bin/python3.8
    ...
    [   26s] tests/test_wheel.py::test_configure_data PASSED                          [ 93%]
    [   26s] tests/test_wheel.py::test_interpreter_abi_tag XFAIL (Meson bug)          [ 95%]
    [   34s] tests/test_wheel.py::test_local_lib PASSED                               [ 97%]
    ...
    [   35s] ======================== 45 passed, 2 xfailed in 20.96s ========================
    

    Although I must admit that I find the whole override mechanism to be a bit fragile. The python binary is not documented in https://mesonbuild.com/Machine-files.html#binaries or in https://mesonbuild.com/Python-module.html#find_installation that it uses the python name. Note the 'python3' string in Meson's report when not providing the binary entry in the native file.

  16. added
    documentationImprovements or additions to documentation
    and removed on Nov 20, 2022
  17. dnicolodi commented on Nov 24, 2022

    @dnicolodi
    Member

    The only actionable issue here is to document the requirements on how import('python').find_installation() is called. I moved that into #233.

  18. added a commit that references this issue on Jan 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions