Mac で`xxx.whl is not a supported wheel on this platform.` を解決する
tldr;
from pip._vendor.packaging.tags import mac_platforms; list(mac_platforms)
した結果から選ぶ
['macosx_12_0_arm64',
'macosx_12_0_universal2',
'macosx_11_0_arm64',
...]
やりたいこと: .whl の名前を正しくする
python setup.py bdist-wheel
した時に <my-package>-py3-none-any.whl
ができてこれを twine upload
などで pypi にあげるが、これを linux と mac で分けたかった時にハマったので忘備録.
なぜ必要か
Rust の CLI アプリをラップしていたので、build は各OS上でやらないと segfault になる.
やったこと
解決に至った道のり.
Step1: --plat-name の設定
python setup.py bdist_wheel --plat-name=<my-platform-name>
すると <my-package>-py3-none-<my-platform-name>.whl
ができるので、適当に macosx
と名前をつけてみた.<my-package>-maxosx.whl
は正しくできるが、それを pip install ***.whl
しようとするとxxx.whl is not a supported wheel on this platform.
が出る.名前だけ any
に変えるとインストールできるので名前だけの問題ぽい.
Step2: pip のソースコードから該当エラーを探す
ググってもあまり埒が開かなかったのでpip のソースコード(https://github.com/pypa/pip)を見に行く.手元に clone して git grep 'is not a supported wheel on this platform'
すると3箇所だけヒットする.
src/pip/_internal/req/req_set.py:92: "{} is not a supported wheel on this platform.".format(
src/pip/_internal/resolution/resolvelib/factory.py:140: msg = f"{link.filename} is not a supported wheel on this platform."
tests/functional/test_install_reqs.py:757: "simple.dist-0.1-py1-none-invalid.whl is not a supported wheel on this platform"
test case
一番下がテストなのでtests/functional/test_install_reqs.py を覗くと今回の挙動がちゃんとテストされている.やはりどこかで名前の validation がされていると考えて良さそう.
validation
一番上のsrc/pip/_internal/req/req_set.pyが validation されている部分.
# src/pip/_internal/req/req_set.py
from pip._internal.utils import compatibility_tags
...
tags = compatibility_tags.get_supported()
if self.check_supported_wheels and not wheel.supported(tags):
raise InstallationError(
"{} is not a supported wheel on this platform.".format(
wheel.filename
)
)
compatibility_tags.get_supported()
の中身を探していけば良さそう.
Step3: compatibility_tags の中身を読み解いていく
src/pip/_internal/utils/compatibility_tags.py の中身を見ていく.
_mac_platforms
といういかにもな関数があるものの、arch を事前に指定しているのでこれを呼び出す他の関数がありそう.タグの生成をしているところを見にいく.
# src/pip/_internal/utils/compatibility_tags.py
from pip._vendor.packaging.tags import (
...,
compatible_tags,
...
supported.extend(
compatible_tags(
python_version=python_version,
interpreter=interpreter,
platforms=platforms,
)
)
Step4:
importされているsrc/pip/_vendor/packaging/tags.pyを見ていく.platform_tags
が mac_platforms
を呼び出しているので、この辺りで 適当なintrepretor を開いて中身を見てみる.
def mac_platforms(
version: Optional[MacVersion] = None, arch: Optional[str] = None
) -> Iterator[str]:
"""
Yields the platform tags for a macOS system.
The `version` parameter is a two-item tuple specifying the macOS version to
generate platform tags for. The `arch` parameter is the CPU architecture to
generate platform tags for. Both parameters default to the appropriate value
for the current system.
"""
version_str, _, cpu_arch = platform.mac_ver()
if version is None:
version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
else:
version = version
if arch is None:
arch = _mac_arch(cpu_arch)
else:
arch = arch
if (10, 0) <= version and version < (11, 0):
...
何となくそれっぽい.すると以下のリストが出てくる
> from pip._vendor.packaging.tags import mac_platforms
> list(mac_platforms)
['macosx_12_0_arm64',
'macosx_12_0_universal2',
'macosx_11_0_arm64',
...]
--plat-names=macosx_12_0_universal2
とすると無事に .whl をインストールできた.
Discussion