Skip to content

feat: Introduce default versions for virtual packages - #2646

Merged
baszalmstra merged 6 commits into
mainfrom
claude/rattler-virtual-packages-defaults-s4r13b
Aug 6, 2026
Merged

baszalmstra merged 6 commits into
mainfrom
claude/rattler-virtual-packages-defaults-s4r13b

Conversation

@pavelzw

@pavelzw pavelzw commented Aug 5, 2026 •

Copy link
Copy Markdown
Member

i noticed that rattler solve --platform <different-platform-than-host> results in __linux=0=0 which leads to weird solving errors by default. wdyt about having default versions?

❯ rattler solve rattler --platform linux-64 python
Solving for platform: linux-64
Loaded 3247 records in 61.649958ms
Virtual packages:
  - __unix=0=0
  - __linux=0=0
  - __glibc=0=0
  - __archspec=1=x86_64

Error:   × Cannot solve the request because of: rattler * cannot be installed because there are no viable options:
  │ └─ rattler 0.1.0 | 0.1.1 | ... | 0.2.7 would require
  │    └─ __glibc >=2.17,<3.0.a0, for which no candidates were found.
  │

prompt

rattler solve uses wrong virtual packages by default when doing cross-platform solves.

❯ rattler solve pnpm --platform linux-64
Solving for platform: linux-64
Loaded 4061 records in 215.789625ms
Virtual packages:
  - __unix=0=0
  - __linux=0=0
  - __glibc=0=0
  - __archspec=1=x86_64


it should specify certain versions by default, for example for __linux and __glibc.
pixi does that already, can you fetch those default versions there and put them into rattler somewhere and use them here?

i think we could use those versions in pixi as well in their defaults, wdyt?

🤖 yap

Description

This PR introduces a new defaults module that provides default virtual package versions matching those used by pixi when detecting packages for platforms other than the current host. Previously, cross-compilation would use hardcoded version 0 for most packages, which doesn't reflect real-world defaults.

Changes:

  • Added crates/rattler_virtual_packages/src/defaults.rs with functions for default versions:
    • default_glibc_version() → 2.28 (RHEL 8 / Debian 10)
    • default_linux_version() → 4.18 (RHEL 8 kernel)
    • default_windows_version() → 10.0
    • default_mac_os_version() → 13.0 (for macOS platforms)
  • Updated VirtualPackages::detect_for_platform() to use these defaults instead of hardcoded zeros
  • Updated documentation to reference the new defaults module and clarify version behavior
  • Added comprehensive test test_cross_platform_default_versions() to verify defaults are applied correctly when cross-compiling

The defaults now align with pixi's behavior, ensuring consistent virtual package resolution across tools in the conda ecosystem.

How Has This Been Tested?

  • Added unit test test_cross_platform_default_versions() that verifies:
    • Linux defaults (kernel 4.18, glibc 2.28) are used when targeting Linux from non-Linux platforms
    • macOS default (13.0) is used when targeting macOS from non-macOS platforms
    • Windows default (10.0) is used when targeting Windows from non-Windows platforms
    • Host platform detection takes precedence (test skips checks for current platform)
  • Existing tests continue to pass

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added sufficient tests to cover my changes

https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K

…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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K
@pavelzw pavelzw changed the title Use pixi default versions for cross-platform virtual packages feat: Introduce default versions for virtual packages Aug 5, 2026
// Check override first, fall back to default (no version)
virtual_packages
.win
.or_else(|| Some(Windows { version: None }))

@pavelzw pavelzw Aug 5, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this None before while in all other places we used 0? maybe we should make it non-optional?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@baszalmstra do you have opinions on this?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont remember no. I think it might be because the version was added later.

@pavelzw
pavelzw marked this pull request as ready for review August 5, 2026 14:10
@pavelzw
pavelzw requested a review from baszalmstra August 5, 2026 14:20
@baszalmstra

Copy link
Copy Markdown
Collaborator

How does this actually work in conda/conda?

@pavelzw

pavelzw commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

is there a conda command for things like cross-platform solves?

@baszalmstra

baszalmstra commented Aug 5, 2026 •

Copy link
Copy Markdown
Collaborator

That, my friend, is a gooood question!

@pavelzw

pavelzw commented Aug 5, 2026 •

Copy link
Copy Markdown
Member Author

seems like they also have =0=0 cross-platform. probably nobody noticed this bug because they don't do as many cross-solves?

🤖 yap

prompt:

❯ take a look at the discussion in https://github.com/conda/rattler/pull/2646. can you find an answer for bas's question?
⏺ I read conda's source directly (didn't execute anything). Here's the answer to Bas's two questions.

  Is there a conda command for cross-platform solves?

  Yes: --platform / --subdir, but only on conda create and conda env create (conda/cli/helpers.py:589, wired in main_create.py:94 and main_env_create.py:107). There's no conda solve; the equivalent of
  rattler solve is:

  conda create --platform linux-64 --dry-run -n throwaway python

  CONDA_SUBDIR=linux-64 works globally too, and --platform also exists on conda export and conda search.

  How does it actually work in conda/conda?

  conda has no default versions. It deliberately does the opposite of what this PR proposes — it emits version 0 and pushes the burden onto the user via CONDA_OVERRIDE_*:

  - __linux: linux_version() returns None when the host isn't Linux → __linux=0=0 (conda/plugins/virtual_packages/linux.py:22-28). Asserted in tests/plugins/test_virtual_packages.py:221-238: assert
  prec.version == "0".
  - __osx / __win: same pattern, same 0 (osx.py:17-23, windows.py:17-23), asserted at test_virtual_packages.py:271-300.
  - __archspec: not subdir-gated at all — always reports the host CPU.

  And the docs state cross-OS solving is explicitly not supported outside --dry-run (docs/source/user-guide/tasks/manage-environments.rst:177-185):

  ▎ This flag also allows specifying a different OS […] but we don't recommend its usage outside of --dry-run operations. Common problems […] The environment cannot be solved because virtual packages are
  ▎ missing. You can workaround this issue by exporting the necessary CONDA_OVERRIDE_**** environment variables. For example, solving for Linux from macOS, you will probably need CONDA_OVERRIDE_LINUX=1 and
  ▎ CONDA_OVERRIDE_GLIBC=2.17.

  So: conda's position is "cross-OS solves are user-driven, set the overrides yourself." The pixi defaults (glibc 2.28, kernel 4.18, …) are a pixi invention with no conda blessing — which is the real
  substance of Bas's question. Nothing upstream to copy from.

  One thing worth flagging on that doc quote

  The docs say __glibc is missing, and that used to be true. Pre-refactor (9f2de6c40^) the code was:

  libc_version = os.getenv(f"CONDA_OVERRIDE_{libc_family.upper()}", libc_version)
  if libc_version:
      yield CondaVirtualPackage(libc_family, libc_version, None)

  On a non-Linux host linux_get_libc_version() returns (None, None), so libc_version was falsy and __glibc was not emitted. After the override refactor (#15248, in 25.11.0), linux.py:70-76 passes
  version=None unconditionally; None is not NULL, so PackageRecord.virtual_package coerces it to "0" (conda/models/records.py:541) and you now get __glibc=0=0. The empty_override=NULL default only kicks in
  when the override var is explicitly set to "".

  That looks like an unintended behavior change rather than a decision — the tests don't cover it (test_subdir_override sets CONDA_OVERRIDE_GLIBC="" at line 190, which masks exactly this case, and
  test_glibc_override only exercises the override paths). I read this from source rather than running it, so worth a quick confirm before you assert it upstream.

  The irony is useful for the PR: conda today produces the same __glibc=0=0 that you're reporting as a rattler bug. So this isn't rattler diverging from conda — it's rattler matching conda's current
  (arguably broken) behavior, and the PR would make rattler diverge from conda toward pixi.

  Suggested framing for the reply

  Rather than defaults inside detect_for_platform(), the conda-compatible answer is: keep the 0s as the library-level truth, and put pixi-style defaults in the rattler CLI's solve command (which is a dev
  tool anyway), or behind an explicit opt-in like --use-default-virtual-packages. That keeps rattler_virtual_packages faithful to conda semantics while fixing the ergonomics you actually hit. Silently
  injecting glibc 2.28 into a library used by conda-rattler-solver would make conda-with-rattler-solver solve differently than conda proper.

@baszalmstra

baszalmstra commented Aug 5, 2026 •

Copy link
Copy Markdown
Collaborator

I guess we should maybe also warn the user? E.g. "cant determine virtual package bla, assuming bla"? and tell them to override using bla.

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K
@pavelzw

pavelzw commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

8111cf5 (this PR)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use those in a follow-up PR in pixi

Comment on lines 314 to 317
/// - **Windows** (`__win`): Version 10.0
/// - **Linux** (`__linux`): Version 4.18
/// - **OSX** (`__osx`): Version 13.0
/// - **iOS** (`__ios`): Version 0 (minimum supported iOS version)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can just point to the defaults module? TO make sure this doesnt go out of date.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WyyLK4E1qspcGuhDgoqS7K
@baszalmstra
baszalmstra merged commit 5453393 into main Aug 6, 2026
19 checks passed
@baszalmstra
baszalmstra deleted the claude/rattler-virtual-packages-defaults-s4r13b branch August 6, 2026 07:34
@octo-sts octo-sts Bot mentioned this pull request Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants