From a1610c794e60b7acf021e805c2d579543c00ad07 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Thu, 30 Oct 2025 09:50:26 -0500 Subject: [PATCH] Add Windows x86-32 emulation support to interpreter architecture checks (#13475) Closes https://github.com/astral-sh/uv/issues/13471 Refactors the logic there a bit too. --------- Co-authored-by: Aria Desires --- crates/uv-platform/src/lib.rs | 30 +++++++++--- crates/uv/tests/it/python_install.rs | 71 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/crates/uv-platform/src/lib.rs b/crates/uv-platform/src/lib.rs index c9adb8fb9..d0e6fdd4b 100644 --- a/crates/uv-platform/src/lib.rs +++ b/crates/uv-platform/src/lib.rs @@ -3,6 +3,7 @@ use std::cmp; use std::fmt; use std::str::FromStr; +use target_lexicon::Architecture; use thiserror::Error; use tracing::trace; @@ -91,13 +92,28 @@ impl Platform { return true; } - // Windows ARM64 runs emulated x86_64 binaries transparently - // Similarly, macOS aarch64 runs emulated x86_64 binaries transparently if you have Rosetta - // installed. We don't try to be clever and check if that's the case here, we just assume - // that if x86_64 distributions are available, they're usable. - if (self.os.is_windows() || self.os.is_macos()) - && matches!(self.arch.family(), target_lexicon::Architecture::Aarch64(_)) - && matches!(other.arch.family(), target_lexicon::Architecture::X86_64) + #[allow(clippy::unnested_or_patterns)] + if self.os.is_windows() + && matches!( + (self.arch.family(), other.arch.family()), + // 32-bit x86 binaries work fine on 64-bit x86 windows + (Architecture::X86_64, Architecture::X86_32(_)) | + // Both 32-bit and 64-bit binaries are transparently emulated on aarch64 windows + (Architecture::Aarch64(_), Architecture::X86_64) | + (Architecture::Aarch64(_), Architecture::X86_32(_)) + ) + { + return true; + } + + if self.os.is_macos() + && matches!( + (self.arch.family(), other.arch.family()), + // macOS aarch64 runs emulated x86_64 binaries transparently if you have Rosetta + // installed. We don't try to be clever and check if that's the case here, + // we just assume that if x86_64 distributions are available, they're usable. + (Architecture::Aarch64(_), Architecture::X86_64) + ) { return true; } diff --git a/crates/uv/tests/it/python_install.rs b/crates/uv/tests/it/python_install.rs index e71569a2f..f7c67a0e4 100644 --- a/crates/uv/tests/it/python_install.rs +++ b/crates/uv/tests/it/python_install.rs @@ -2765,6 +2765,77 @@ fn python_install_emulated_macos() { "); } +#[cfg(all(target_os = "windows", target_arch = "x86_64"))] +#[test] +fn python_install_emulated_windows_x86_on_x64() { + let context: TestContext = TestContext::new_with_versions(&[]) + .with_filtered_exe_suffix() + .with_managed_python_dirs() + .with_python_download_cache(); + + // Before installation, `uv python list` should not show the x86_32 download + uv_snapshot!(context.filters(), context.python_list().arg("3.13"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.13.9-windows-x86_64-none + + ----- stderr ----- + "); + + // Install an x86_32 version (assuming an x64 host) + uv_snapshot!(context.filters(), context.python_install().arg("3.13-x86"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Installed Python 3.13.9 in [TIME] + + cpython-3.13.9-windows-x86-none (python3.13) + "); + + // It should be discoverable with `uv python find` + uv_snapshot!(context.filters(), context.python_find().arg("3.13"), @r" + success: true + exit_code: 0 + ----- stdout ----- + [TEMP_DIR]/managed/cpython-3.13.9-windows-x86-none/python + + ----- stderr ----- + "); + + // And included in `uv python list` + uv_snapshot!(context.filters(), context.python_list().arg("3.13"), @r" + success: true + exit_code: 0 + ----- stdout ----- + cpython-3.13.9-windows-x86_64-none + cpython-3.13.9-windows-x86-none managed/cpython-3.13.9-windows-x86-none/python + + ----- stderr ----- + "); + + uv_snapshot!(context.filters(), context.python_install().arg("3.13-x86_64"), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Installed Python 3.13.9 in [TIME] + + cpython-3.13.9-windows-x86_64-none + "); + + // Once we've installed the native version, it should be preferred over x86_32 + uv_snapshot!(context.filters(), context.python_find().arg("3.13"), @r" + success: true + exit_code: 0 + ----- stdout ----- + [TEMP_DIR]/managed/cpython-3.13.9-windows-x86_64-none/python + + ----- stderr ----- + "); +} + // A virtual environment should track the latest patch version installed. #[test] fn install_transparent_patch_upgrade_uv_venv() {