diff --git a/src/auditwheel/audit.rs b/src/auditwheel/audit.rs index b2ee74a89..3d69f1431 100644 --- a/src/auditwheel/audit.rs +++ b/src/auditwheel/audit.rs @@ -2,7 +2,7 @@ use super::musllinux::{find_musl_libc, get_musl_version}; use super::policy::{MANYLINUX_POLICIES, MUSLLINUX_POLICIES, Policy}; use crate::auditwheel::{PlatformTag, find_external_libs}; use crate::compile::BuildArtifact; -use crate::target::Target; +use crate::target::{Arch, Target}; use anyhow::{Context, Result, bail}; use fs_err::File; use goblin::elf::{Elf, sym::STB_WEAK, sym::STT_FUNC}; @@ -405,6 +405,10 @@ pub fn auditwheel_rs( } } else if let Some(policy) = highest_policy { Ok(policy) + } else if target.target_arch() == Arch::Armv6L || target.target_arch() == Arch::Armv7L { + // Old arm versions + // https://github.com/pypi/warehouse/blob/556e1e3390999381c382873b003a779a1363cb4d/warehouse/forklift/legacy.py#L122-L123 + Ok(Policy::default()) } else { eprintln!( "⚠️ Warning: No compatible platform tag found, using the linux tag instead. \ diff --git a/src/build_options.rs b/src/build_options.rs index 20e56bae9..34050f34b 100644 --- a/src/build_options.rs +++ b/src/build_options.rs @@ -769,7 +769,7 @@ impl BuildContextBuilder { } else if let [PlatformTag::Pypi] = &build_options.platform_tag[..] { // Avoid building for architectures we already know aren't allowed on PyPI if !is_arch_supported_by_pypi(&target) { - bail!("Target {} architecture is not supported by PyPI", target); + bail!("Rust target {} is not supported by PyPI", target); } // The defaults are already targeting PyPI: manylinux on linux, // and the native tag on windows and mac diff --git a/src/target/mod.rs b/src/target/mod.rs index f3d4364d8..8838d84a5 100644 --- a/src/target/mod.rs +++ b/src/target/mod.rs @@ -99,33 +99,39 @@ pub enum Arch { LoongArch64, } -impl fmt::Display for Arch { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl Arch { + pub fn as_str(&self) -> &str { match *self { - Arch::Aarch64 => write!(f, "aarch64"), - Arch::Armv5teL => write!(f, "armv5tel"), - Arch::Armv6L => write!(f, "armv6l"), - Arch::Armv7L => write!(f, "armv7l"), - Arch::Powerpc => write!(f, "ppc"), - Arch::Powerpc64Le => write!(f, "ppc64le"), - Arch::Powerpc64 => write!(f, "ppc64"), - Arch::X86 => write!(f, "i686"), - Arch::X86_64 => write!(f, "x86_64"), - Arch::S390X => write!(f, "s390x"), - Arch::Wasm32 => write!(f, "wasm32"), - Arch::Riscv32 => write!(f, "riscv32"), - Arch::Riscv64 => write!(f, "riscv64"), - Arch::Mips64el => write!(f, "mips64el"), - Arch::Mips64 => write!(f, "mips64"), - Arch::Mipsel => write!(f, "mipsel"), - Arch::Mips => write!(f, "mips"), - Arch::Sparc64 => write!(f, "sparc64"), - Arch::Sparcv9 => write!(f, "sparcv9"), - Arch::LoongArch64 => write!(f, "loongarch64"), + Arch::Aarch64 => "aarch64", + Arch::Armv5teL => "armv5tel", + Arch::Armv6L => "armv6l", + Arch::Armv7L => "armv7l", + Arch::Powerpc => "ppc", + Arch::Powerpc64Le => "ppc64le", + Arch::Powerpc64 => "ppc64", + Arch::X86 => "i686", + Arch::X86_64 => "x86_64", + Arch::S390X => "s390x", + Arch::Wasm32 => "wasm32", + Arch::Riscv32 => "riscv32", + Arch::Riscv64 => "riscv64", + Arch::Mips64el => "mips64el", + Arch::Mips64 => "mips64", + Arch::Mipsel => "mipsel", + Arch::Mips => "mips", + Arch::Sparc64 => "sparc64", + Arch::Sparcv9 => "sparcv9", + Arch::LoongArch64 => "loongarch64", } } } +impl fmt::Display for Arch { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.as_str()) + } +} + impl Arch { /// Represents the hardware platform. /// diff --git a/src/target/pypi_tags.rs b/src/target/pypi_tags.rs index 176cc12ff..9914ad1e7 100644 --- a/src/target/pypi_tags.rs +++ b/src/target/pypi_tags.rs @@ -23,23 +23,31 @@ use crate::target::legacy_py::{ LINUX_PLATFORM_RE, MACOS_ARCHES, MACOS_MAJOR_VERSIONS, MACOS_PLATFORM_RE, MANYLINUX_ARCHES, MUSLLINUX_ARCHES, WINDOWS_ARCHES, }; -use crate::target::{Os, Target}; +use crate::target::{Arch, Os, Target}; use anyhow::{Result, anyhow, bail}; use target_lexicon::Environment; /// Check for target architectures that we know aren't supported by PyPI to error early. pub fn is_arch_supported_by_pypi(target: &Target) -> bool { - let arch = target.target_arch().to_string(); + let arch = target.target_arch(); match target.target_os() { Os::Windows => WINDOWS_ARCHES.contains(&arch.as_str()), Os::Macos => { // macOS uses arm64 in platform tags, but target triple uses aarch64 - let normalized_arch = if arch == "aarch64" { "arm64" } else { &arch }; + let normalized_arch = if arch == Arch::Aarch64 { + "arm64" + } else { + arch.as_str() + }; MACOS_ARCHES.contains(&normalized_arch) } Os::Ios => { // iOS uses arm64 in platform tags, but target triple uses aarch64 - let normalized_arch = if arch == "aarch64" { "arm64" } else { &arch }; + let normalized_arch = if arch == Arch::Aarch64 { + "arm64" + } else { + arch.as_str() + }; // PyPI allows iOS with arm64 and x86_64 (simulator) matches!(normalized_arch, "arm64" | "x86_64") } @@ -54,23 +62,25 @@ pub fn is_arch_supported_by_pypi(target: &Target) -> bool { }; ANDROID_ARCHES.contains(&android_arch) } - Os::Linux => match target.target_env() { - Environment::Gnu - | Environment::Gnuabi64 - | Environment::Gnueabi - | Environment::Gnueabihf => { - let arch1 = arch.as_str(); - MANYLINUX_ARCHES.contains(&arch1) + Os::Linux => { + // Old arm versions + // https://github.com/pypi/warehouse/blob/556e1e3390999381c382873b003a779a1363cb4d/warehouse/forklift/legacy.py#L122-L123 + if arch == Arch::Armv6L || arch == Arch::Armv7L { + return true; } - Environment::Musl - | Environment::Musleabi - | Environment::Musleabihf - | Environment::Muslabi64 => { - let arch1 = arch.as_str(); - MUSLLINUX_ARCHES.contains(&arch1) + + match target.target_env() { + Environment::Gnu + | Environment::Gnuabi64 + | Environment::Gnueabi + | Environment::Gnueabihf => MANYLINUX_ARCHES.contains(&arch.as_str()), + Environment::Musl + | Environment::Musleabi + | Environment::Musleabihf + | Environment::Muslabi64 => MUSLLINUX_ARCHES.contains(&arch.as_str()), + _ => false, } - _ => false, - }, + } _ => false, } } @@ -105,6 +115,12 @@ fn is_platform_tag_allowed_by_pypi(platform_tag: &str) -> bool { }; } + // Old arm versions + // https://github.com/pypi/warehouse/blob/556e1e3390999381c382873b003a779a1363cb4d/warehouse/forklift/legacy.py#L122-L123 + if platform_tag == "linux_armv6l" || platform_tag == "linux_armv7l" { + return true; + } + // iOS if let Some(captures) = IOS_PLATFORM_RE.captures(platform_tag) { let arch = captures.name("arch").unwrap().as_str(); @@ -176,6 +192,10 @@ mod tests { // musllinux platforms ("musllinux_1_1_x86_64", true), ("musllinux_1_1_riscv64", false), + // Old arm versions + // https://github.com/pypi/warehouse/blob/556e1e3390999381c382873b003a779a1363cb4d/warehouse/forklift/legacy.py#L122-L123 + ("linux_armv6l", true), + ("linux_armv7l", true), // macOS platforms ("macosx_9_0_x86_64", false), // Invalid major version ("macosx_10_9_x86_64", true), diff --git a/tests/common/errors.rs b/tests/common/errors.rs index fa32505df..5478f0274 100644 --- a/tests/common/errors.rs +++ b/tests/common/errors.rs @@ -178,9 +178,7 @@ pub fn pypi_compatibility_unsupported_target() -> Result<()> { if let Err(err) = result { let err_string = err.to_string(); assert!( - err_string.contains( - "Target riscv32gc-unknown-linux-gnu architecture is not supported by PyPI" - ), + err_string.contains("Rust target riscv32gc-unknown-linux-gnu is not supported by PyPI"), "{err_string}", ); } else {