From 3aa8faa0b4d688576a0db90c52fb02aee70de966 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 13:05:13 +0000 Subject: [PATCH 1/4] feat: use pixi's default virtual package versions for cross-platform solves When detecting virtual packages for a platform other than the current one, __linux, __glibc, __osx and __win previously fell back to version 0, which causes solves to pick packages that don't match any realistic system. Use the same defaults as pixi instead (linux 4.18, glibc 2.28, macOS 13.0, Windows 10.0), exposed in a new rattler_virtual_packages::defaults module. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K --- .../rattler_virtual_packages/src/defaults.rs | 39 ++++++++++ crates/rattler_virtual_packages/src/lib.rs | 78 ++++++++++++++----- 2 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 crates/rattler_virtual_packages/src/defaults.rs diff --git a/crates/rattler_virtual_packages/src/defaults.rs b/crates/rattler_virtual_packages/src/defaults.rs new file mode 100644 index 0000000000..8e39a0624b --- /dev/null +++ b/crates/rattler_virtual_packages/src/defaults.rs @@ -0,0 +1,39 @@ +//! Default virtual package versions to use when the actual version cannot be +//! detected from the host system, for example when detecting virtual packages +//! for a platform other than the current one (see +//! [`crate::VirtualPackages::detect_for_platform`]). +//! +//! The values match the defaults used by +//! [pixi](https://github.com/prefix-dev/pixi) when no system requirements are +//! specified. + +use rattler_conda_types::{Platform, Version}; + +/// The default `glibc` version to use when the version cannot be detected. +/// +/// This is the `glibc` version that ships with RHEL 8 and Debian 10. +pub fn default_glibc_version() -> Version { + "2.28".parse().unwrap() +} + +/// The default Linux kernel version to use when the version cannot be +/// detected. +/// +/// This is the kernel version that ships with RHEL 8. +pub fn default_linux_version() -> Version { + "4.18".parse().unwrap() +} + +/// The default Windows version to use when the version cannot be detected. +pub fn default_windows_version() -> Version { + "10.0".parse().unwrap() +} + +/// Returns the default macOS version to use when the version cannot be +/// detected, or `None` if the given platform is not a macOS platform. +pub fn default_mac_os_version(platform: Platform) -> Option { + match platform { + Platform::Osx64 | Platform::OsxArm64 => Some("13.0".parse().unwrap()), + _ => None, + } +} diff --git a/crates/rattler_virtual_packages/src/lib.rs b/crates/rattler_virtual_packages/src/lib.rs index dc9f3b6c7d..107bd3addf 100644 --- a/crates/rattler_virtual_packages/src/lib.rs +++ b/crates/rattler_virtual_packages/src/lib.rs @@ -33,6 +33,7 @@ //! example. pub mod cuda; +pub mod defaults; pub mod libc; pub mod linux; pub mod osx; @@ -307,14 +308,15 @@ impl VirtualPackages { /// # Cross-compilation defaults /// /// When cross-compiling (targeting a platform different from the current one), the following - /// defaults are used if no override is provided: + /// defaults are used if no override is provided (see the [`defaults`] module, the versions + /// match the defaults used by pixi): /// - /// - **Windows** (`__win`): No version specified - /// - **Linux** (`__linux`): Version 0 - /// - **OSX** (`__osx`): Version 0 + /// - **Windows** (`__win`): Version 10.0 + /// - **Linux** (`__linux`): Version 4.18 + /// - **OSX** (`__osx`): Version 13.0 /// - **iOS** (`__ios`): Version 0 (minimum supported iOS version) /// - **Android** (`__android`): Version 0 (minimum supported API level) - /// - **`LibC`** (`__glibc`): `glibc` with version 0 (only for Linux platforms) + /// - **`LibC`** (`__glibc`): `glibc` with version 2.28 (only for Linux platforms) /// - **CUDA** (`__cuda`): Not included (None) /// - **Archspec**: Platform-specific minimal architecture (e.g., `x86_64` for `osx-64`) pub fn detect_for_platform( @@ -328,10 +330,12 @@ impl VirtualPackages { } else { // When cross-compiling, respect overrides but fall back to defaults let win = if platform.is_windows() { - // Check override first, fall back to default (no version) - virtual_packages - .win - .or_else(|| Some(Windows { version: None })) + // Check override first, fall back to the default version + virtual_packages.win.or_else(|| { + Some(Windows { + version: Some(defaults::default_windows_version()), + }) + }) } else { None }; @@ -339,7 +343,7 @@ impl VirtualPackages { let linux = if platform.is_linux() { virtual_packages.linux.or_else(|| { Some(Linux { - version: Version::major(0), + version: defaults::default_linux_version(), }) }) } else { @@ -347,12 +351,10 @@ impl VirtualPackages { }; let osx = if platform.is_osx() { - // Check override first, fall back to version 0 - virtual_packages.osx.or_else(|| { - Some(Osx { - version: Version::major(0), - }) - }) + // Check override first, fall back to the default version + virtual_packages + .osx + .or_else(|| defaults::default_mac_os_version(platform).map(Osx::from)) } else { None }; @@ -380,11 +382,11 @@ impl VirtualPackages { }; let libc = if platform.is_linux() { - // Check override first, fall back to glibc 0 + // Check override first, fall back to the default glibc version virtual_packages.libc.or_else(|| { Some(LibC { family: "glibc".into(), - version: Version::major(0), + version: defaults::default_glibc_version(), }) }) } else { @@ -1428,6 +1430,46 @@ mod test { assert!(win_names.contains(&"__archspec".to_string())); } + #[test] + fn test_cross_platform_default_versions() { + // When targeting a platform whose virtual packages cannot be detected + // on the host, the pixi default versions are used instead of 0. The + // host's own platform family is skipped because there the detected + // (host) versions take precedence over the defaults. + let overrides = VirtualPackageOverrides::default(); + let current = Platform::current(); + + if !current.is_linux() { + let packages = + VirtualPackages::detect_for_platform(Platform::Linux64, &overrides).unwrap(); + assert_eq!( + packages.linux.expect("__linux should be present").version, + defaults::default_linux_version() + ); + let libc = packages.libc.expect("__glibc should be present"); + assert_eq!(libc.family, "glibc"); + assert_eq!(libc.version, defaults::default_glibc_version()); + } + + if !current.is_osx() { + let packages = + VirtualPackages::detect_for_platform(Platform::OsxArm64, &overrides).unwrap(); + assert_eq!( + packages.osx.expect("__osx should be present").version, + defaults::default_mac_os_version(Platform::OsxArm64).unwrap() + ); + } + + if !current.is_windows() { + let packages = + VirtualPackages::detect_for_platform(Platform::Win64, &overrides).unwrap(); + assert_eq!( + packages.win.expect("__win should be present").version, + Some(defaults::default_windows_version()) + ); + } + } + #[test] fn test_ios_android_virtual_packages() { // Cross-compiling to an ios-* subdir yields __ios (falling back to From 8111cf5c918eee5e5bfbb244f939e63b8d78a3a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 14:50:12 +0000 Subject: [PATCH 2/4] feat: log assumed default virtual package versions When detect_for_platform falls back to a default version for __win, __linux, __osx or __glibc, emit an info-level tracing message telling the user which version is assumed and which CONDA_OVERRIDE_* variable overrides it. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K --- crates/rattler_virtual_packages/src/lib.rs | 56 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/crates/rattler_virtual_packages/src/lib.rs b/crates/rattler_virtual_packages/src/lib.rs index 107bd3addf..54a24c5bc7 100644 --- a/crates/rattler_virtual_packages/src/lib.rs +++ b/crates/rattler_virtual_packages/src/lib.rs @@ -332,8 +332,15 @@ impl VirtualPackages { let win = if platform.is_windows() { // Check override first, fall back to the default version virtual_packages.win.or_else(|| { + let version = defaults::default_windows_version(); + log_default_virtual_package( + "__win", + platform, + &version, + Windows::DEFAULT_ENV_NAME, + ); Some(Windows { - version: Some(defaults::default_windows_version()), + version: Some(version), }) }) } else { @@ -342,9 +349,14 @@ impl VirtualPackages { let linux = if platform.is_linux() { virtual_packages.linux.or_else(|| { - Some(Linux { - version: defaults::default_linux_version(), - }) + let version = defaults::default_linux_version(); + log_default_virtual_package( + "__linux", + platform, + &version, + Linux::DEFAULT_ENV_NAME, + ); + Some(Linux { version }) }) } else { None @@ -352,9 +364,17 @@ impl VirtualPackages { let osx = if platform.is_osx() { // Check override first, fall back to the default version - virtual_packages - .osx - .or_else(|| defaults::default_mac_os_version(platform).map(Osx::from)) + virtual_packages.osx.or_else(|| { + defaults::default_mac_os_version(platform).map(|version| { + log_default_virtual_package( + "__osx", + platform, + &version, + Osx::DEFAULT_ENV_NAME, + ); + Osx { version } + }) + }) } else { None }; @@ -384,9 +404,16 @@ impl VirtualPackages { let libc = if platform.is_linux() { // Check override first, fall back to the default glibc version virtual_packages.libc.or_else(|| { + let version = defaults::default_glibc_version(); + log_default_virtual_package( + "__glibc", + platform, + &version, + LibC::DEFAULT_ENV_NAME, + ); Some(LibC { family: "glibc".into(), - version: defaults::default_glibc_version(), + version, }) }) } else { @@ -417,6 +444,19 @@ impl VirtualPackages { } } +/// Logs that the version of a virtual package could not be detected for the +/// target platform and that a default version is assumed instead. +fn log_default_virtual_package( + name: &str, + platform: Platform, + version: &Version, + env_var_name: &str, +) { + tracing::info!( + "cannot detect the version of the virtual package '{name}' when targeting '{platform}', assuming version {version}; set the {env_var_name} environment variable to override" + ); +} + impl From for GenericVirtualPackage { fn from(package: VirtualPackage) -> Self { match package { From eff8c5222756d81c0acb2d439644e5d4d4c2b894 Mon Sep 17 00:00:00 2001 From: Pavel Zwerschke Date: Wed, 5 Aug 2026 16:52:33 +0200 Subject: [PATCH 3/4] Update crates/rattler_virtual_packages/src/defaults.rs --- crates/rattler_virtual_packages/src/defaults.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/rattler_virtual_packages/src/defaults.rs b/crates/rattler_virtual_packages/src/defaults.rs index 8e39a0624b..63d149d9fc 100644 --- a/crates/rattler_virtual_packages/src/defaults.rs +++ b/crates/rattler_virtual_packages/src/defaults.rs @@ -2,10 +2,6 @@ //! detected from the host system, for example when detecting virtual packages //! for a platform other than the current one (see //! [`crate::VirtualPackages::detect_for_platform`]). -//! -//! The values match the defaults used by -//! [pixi](https://github.com/prefix-dev/pixi) when no system requirements are -//! specified. use rattler_conda_types::{Platform, Version}; From 7333876672e2e2c6aa2f8b714a581e9e767c3da6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 06:55:08 +0000 Subject: [PATCH 4/4] docs: link cross-compilation defaults to the defaults module Reference the defaults::default_*_version functions instead of hardcoding the version numbers in the detect_for_platform docs so they cannot go out of date. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K --- crates/rattler_virtual_packages/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/rattler_virtual_packages/src/lib.rs b/crates/rattler_virtual_packages/src/lib.rs index 54a24c5bc7..915b28b7d7 100644 --- a/crates/rattler_virtual_packages/src/lib.rs +++ b/crates/rattler_virtual_packages/src/lib.rs @@ -308,15 +308,15 @@ impl VirtualPackages { /// # Cross-compilation defaults /// /// When cross-compiling (targeting a platform different from the current one), the following - /// defaults are used if no override is provided (see the [`defaults`] module, the versions - /// match the defaults used by pixi): + /// defaults are used if no override is provided (see the [`defaults`] module): /// - /// - **Windows** (`__win`): Version 10.0 - /// - **Linux** (`__linux`): Version 4.18 - /// - **OSX** (`__osx`): Version 13.0 + /// - **Windows** (`__win`): [`defaults::default_windows_version`] + /// - **Linux** (`__linux`): [`defaults::default_linux_version`] + /// - **OSX** (`__osx`): [`defaults::default_mac_os_version`] /// - **iOS** (`__ios`): Version 0 (minimum supported iOS version) /// - **Android** (`__android`): Version 0 (minimum supported API level) - /// - **`LibC`** (`__glibc`): `glibc` with version 2.28 (only for Linux platforms) + /// - **`LibC`** (`__glibc`): `glibc` with [`defaults::default_glibc_version`] (only for Linux + /// platforms) /// - **CUDA** (`__cuda`): Not included (None) /// - **Archspec**: Platform-specific minimal architecture (e.g., `x86_64` for `osx-64`) pub fn detect_for_platform(