feat: runtime musl/glibc detection for correct libc variant selection#8490
feat: runtime musl/glibc detection for correct libc variant selection#8490
Conversation
- Detect musl at runtime by checking for /lib/ld-musl-* instead of using compile-time cfg!(target_env = "musl"), so a musl-built mise on a glibc system (or vice versa) picks the correct artifact variant - Set qualifier on Platform::current() for musl systems so lockfile keys and asset selection use the right libc variant - Add linux-x64-musl and linux-arm64-musl to common_platforms() so mise lock resolves checksums/URLs for both glibc and musl variants - Update get_platform_key() to include the qualifier from Platform::current() - Add github:snyk/cli as a registry backend for snyk Closes #8456 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces runtime detection of musl libc on Linux systems, which is a significant improvement over the previous compile-time check. This allows mise binaries to correctly select libc-specific tool variants regardless of how mise itself was compiled. The changes are well-structured, propagating the detected libc variant through the Platform struct to asset selection and lockfile key generation. The addition of musl variants to common_platforms ensures lockfiles can be generated for both glibc and musl environments. I have one suggestion to make the musl detection logic more concise and idiomatic.
Note: Security Review is unavailable for this PR.
src/platform.rs
Outdated
| if let Ok(entries) = std::fs::read_dir("/lib") { | ||
| for entry in entries.flatten() { | ||
| if entry.file_name().to_string_lossy().starts_with("ld-musl-") { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| false |
There was a problem hiding this comment.
The logic for checking for musl can be made more concise and idiomatic by using iterator methods like any() and map() on the Result from read_dir.
std::fs::read_dir("/lib")
.map(|entries| {
entries.flatten().any(|entry| {
entry
.file_name()
.to_string_lossy()
.starts_with("ld-musl-")
})
})
.unwrap_or(false)
Greptile SummaryThis PR implements runtime musl/glibc detection on Linux so a glibc-compiled mise binary running on a musl system (e.g., Alpine) correctly selects musl-flavored artifacts. The implementation:
The runtime detection uses LazyLock for caching to avoid repeated filesystem checks. Existing lockfiles without musl entries continue to work due to Confidence Score: 4/5
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Platform::current called] --> B{OS is linux?}
B -- No --> C[qualifier = None]
B -- Yes --> D[Runtime libc detection\ncached via LazyLock]
D --> E{glibc linker found\nin /lib or /lib64?}
E -- Yes --> F[qualifier = None\nglibc system]
E -- No --> G{musl linker found\nin /lib?}
G -- Yes --> H[qualifier = musl]
G -- No --> I[qualifier = None\nunknown libc]
C --> J[to_key returns os-arch]
F --> J
I --> J
H --> K[to_key returns os-arch-musl]
J --> L[Backend::get_platform_key]
K --> L
L --> M[Lockfile lookup\nby platform key]
L --> N[AssetMatcher.for_target\npropagates qualifier as libc]
M --> O{Cache hit?}
O -- Yes --> P[Use stored URL and checksum]
O -- No --> Q[Resolve via release API]
Last reviewed commit: bd5f8d2 |
- Fix cross-platform lockfile bug: AssetPicker::with_libc now defaults to "gnu" when no qualifier is passed, instead of checking Platform::current(). This prevents `mise lock` on musl systems from incorrectly populating unqualified `linux-x64` entries with musl assets. - Add ToolVersion::get_lock_platform() fallback: when looking up a qualified key like `linux-x64-musl`, falls back to the unqualified `linux-x64` key. This maintains backward compatibility with existing lockfiles in --locked mode. - Update all lockfile read sites (github, java, locked-mode check) to use the new fallback method. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The aqua backend was still using tv.lock_platforms.get() directly instead of tv.get_lock_platform(), missing the fallback from qualified keys (linux-x64-musl) to unqualified keys (linux-x64) for pre-existing lockfiles. This caused --locked mode to pass validation but then fail to find the URL during aqua's actual install. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove get_lock_platform() fallback from linux-x64-musl to linux-x64. On musl systems with old lockfiles, this fallback would silently install glibc binaries (which won't run) instead of either resolving fresh (normal mode) or erroring with a helpful "run mise lock" message (--locked mode). Both of those behaviors are correct and preferable to silently installing the wrong binary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
- Replace /lib/ld-musl-* file check with ldd --version output parsing. The ld-musl linker file can exist on glibc systems with musl-tools installed for cross-compilation, causing false positive detection. ldd --version reliably distinguishes: musl's ldd prints "musl libc", glibc's prints GNU version info. - Update e2e test_lock to expect 7 platforms (added musl variants). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ldd --version subprocess with filesystem checks for the dynamic linker. glibc systems always have /lib[64]/ld-linux-*, even when musl-tools is installed for cross-compilation. Musl systems (Alpine, Void musl, etc.) only have /lib/ld-musl-* without ld-linux-*. Checking for the absence of glibc's linker first avoids false positives and is faster than spawning a subprocess. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 x -- echo |
24.5 ± 0.5 | 23.7 | 30.1 | 1.00 |
mise x -- echo |
25.2 ± 0.9 | 23.6 | 30.3 | 1.03 ± 0.04 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 env |
24.2 ± 0.8 | 22.9 | 29.3 | 1.00 |
mise env |
25.4 ± 1.1 | 23.4 | 30.5 | 1.05 ± 0.06 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 hook-env |
25.1 ± 1.0 | 23.9 | 30.8 | 1.01 ± 0.04 |
mise hook-env |
24.8 ± 0.4 | 23.8 | 26.7 | 1.00 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.3.3 ls |
24.2 ± 0.9 | 23.2 | 32.4 | 1.00 |
mise ls |
24.3 ± 0.7 | 23.1 | 27.3 | 1.00 ± 0.05 |
xtasks/test/perf
| Command | mise-2026.3.3 | mise | Variance |
|---|---|---|---|
| install (cached) | 156ms | 154ms | +1% |
| ls (cached) | 85ms | 84ms | +1% |
| bin-paths (cached) | 88ms | 87ms | +1% |
| task-ls (cached) | 855ms | 864ms | -1% |
### 🚀 Features - **(github)** keep exe extensions on Windows by @iki in [#8424](#8424) - **(task)** add `interactive` field for exclusive terminal access by @jdx in [#8491](#8491) - add header comment to generated lockfiles by @ivy in [#8481](#8481) - runtime musl/glibc detection for correct libc variant selection by @jdx in [#8490](#8490) ### 🐛 Bug Fixes - **(github)** use registry platform options during install by @jdx in [#8492](#8492) - **(http)** store tool opts as native TOML to fix platform switching by @jdx in [#8448](#8448) - **(installer)** error if MISE_INSTALL_PATH is a directory by @jdx in [#8468](#8468) - **(prepare)** resolve sources/outputs relative to `dir` when set by @jdx in [#8472](#8472) - **(ruby)** fetch precompiled binary by release tag instead of listing all releases by @jdx in [#8488](#8488) - **(schema)** support structured objects in task depends by @risu729 in [#8463](#8463) - **(task)** replace println!/eprintln! with calm_io in task output macros by @vmaleze in [#8485](#8485) - handle scoped npm package names without backend prefix by @jdx in [#8477](#8477) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:copr docker digest to c485c4c by @renovate[bot] in [#8484](#8484) - update ghcr.io/jdx/mise:alpine docker digest to 8118bc7 by @renovate[bot] in [#8483](#8483) ### 📦 Registry - disable sd version test by @jdx in [#8489](#8489) ### New Contributors - @ivy made their first contribution in [#8481](#8481) - @iki made their first contribution in [#8424](#8424) ## 📦 Aqua Registry Updates #### New Packages (5) - [`datadog-labs/pup`](https://github.com/datadog-labs/pup) - [`k1LoW/mo`](https://github.com/k1LoW/mo) - [`rtk-ai/rtk`](https://github.com/rtk-ai/rtk) - [`suzuki-shunsuke/docfresh`](https://github.com/suzuki-shunsuke/docfresh) - [`yashikota/exiftool-go`](https://github.com/yashikota/exiftool-go) #### Updated Packages (6) - [`cloudflare/cloudflared`](https://github.com/cloudflare/cloudflared) - [`mozilla/sccache`](https://github.com/mozilla/sccache) - [`owenlamont/ryl`](https://github.com/owenlamont/ryl) - [`spinel-coop/rv`](https://github.com/spinel-coop/rv) - [`technicalpickles/envsense`](https://github.com/technicalpickles/envsense) - [`weaviate/weaviate`](https://github.com/weaviate/weaviate)
## Summary Expose the libc type detection added in #8490 to vfox plugins, in the `RUNTIME` global table. ## Details - Expose `RUNTIME.envType` to vfox Lua plugins (`"gnu"` for glibc Linux, `"musl"` for musl Linux, `nil` otherwise) - Add `env_type()` in `crates/vfox/src/config.rs` to detect libc at runtime via `/lib` and `/lib64` linker names - Add sync-note comments in `crates/vfox/src/config.rs` and `src/platform.rs` to keep both implementations aligned - Set `env_type` to `None` in `Runtime::with_platform()` because target libc is unknown for platform overrides - Document `RUNTIME.envType` in Lua types and plugin docs - Add missing `RUNTIME.version` and `RUNTIME.pluginDirPath` entries to `docs/tool-plugin-development.md` for parity ### Usage in plugins ```lua if RUNTIME.envType == "musl" then -- download musl-compatible binary elseif RUNTIME.envType == "gnu" then -- download glibc-compatible binary end ``` ## Design decisions We intentionally duplicate musl/glibc detection in `crates/vfox` because `vfox` is a separate crate boundary and sharing `is_musl_system()` would add unnecessary coupling. The logic is small, self-contained, and cross-referenced by sync notes in both locations to reduce drift. ## Test plan - [x] Unit tests for `env_type()` return only valid values (`"gnu"`, `"musl"`, or `nil`) on Linux and `nil` on non-Linux - [x] Added regression test ensuring `RUNTIME.envType` is `nil` when using platform override (`Runtime::with_platform`) - [x] `cargo test` passes - [x] Lint passes (`mise --cd crates/vfox run lint-fix`) 🤖 This PR description was generated with the assistance of Claude Opus 4.6.
Summary
/lib/ld-musl-*) instead of using compile-timecfg!(target_env = "musl"), so a musl-built mise on a glibc system (or vice versa) selects the correct artifact variantmuslqualifier onPlatform::current()for musl systems, propagating throughget_platform_key()andAssetPickerfor correct lockfile keys and asset selectionlinux-x64-muslandlinux-arm64-musltocommon_platforms()somise lockresolves checksums/URLs for both glibc and musl variantsgithub:snyk/clias a fallback registry backend for snykHow it works with mise.lock
The lockfile now stores separate entries for glibc and musl:
At install time, the runtime-detected platform key selects the correct entry. Existing lockfiles without musl entries gracefully fall through to normal asset resolution.
Backward compatibility
linux-x64keys continue to work — musl systems just resolve assets normally (no lockfile cache hit) untilmise lockis re-runplatform_variantsmechanism (already used by bun) allows backends to opt into generating musl-specific lockfile entriesCloses #8456
Test plan
Platform::current()returnslinux-x64-muslPlatform::current()returnslinux-x64(no qualifier)mise use github:snyk/clion both musl and glibc systems🤖 Generated with Claude Code
Note
Medium Risk
Changes platform-keying and libc selection logic that affects lockfile lookups and which binaries are downloaded on Linux, so regressions could cause missed lockfile hits or wrong artifact selection on some distros.
Overview
Improves Linux libc handling by detecting musl at runtime and propagating it into
Platform::current()so lockfile platform keys can include a-muslqualifier when appropriate.Expands default lockfile targeting from 5 to 7 platforms by adding
linux-*-muslentries, updatesBackend::get_platform_key()to usePlatform::current().to_key(), and adjustsAssetPickerto avoid using compile-timecfg!(target_env = "musl")so cross-platform locking doesn’t leak the host libc into other targets.Updates the registry entry for
snykto includegithub:snyk/clias an additional backend option, and refreshes themise locke2e test expectations accordingly.Written by Cursor Bugbot for commit bd5f8d2. This will update automatically on new commits. Configure here.