From e547527587fc47d3c83b200afa0d6bd15897081a Mon Sep 17 00:00:00 2001 From: Nathan Cain <13713501+nathanscain@users.noreply.github.com> Date: Wed, 16 Jul 2025 08:52:17 -0500 Subject: [PATCH] Add UV_LIBC to allow libc selection in multi-libc environment (#14646) Closes #14262 ## Description Adds `UV_LIBC` environment variable and implements check within `Libc::from_env` as recommended here: https://github.com/astral-sh/uv/issues/14262#issuecomment-3014600313 Gave this a few passes to make sure I follow dev practices within uv as best I am able. Feel free to call out anything that could be improved. ## Test Plan Planned to simply run existing test suite. Open to adding more tests once implementation is validated due to my limited Rust experience. --- crates/uv-python/src/platform.rs | 42 +++++++++++++++++++++----------- crates/uv-static/src/env_vars.rs | 4 +++ docs/reference/environment.md | 5 ++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/crates/uv-python/src/platform.rs b/crates/uv-python/src/platform.rs index ce8620ae2..606e05e28 100644 --- a/crates/uv-python/src/platform.rs +++ b/crates/uv-python/src/platform.rs @@ -5,6 +5,8 @@ use std::ops::Deref; use std::{fmt, str::FromStr}; use thiserror::Error; +use uv_static::EnvVars; + #[derive(Error, Debug)] pub enum Error { #[error("Unknown operating system: {0}")] @@ -15,6 +17,8 @@ pub enum Error { UnknownLibc(String), #[error("Unsupported variant `{0}` for architecture `{1}`")] UnsupportedVariant(String, String), + #[error(transparent)] + LibcDetectionError(#[from] LibcDetectionError), } /// Architecture variants, e.g., with support for different instruction sets @@ -95,22 +99,32 @@ pub enum Libc { } impl Libc { - pub(crate) fn from_env() -> Result { + pub(crate) fn from_env() -> Result { match std::env::consts::OS { - "linux" => Ok(Self::Some(match detect_linux_libc()? { - LibcVersion::Manylinux { .. } => match std::env::consts::ARCH { - // Checks if the CPU supports hardware floating-point operations. - // Depending on the result, it selects either the `gnueabihf` (hard-float) or `gnueabi` (soft-float) environment. - // download-metadata.json only includes armv7. - "arm" | "armv5te" | "armv7" => match detect_hardware_floating_point_support() { - Ok(true) => target_lexicon::Environment::Gnueabihf, - Ok(false) => target_lexicon::Environment::Gnueabi, - Err(_) => target_lexicon::Environment::Gnu, + "linux" => { + if let Ok(libc) = std::env::var(EnvVars::UV_LIBC) { + if !libc.is_empty() { + return Self::from_str(&libc); + } + } + + Ok(Self::Some(match detect_linux_libc()? { + LibcVersion::Manylinux { .. } => match std::env::consts::ARCH { + // Checks if the CPU supports hardware floating-point operations. + // Depending on the result, it selects either the `gnueabihf` (hard-float) or `gnueabi` (soft-float) environment. + // download-metadata.json only includes armv7. + "arm" | "armv5te" | "armv7" => { + match detect_hardware_floating_point_support() { + Ok(true) => target_lexicon::Environment::Gnueabihf, + Ok(false) => target_lexicon::Environment::Gnueabi, + Err(_) => target_lexicon::Environment::Gnu, + } + } + _ => target_lexicon::Environment::Gnu, }, - _ => target_lexicon::Environment::Gnu, - }, - LibcVersion::Musllinux { .. } => target_lexicon::Environment::Musl, - })), + LibcVersion::Musllinux { .. } => target_lexicon::Environment::Musl, + })) + } "windows" | "macos" => Ok(Self::None), // Use `None` on platforms without explicit support. _ => Ok(Self::None), diff --git a/crates/uv-static/src/env_vars.rs b/crates/uv-static/src/env_vars.rs index 5b91fccea..ae981cac3 100644 --- a/crates/uv-static/src/env_vars.rs +++ b/crates/uv-static/src/env_vars.rs @@ -154,6 +154,10 @@ impl EnvVars { /// `--no-python-downloads` option. Whether uv should allow Python downloads. pub const UV_PYTHON_DOWNLOADS: &'static str = "UV_PYTHON_DOWNLOADS"; + /// Overrides the environment-determined libc on linux systems when filling in the current platform + /// within Python version requests. Options are: `gnu`, `gnueabi`, `gnueabihf`, `musl`, and `none`. + pub const UV_LIBC: &'static str = "UV_LIBC"; + /// Equivalent to the `--compile-bytecode` command-line argument. If set, uv /// will compile Python source files to bytecode after installation. pub const UV_COMPILE_BYTECODE: &'static str = "UV_COMPILE_BYTECODE"; diff --git a/docs/reference/environment.md b/docs/reference/environment.md index bf8bf29ec..47e4d8db9 100644 --- a/docs/reference/environment.md +++ b/docs/reference/environment.md @@ -167,6 +167,11 @@ Defaults to `~/.local/bin`. Equivalent to the `--keyring-provider` command-line argument. If set, uv will use this value as the keyring provider. +### `UV_LIBC` + +Overrides the environment-determined libc on linux systems when filling in the current platform +within Python version requests. Options are: `gnu`, `gnueabi`, `gnueabihf`, `musl`, and `none`. + ### `UV_LINK_MODE` Equivalent to the `--link-mode` command-line argument. If set, uv will use this as