From fa579e3fb0531cf9d45b3be05f571fd55d9a0062 Mon Sep 17 00:00:00 2001 From: mayeut Date: Sat, 22 Apr 2023 11:26:43 +0200 Subject: [PATCH] Ability to install armv7l manylinux/musllinux wheels on armv8l aarch64 systems running under linux32 emulation will report an armv8l machine rather than armv7l. This shall not prevent packaging to report musllinux/manylinux armv7l compatibiility as long as the running python has a compatible ABI. --- src/packaging/_manylinux.py | 9 +++++++-- src/packaging/_musllinux.py | 4 ++++ src/packaging/tags.py | 2 +- tests/test_tags.py | 20 ++++++++++++++------ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/packaging/_manylinux.py b/src/packaging/_manylinux.py index 449c655b..bd25b841 100644 --- a/src/packaging/_manylinux.py +++ b/src/packaging/_manylinux.py @@ -204,6 +204,11 @@ def _is_compatible(name: str, arch: str, version: _GLibCVersion) -> bool: def platform_tags(linux: str, arch: str) -> Iterator[str]: + if arch == "armv8l": + # armv8l wheels are not accepted on PyPI + # As long as we pass the the ABI check below, + # the armv7l wheels can be installed. + arch = "armv7l" if not _have_compatible_abi(sys.executable, arch): return # Oldest glibc to be supported regardless of architecture is (2, 17). @@ -232,9 +237,9 @@ def platform_tags(linux: str, arch: str) -> Iterator[str]: glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) tag = "manylinux_{}_{}".format(*glibc_version) if _is_compatible(tag, arch, glibc_version): - yield linux.replace("linux", tag) + yield f"{tag}_{arch}" # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. if glibc_version in _LEGACY_MANYLINUX_MAP: legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version] if _is_compatible(legacy_tag, arch, glibc_version): - yield linux.replace("linux", legacy_tag) + yield f"{legacy_tag}_{arch}" diff --git a/src/packaging/_musllinux.py b/src/packaging/_musllinux.py index 706ba600..b9e72f8f 100644 --- a/src/packaging/_musllinux.py +++ b/src/packaging/_musllinux.py @@ -63,6 +63,10 @@ def platform_tags(arch: str) -> Iterator[str]: sys_musl = _get_musl_version(sys.executable) if sys_musl is None: # Python not dynamically linked against musl. return + if arch == "armv8l": + # armv8l wheels are not accepted on PyPI + # The armv7l wheels can be installed. + arch = "armv7l" for minor in range(sys_musl.minor, -1, -1): yield f"musllinux_{sys_musl.major}_{minor}_{arch}" diff --git a/src/packaging/tags.py b/src/packaging/tags.py index 76d24341..a9f4f01d 100644 --- a/src/packaging/tags.py +++ b/src/packaging/tags.py @@ -473,7 +473,7 @@ def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: if linux == "linux_x86_64": linux = "linux_i686" elif linux == "linux_aarch64": - linux = "linux_armv7l" + linux = "linux_armv8l" _, arch = linux.split("_", 1) yield from _manylinux.platform_tags(linux, arch) yield from _musllinux.platform_tags(arch) diff --git a/tests/test_tags.py b/tests/test_tags.py index 1ee62711..d748a8b6 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -362,7 +362,7 @@ def test_get_config_var_does_log(self, monkeypatch): ("linux-x86_64", False, "linux_x86_64"), ("linux-x86_64", True, "linux_i686"), ("linux-aarch64", False, "linux_aarch64"), - ("linux-aarch64", True, "linux_armv7l"), + ("linux-aarch64", True, "linux_armv8l"), ], ) def test_linux_platforms_32_64bit_on_64bit_os( @@ -440,14 +440,20 @@ def test_linux_platforms_manylinux2014(self, monkeypatch): ] assert platforms == expected - def test_linux_platforms_manylinux2014_armhf_abi(self, monkeypatch): + @pytest.mark.parametrize( + "native_arch, cross_arch", + [("armv7l", "armv7l"), ("armv8l", "armv8l"), ("aarch64", "armv8l")], + ) + def test_linux_platforms_manylinux2014_armhf_abi( + self, native_arch, cross_arch, monkeypatch + ): monkeypatch.setattr(tags._manylinux, "_glibc_version_string", lambda: "2.30") monkeypatch.setattr( tags._manylinux, "_is_compatible", lambda name, *args: name == "manylinux2014", ) - monkeypatch.setattr(sysconfig, "get_platform", lambda: "linux_armv7l") + monkeypatch.setattr(sysconfig, "get_platform", lambda: f"linux_{native_arch}") monkeypatch.setattr( sys, "executable", @@ -458,7 +464,7 @@ def test_linux_platforms_manylinux2014_armhf_abi(self, monkeypatch): ), ) platforms = list(tags._linux_platforms(is_32bit=True)) - expected = ["manylinux2014_armv7l", "linux_armv7l"] + expected = ["manylinux2014_armv7l", f"linux_{cross_arch}"] assert platforms == expected def test_linux_platforms_manylinux2014_i386_abi(self, monkeypatch): @@ -520,7 +526,8 @@ def test_linux_platforms_manylinux_glibc3(self, monkeypatch): @pytest.mark.parametrize( "native_arch, cross32_arch, musl_version", [ - ("aarch64", "armv7l", _MuslVersion(1, 1)), + ("armv7l", "armv7l", _MuslVersion(1, 1)), + ("aarch64", "armv8l", _MuslVersion(1, 1)), ("i386", "i386", _MuslVersion(1, 2)), ("x86_64", "i686", _MuslVersion(1, 2)), ], @@ -543,8 +550,9 @@ def test_linux_platforms_musllinux( platforms = list(tags._linux_platforms(is_32bit=cross32)) target_arch = cross32_arch if cross32 else native_arch + target_arch_musl = "armv7l" if target_arch == "armv8l" else target_arch expected = [ - f"musllinux_{musl_version[0]}_{minor}_{target_arch}" + f"musllinux_{musl_version[0]}_{minor}_{target_arch_musl}" for minor in range(musl_version[1], -1, -1) ] + [f"linux_{target_arch}"] assert platforms == expected