Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intel MacOS + pyenv outputs a wheel that cannot be installed #41

Open
joshlk opened this issue Jan 23, 2025 · 5 comments
Open

Intel MacOS + pyenv outputs a wheel that cannot be installed #41

joshlk opened this issue Jan 23, 2025 · 5 comments

Comments

@joshlk
Copy link
Contributor

joshlk commented Jan 23, 2025

Hi,

I am testing the nanobind-project example with my Intel Mac with OS version 15.2 (more details below). The project builds fine, but I can't install the wheel. Pip says the wheel "is not a supported wheel on this platform" - even though I just built it. This seems to only happen when I have installed Python using pyenv and not when using uv.

Here are the steps (in the root nanobind-project example folder):

# Clear dist folder
rm -r dist
# Build a wheel
python -m build
# Outputs a wheel
ls dist/nanobind_project-0.3.4-cp312-abi3-macosx_14_6_x86_64.whl
# Try to install the wheel
python -m pip install dist/nanobind_project-0.3.4-cp312-abi3-macosx_14_6_x86_64.whl

Produces the error:

ERROR: nanobind_project-0.3.4-cp312-abi3-macosx_14_6_x86_64.whl is not a supported wheel on this platform.

Notice that the MacOS version tag is 14.6 smaller than my current OS version which is 15.2.

Version info:

  • MacOS:
$ sw_vers
ProductName:		macOS
ProductVersion:		15.2
BuildVersion:		24C101
  • Python:
$ python --version
Python 3.12.5
$ pip --version
pip 24.3.1 from ... (python 3.12)
$ python -m build --version
build 1.2.2.post1

The way I installed Python was by using Pyenv:

pyenv install 3.12.5
pyenv global 3.12.5

If I install Python using uv the wheel works and installs fine:

pip install uv
uv venv --seed --python 3.12 ~/.venvs/py3.12
source ~/.venvs/py3.12/bin/activate

When using uv, it creates a wheel named: nanobind_project-0.3.4-cp312-abi3-macosx_10_9_x86_64.whl - the MacOS version is 10.9 which is lower than the previous.

Do you have any ideas about what is going on?

Thanks,
Josh

cc: @steve-barlow

@joshlk joshlk changed the title MacOS 15.2 x86 produces a wheel that cannot be installed Intel MacOS + pyenv outputs a wheel that cannot be installed Jan 23, 2025
@tttapa
Copy link
Owner

tttapa commented Jan 24, 2025

Thanks for the detailed report!

Currently looking into this. Some thoughts and observations:

For native builds, py-build-cmake gets the Wheel platform tag (the macosx_14_6_x86_64 part) from PyPA's distlib.util.get_platform(). This in turn uses the built-in _osx_support.get_platform_osx() function, which uses the MACOSX_DEPLOYMENT_TARGET sysconfig variable if it exists, and otherwise uses the system version.
https://github.com/python/cpython/blob/732670d93b9b0c0ff8adde07418fd6f8397893ef/Lib/_osx_support.py#L503-L516

This explains why pyenv and uv yield different tags: they have different values for MACOSX_DEPLOYMENT_TARGET in their respective sysconfigs (or at least that's what I'm guessing based on the code).

Now, why does pip reject macosx_14_6_x86_64?
If I understand correctly, the list of tags that pip considers supported is assembled in pip._internal.utils.compatibility_tags.get_supported():
https://github.com/pypa/pip/blob/c7fb1e13ec79b1b48481ac245144c2b368e64f7d/src/pip/_internal/utils/compatibility_tags.py#L135
This eventually calls packaging.tags.mac_platforms(), which uses platform.mac_ver() to determine the latest supported macOS version:
https://github.com/pypa/pip/blob/c7fb1e13ec79b1b48481ac245144c2b368e64f7d/src/pip/_vendor/packaging/tags.py#L397-L408
platform.mac_ver() gets its information from the /System/Library/CoreServices/SystemVersion.plist file:
https://github.com/python/cpython/blob/732670d93b9b0c0ff8adde07418fd6f8397893ef/Lib/platform.py#L459-L498

It is not clear to me why this fails, though. Could you run the following?

import sysconfig
print(sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET'))
import distlib.util
print(distlib.util.get_platform())
import packaging.tags
print(list(packaging.tags.mac_platforms()))
import platform
print(platform.mac_ver())
import pip._internal.utils.compatibility_tags
print(pip._internal.utils.compatibility_tags.get_supported())

This does raise some more general questions as well, though:

  • Which version should py-build-cmake use for the Wheel tag? The version from distlib based on the version that's baked into the sysconfig of the running interpreter, or the current macOS version as used by packaging.tags, based on platform.mac_ver()?
  • If the user sets the MACOSX_DEPLOYMENT_TARGET environment variable, should this always override the default option (i.e. should the wheel.platform_tag=guess option become the default on macOS)?
  • Either way, py-build-cmake should probably always set MACOSX_DEPLOYMENT_TARGET during the build to match the Wheel tag.

I'm not a mac user myself, so your insights are certainly welcome!

@steve-barlow
Copy link

steve-barlow commented Jan 24, 2025 via email

@joshlk
Copy link
Contributor Author

joshlk commented Jan 24, 2025

Hi,

I have reproduced the issue using a GitHub actions runner which uses a ARM MacOS 15 machine (so the issues doesn't seem to be unique to Intel machines).

The GitHub actions file is here: https://github.com/joshlk/py-build-cmake/blob/main/.github/workflows/macos_build.yml
And an example run is here: https://github.com/joshlk/py-build-cmake/actions/runs/12947940135/job/36115546953
The output of pip._internal.utils.compatibility_tags.get_supported() can be downloaded here: https://github.com/joshlk/py-build-cmake/actions/runs/12947940135/artifacts/2480101117

It produces a wheel called: nanobind_project-0.3.4-cp312-abi3-macosx_15_2_arm64.whl which pip rejects for the same reason.

Looking at the output of pip._internal.utils.compatibility_tags.get_supported(), the only options that match the pattern cp312-abi3*_arm64 are:

<cp312-abi3-macosx_15_0_arm64 @ 4303243712>
<cp312-abi3-macosx_14_0_arm64 @ 4303243520>
<cp312-abi3-macosx_13_0_arm64 @ 4303243840>
<cp312-abi3-macosx_12_0_arm64 @ 4303244224>
<cp312-abi3-macosx_11_0_arm64 @ 4303244480>

It looks like pip is only enumerating the major OS versions and missing the minor versions. As our wheel includes a minor version "15_2" it gets rejected. Do you think this is a problem with pip or MACOSX_DEPLOYMENT_TARGET being set incorrectly?

@tttapa
Copy link
Owner

tttapa commented Jan 30, 2025

I'm currently working on a fix, but I probably won't have much time to finish it before the weekend.

In the meantime, you can try setting the MACOSX_DEPLOYMENT_TARGET to e.g. 15.0 manually, and then set wheel.platform_tag=guess (which will cause py-build-cmake to use the value from the environment rather than from the running interpreter):

export MACOSX_DEPLOYMENT_TARGET="15.0"
python -m build -C override=wheel.platform_tag=guess

Alternatively, you could even set the entire platform tag if necessary:

python -m build -C override=wheel.platform_tag=macosx_15_0_arm64

@steve-barlow
Copy link

steve-barlow commented Jan 30, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants