From fdebc0c7fdcc274052ed27e9b2479e0ac371a4f6 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 19 Feb 2025 12:01:46 -0600 Subject: [PATCH] Allow use of x86-64 Python on ARM Windows (#11625) Closes https://github.com/astral-sh/uv/issues/11493 --- crates/uv-python/src/downloads.rs | 14 ++++++++------ crates/uv-python/src/managed.rs | 6 +++++- crates/uv-python/src/platform.rs | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/crates/uv-python/src/downloads.rs b/crates/uv-python/src/downloads.rs index d26635f69..8c158b9c1 100644 --- a/crates/uv-python/src/downloads.rs +++ b/crates/uv-python/src/downloads.rs @@ -250,18 +250,20 @@ impl PythonDownloadRequest { .filter(move |download| self.satisfied_by_download(download)) } - /// Whether this request is satisfied by the key of an existing installation. + /// Whether this request is satisfied by an installation key. pub fn satisfied_by_key(&self, key: &PythonInstallationKey) -> bool { - if let Some(arch) = &self.arch { - if key.arch != *arch { - return false; - } - } if let Some(os) = &self.os { if key.os != *os { return false; } } + + if let Some(arch) = &self.arch { + if !arch.supports(key.arch) { + return false; + } + } + if let Some(libc) = &self.libc { if key.libc != *libc { return false; diff --git a/crates/uv-python/src/managed.rs b/crates/uv-python/src/managed.rs index 885f92cb1..72b43180c 100644 --- a/crates/uv-python/src/managed.rs +++ b/crates/uv-python/src/managed.rs @@ -250,7 +250,10 @@ impl ManagedPythonInstallations { .find_all()? .filter(move |installation| { installation.key.os == os - && installation.key.arch.family == arch.family + && (arch.supports(installation.key.arch) + // TODO(zanieb): Allow inequal variants, as `Arch::supports` does not + // implement this yet. See https://github.com/astral-sh/uv/pull/9788 + || arch.family == installation.key.arch.family) && installation.key.libc == libc }); @@ -665,6 +668,7 @@ impl ManagedPythonInstallation { } } +// TODO(zanieb): Only used in tests now. /// Generate a platform portion of a key from the environment. pub fn platform_key_from_env() -> Result { let os = Os::from_env(); diff --git a/crates/uv-python/src/platform.rs b/crates/uv-python/src/platform.rs index 7ebc892c8..18f6d59e3 100644 --- a/crates/uv-python/src/platform.rs +++ b/crates/uv-python/src/platform.rs @@ -103,6 +103,26 @@ impl Arch { } } + /// Does the current architecture support running the other? + /// + /// When the architecture is equal, this is always true. Otherwise, this is true if the + /// architecture is transparently emulated or is a microarchitecture with worse performance + /// characteristics. + pub(crate) fn supports(self, other: Self) -> bool { + if self == other { + return true; + } + + // TODO: Implement `variant` support checks + + // Windows ARM64 runs emulated x86_64 binaries transparently + if cfg!(windows) && matches!(self.family, target_lexicon::Architecture::Aarch64(_)) { + return other.family == target_lexicon::Architecture::X86_64; + } + + false + } + pub fn family(&self) -> target_lexicon::Architecture { self.family }