Skip to content

fix(install): filter optional dependencies by libc field - #26159

Closed
robobun wants to merge 3 commits into
mainfrom
claude/fix-libc-filtering-26156
Closed

robobun wants to merge 3 commits into
mainfrom
claude/fix-libc-filtering-26156

Conversation

@robobun

@robobun robobun commented Jan 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Implements support for the libc field in package.json for filtering optional dependencies
  • Adds --libc CLI flag for manually overriding the target libc type
  • Detects glibc vs musl at compile time on Linux, uses .all on other platforms

Test plan

  • Run bun bd test test/cli/install/bun-install-cpu-os.test.ts - all 17 tests pass (including 4 new libc tests)
  • Run bun bd test test/regression/issue/26156.test.ts - all 3 tests pass
  • Verify --libc glibc, --libc musl, and --libc * flags work correctly
  • Verify invalid libc values are rejected with appropriate error messages
  • Verify backwards compatibility: packages without libc field still install correctly

Details

This PR adds libc filtering support to the package manager, allowing packages like @rollup/rollup-linux-x64-gnu (glibc) and @rollup/rollup-linux-x64-musl (musl) to be correctly filtered based on the target system's libc type.

Key changes:

  1. npm.zig: Updated Libc.current to detect glibc vs musl at compile time on Linux. On non-Linux platforms (macOS, Windows), returns .all since libc is not relevant.

  2. Meta.zig: Added libc field to the package metadata struct, replacing the padding byte with the actual field. Updated isDisabled() to check libc in addition to cpu and os.

  3. isMatch() fix: The isMatch function now treats .none (unset) the same as .all, ensuring backwards compatibility with existing lockfiles where the padding bytes would be 0.

  4. CLI flag: Added --libc flag to override the target libc, similar to existing --cpu and --os flags.

  5. Lockfile support: Added libc serialization/deserialization for both bun.lock and pnpm lockfile formats.

Fixes #26156

🤖 Generated with Claude Code

Implement support for the `libc` field in package.json, which is used by
packages like @rollup/rollup-linux-x64-gnu and @rollup/rollup-linux-x64-musl
to specify which libc variant they require.

Changes:
- Add `libc` field to lockfile `Meta` struct
- Implement compile-time libc detection (glibc vs musl on Linux, .all elsewhere)
- Update `isDisabled()` to check libc in addition to cpu and os
- Add `--libc` CLI flag for manually overriding libc (like `--cpu` and `--os`)
- Add libc serialization/deserialization for bun.lock and pnpm lockfiles
- Parse `libc` field from package.json

The isMatch logic handles backwards compatibility by treating `.none` (unset)
the same as `.all`, so packages without a libc field match any system libc.

Fixes #26156

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@robobun

robobun commented Jan 16, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 1:39 AM PT - Jan 16th, 2026

❌ Your commit a9ad1d55 has 10 failures in Build #35010 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 26159

That installs a local version of the PR into your bun-26159 executable, so you can run:

bun-26159 --bun

@coderabbitai

coderabbitai Bot commented Jan 16, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds libc as a platform dimension: CLI flag and Options field, runtime libc detection, libc stored in package metadata and lockfiles, and libc-aware logic throughout dependency filtering, native binlink replacement, lifecycle script gating, and resolution/installation. Tests for CLI parsing and libc filtering were added. (≤50 words)

Changes

Cohort / File(s) Change Summary
CLI & Options
src/install/PackageManager/CommandLineArguments.zig, src/install/PackageManager/PackageManagerOptions.zig
Added --libc CLI param, new libc field in CommandLineArguments and Options, and getLibc() resolving .none to runtime detection.
Runtime libc core
src/install/npm.zig
Added runtime libc detection (Libc.current()), updated Libc.isMatch semantics and caching/detection logic for musl vs glibc on Linux.
Package metadata & meta checks
src/install/lockfile/Package/Meta.zig, src/install/lockfile/Package.zig, src/install/lockfile.zig
Introduced meta.libc: Npm.Libc, updated isDisabled/isResolvedDependencyDisabled to accept libc and match against it, and populated libc from package JSON/NPM sources.
Lockfile I/O & migration
src/install/lockfile/bun.lock.zig, src/install/lockfile/lockfile_json_stringify_for_debugging.zig, src/install/pnpm.zig
Emit/parse libc in binary/text lockfile formats and enable libc parsing during pnpm migration paths.
Resolver / package.json parsing
src/resolver/package_json.zig
Added libc: Libc to PackageJSON and parsing of libc arrays from package.json (imports Libc).
Installer / optimizer / lifecycle
src/install/PackageInstaller.zig, src/install/isolated_install/Installer.zig, src/install/postinstall_optimizer.zig, src/install/PackageManager/PackageManagerLifecycle.zig
Threaded target libc through native binlink replacement and lifecycle gating APIs (getNativeBinlinkReplacementPackageID, shouldIgnoreLifecycleScripts) and preinstall checks; updated call sites/signatures.
Dependency tree & printing
src/install/lockfile/Tree.zig, src/install/lockfile/printer/tree_printer.zig
Use options.getLibc() when evaluating isDisabled, add verbose libc-mismatch logging, and pass libc to printer disabled checks.
Tests
test/cli/install/bun-install-cpu-os.test.ts, test/regression/issue/26156.test.ts
Added tests for --libc parsing, wildcard/negation behavior, combined CPU/OS/libc filtering, invalid-value handling, and regression coverage for issue #26156.

Possibly related PRs

Suggested reviewers

  • dylan-conway
  • nektro
  • cirospaciari
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: filtering optional dependencies by libc field, which is the core objective of this PR.
Description check ✅ Passed The PR description covers the summary of changes, implementation details, test plan with verification steps, and links to the issue. It follows the template structure with comprehensive information.
Linked Issues check ✅ Passed The code changes fully implement libc detection, filtering, CLI flags, and lockfile support as required by issue #26156 to fix incorrect musl binary installation on glibc WSL environments.
Out of Scope Changes check ✅ Passed All changes are focused on implementing libc support for optional dependency filtering. No unrelated modifications to unrelated systems or files outside the install/resolver/lockfile scope are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.



📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 04ed2fc and a9ad1d5.

📒 Files selected for processing (1)
  • src/install/npm.zig
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.zig

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.zig: Use the # prefix for private fields in Zig structs, e.g., struct { #foo: u32 };
Use Decl literals in Zig, e.g., const decl: Decl = .{ .binding = 0, .value = 0 };
Place @import statements at the bottom of the file in Zig (auto formatter will handle positioning)
Never use @import() inline inside functions in Zig; always place imports at the bottom of the file or containing struct

Files:

  • src/install/npm.zig
🧠 Learnings (12)
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/src/napi/napi.zig : For each new V8 C++ method, add both GCC/Clang and MSVC mangled symbol names to the V8API struct in src/napi/napi.zig using extern fn declarations

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Applies to src/js/{builtins,node,bun,thirdparty,internal}/**/*.{ts,js} : Use `process.platform` and `process.arch` for platform detection; these values are inlined and dead-code eliminated at build time

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-16T17:32:03.074Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/install/PackageManager/PackageManagerOptions.zig:187-193
Timestamp: 2025-10-16T17:32:03.074Z
Learning: In Bun's codebase (particularly in files like src/install/PackageManager/PackageManagerOptions.zig), mixing bun.EnvVar.*.get() and bun.EnvVar.*.platformGet() for environment variable lookups is intentional and safe. The code is protected by compile-time platform checks (Environment.isWindows, etc.), and compilation will fail if the wrong function is used on the wrong platform. This pattern should not be flagged as a consistency issue.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Run `bun run zig:check-all` to compile Zig code on all platforms when making platform-specific changes

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-15T22:03:50.832Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/envvars.zig:135-144
Timestamp: 2025-10-15T22:03:50.832Z
Learning: In src/envvars.zig, the boolean feature flag cache uses a single atomic enum and should remain monotonic. Only the string cache (which uses two atomics: ptr and len) requires acquire/release ordering to prevent torn reads.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-16T21:24:52.779Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/crash_handler.zig:1415-1423
Timestamp: 2025-10-16T21:24:52.779Z
Learning: When a boolean EnvVar in src/envvars.zig is defined with a default value (e.g., `.default = false`), the `get()` method returns `bool` instead of `?bool`. This means you cannot distinguish between "environment variable not set" and "environment variable explicitly set to the default value". For opt-out scenarios where detection of explicit setting is needed (like `BUN_ENABLE_CRASH_REPORTING` on platforms where crash reporting defaults to enabled), either: (1) don't provide a default value so `get()` returns `?bool`, or (2) use the returned boolean directly instead of only checking if it's true.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-24T10:43:09.398Z
Learnt from: fmguerreiro
Repo: oven-sh/bun PR: 23774
File: src/install/PackageManager/updatePackageJSONAndInstall.zig:548-548
Timestamp: 2025-10-24T10:43:09.398Z
Learning: In Bun's Zig codebase, the `as(usize, intCast(...))` cast pattern triggers a Zig compiler bug that causes compilation to hang indefinitely when used in complex control flow contexts (loops + short-circuit operators + optional unwrapping). Avoid this pattern and use simpler alternatives like just `intCast(...)` if type casting is necessary.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-12-11T02:11:47.024Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 25462
File: src/ast/visitExpr.zig:1644-1695
Timestamp: 2025-12-11T02:11:47.024Z
Learning: In Bun's bundler feature flag implementation (src/ast/visitExpr.zig), the validation for feature() flag names intentionally only rejects UTF-16 strings (checking `is_utf16`) while allowing UTF-8 strings, even though the error message says "must be an ASCII string". This is the intended behavior and should not be changed to enforce strict ASCII validation.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Zig code should be organized in `src/*.zig` for core runtime, JavaScript bindings, and package manager

Applied to files:

  • src/install/npm.zig
📚 Learning: 2026-01-05T16:32:07.551Z
Learnt from: alii
Repo: oven-sh/bun PR: 25474
File: src/bun.js/event_loop/Sigusr1Handler.zig:0-0
Timestamp: 2026-01-05T16:32:07.551Z
Learning: In Zig codebases (e.g., Bun), treat std.posix.sigaction as returning void and do not perform runtime error handling for its failure. The Zig standard library views sigaction failures as programmer errors (unreachable) because they only occur with invalid signals like SIGKILL/SIGSTOP. Apply this pattern across Zig files that call sigaction (e.g., crash_handler.zig, main.zig, filter_run.zig, process.zig) and ensure failures are not handled as recoverable errors; prefer reaching an explicit unreachable/compile-time assumption when such failures are detected.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-16T02:17:35.237Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/analytics.zig:15-21
Timestamp: 2025-10-16T02:17:35.237Z
Learning: In src/analytics.zig and similar files using bun.EnvVar boolean environment variables: the new EnvVar API for boolean flags (e.g., bun.EnvVar.do_not_track.get(), bun.EnvVar.ci.get()) is designed to parse and return boolean values from environment variables, not just check for their presence. This is an intentional design change from the previous presence-based checks using bun.getenvZ().

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-17T01:21:35.060Z
Learnt from: taylordotfish
Repo: oven-sh/bun PR: 23755
File: src/bun.js/bindings/BunIDLConvert.h:79-95
Timestamp: 2025-10-17T01:21:35.060Z
Learning: In JavaScriptCore (used by Bun), the `toBoolean()` method implements ECMAScript's ToBoolean abstract operation, which is side-effect-free and cannot throw exceptions. It does not execute arbitrary JavaScript or invoke user-defined methods like Symbol.toPrimitive. Exception handling is not needed after toBoolean() calls.

Applied to files:

  • src/install/npm.zig
🔇 Additional comments (3)
src/install/npm.zig (3)

717-722: Backward‑compatible libc matching looks good.

Treating .none/.all as universal matches and honoring target .all keeps behavior compatible with older lockfiles and non‑Linux targets.


729-775: Runtime libc detection with caching is solid.

The runtime probe and cached result provide a clean Linux fallback while keeping non‑Linux behavior simple.


789-789: JS libc matcher now uses runtime libc—nice alignment.

This keeps JS-side filtering consistent with native libc detection.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/install/npm.zig`:
- Around line 717-735: Libc.current is a compile-time const using
Environment.isMusl, which misdetects the hosting libc for binaries compiled for
a different ABI; change it to a runtime-detected value by replacing the const
with a function (e.g., pub fn current() Libc) that, when Environment.isLinux is
true, performs runtime checks for musl (such as testing for the musl dynamic
loader binary paths like /lib*/ld-musl-*-*.so.1 or using a safe runtime probe)
and returns .musl or .glibc accordingly, otherwise returns .all; keep isMatch
and negatable as-is and ensure callers use Libc.current() (function) instead of
the old const.

In `@test/regression/issue/26156.test.ts`:
- Around line 45-100: The test "should correctly filter glibc vs musl optional
dependencies" only checks exit codes and leaves bun.lockb around, so update the
test to (1) add concrete mock optional deps with libc-specific package names in
the tempDir package.json (e.g. include both "@rollup/rollup-linux-x64-gnu" and
"@rollup/rollup-linux-x64-musl" or equivalent registry-mocked packages) so the
installer must choose between them, (2) after each Bun.spawn install
(proc1/proc2/proc3) assert which package got installed (verify node_modules
contains the expected libc-specific package or check bun.lock/bun.lockb
contents), and (3) ensure you explicitly remove both lockfile variants (bun.lock
and bun.lockb) between runs instead of only bun.lock so prior resolutions don't
leak into subsequent installs.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bcbb4fc and 34d1c70.

📒 Files selected for processing (25)
  • src/install/PackageInstaller.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/PackageManager/PackageManagerLifecycle.zig
  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/isolated_install/Installer.zig
  • src/install/lockfile.zig
  • src/install/lockfile/Package.zig
  • src/install/lockfile/Package/Meta.zig
  • src/install/lockfile/Tree.zig
  • src/install/lockfile/bun.lock.zig
  • src/install/lockfile/lockfile_json_stringify_for_debugging.zig
  • src/install/lockfile/printer/tree_printer.zig
  • src/install/npm.zig
  • src/install/pnpm.zig
  • src/install/postinstall_optimizer.zig
  • src/resolver/package_json.zig
  • test/cli/install/bun-install-cpu-os.test.ts
  • test/cli/install/dep-arm64-linux-glibc-3.0.0.tgz
  • test/cli/install/dep-glibc-1.0.0.tgz
  • test/cli/install/dep-glibc-only-1.0.0.tgz
  • test/cli/install/dep-musl-2.0.0.tgz
  • test/cli/install/dep-musl-only-2.0.0.tgz
  • test/cli/install/dep-x64-linux-glibc-1.0.0.tgz
  • test/cli/install/dep-x64-linux-musl-2.0.0.tgz
  • test/regression/issue/26156.test.ts
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.zig

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.zig: Use the # prefix for private fields in Zig structs, e.g., struct { #foo: u32 };
Use Decl literals in Zig, e.g., const decl: Decl = .{ .binding = 0, .value = 0 };
Place @import statements at the bottom of the file in Zig (auto formatter will handle positioning)
Never use @import() inline inside functions in Zig; always place imports at the bottom of the file or containing struct

Files:

  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/pnpm.zig
  • src/install/PackageManager/PackageManagerLifecycle.zig
  • src/install/lockfile/Tree.zig
  • src/install/isolated_install/Installer.zig
  • src/install/lockfile/lockfile_json_stringify_for_debugging.zig
  • src/install/lockfile/bun.lock.zig
  • src/install/lockfile/printer/tree_printer.zig
  • src/install/npm.zig
  • src/install/lockfile.zig
  • src/install/lockfile/Package.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/lockfile/Package/Meta.zig
  • src/install/postinstall_optimizer.zig
  • src/install/PackageInstaller.zig
  • src/resolver/package_json.zig
test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}: Use bun bd test <...test file> to run tests with compiled code changes. Do not use bun test as it will not include your changes.
Use bun:test for files ending in *.test.{ts,js,jsx,tsx,mjs,cjs}. For test files without .test extension in test/js/node/test/{parallel,sequential}/*.js, use bun bd <file> instead of bun bd test <file> since they expect exit code 0.
Do not set a timeout on tests. Bun already has timeouts built-in.

Files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.ts: Use Bun's Jest-compatible test runner with proper test fixtures and imports from harness
Always use port: 0 when binding to ports in tests - never hardcode ports or use custom random port functions
Use normalizeBunSnapshot to normalize snapshot output in tests
Never write tests that check for 'panic', 'uncaught exception', or similar strings in test output as these will never fail in CI
Use tempDir from harness to create temporary directories in tests - do not use tmpdirSync or fs.mkdtempSync
In spawned process tests, use expect(stdout).toBe(...) BEFORE expect(exitCode).toBe(0) for more useful error messages
Do not use setTimeout in tests - await the condition to be met instead, as you are testing the CONDITION not TIME PASSING

Files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
🧠 Learnings (30)
📓 Common learnings
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24880
File: packages/bun-vscode/package.json:382-385
Timestamp: 2025-11-20T19:51:32.288Z
Learning: In the Bun repository, dependencies may be explicitly added to package.json files (even when not directly imported in code) to force version upgrades on transitive dependencies, particularly as part of Aikido security scanner remediation to ensure vulnerable transitive dependencies resolve to patched versions.
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23680
File: cmake/targets/BuildBun.cmake:822-822
Timestamp: 2025-10-15T20:19:37.256Z
Learning: In the Bun codebase, FFI (Foreign Function Interface) code is compiled separately using TinyCC (tcc), which barely supports C99. Headers like src/bun.js/api/FFI.h and src/bun.js/api/ffi-stdbool.h are only used for FFI compilation with tcc, not with the main compiler. Therefore, C standard changes to the main Bun target do not affect FFI code compilation.
📚 Learning: 2026-01-05T16:32:07.551Z
Learnt from: alii
Repo: oven-sh/bun PR: 25474
File: src/bun.js/event_loop/Sigusr1Handler.zig:0-0
Timestamp: 2026-01-05T16:32:07.551Z
Learning: In Zig codebases (e.g., Bun), treat std.posix.sigaction as returning void and do not perform runtime error handling for its failure. The Zig standard library views sigaction failures as programmer errors (unreachable) because they only occur with invalid signals like SIGKILL/SIGSTOP. Apply this pattern across Zig files that call sigaction (e.g., crash_handler.zig, main.zig, filter_run.zig, process.zig) and ensure failures are not handled as recoverable errors; prefer reaching an explicit unreachable/compile-time assumption when such failures are detected.

Applied to files:

  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/pnpm.zig
  • src/install/PackageManager/PackageManagerLifecycle.zig
  • src/install/lockfile/Tree.zig
  • src/install/isolated_install/Installer.zig
  • src/install/lockfile/lockfile_json_stringify_for_debugging.zig
  • src/install/lockfile/bun.lock.zig
  • src/install/lockfile/printer/tree_printer.zig
  • src/install/npm.zig
  • src/install/lockfile.zig
  • src/install/lockfile/Package.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/lockfile/Package/Meta.zig
  • src/install/postinstall_optimizer.zig
  • src/install/PackageInstaller.zig
  • src/resolver/package_json.zig
📚 Learning: 2025-09-06T03:37:41.154Z
Learnt from: taylordotfish
Repo: oven-sh/bun PR: 22229
File: src/bundler/LinkerGraph.zig:0-0
Timestamp: 2025-09-06T03:37:41.154Z
Learning: In Bun's codebase, when checking import record source indices in src/bundler/LinkerGraph.zig, prefer using `if (import_index >= self.import_records.len)` bounds checking over `isValid()` checks, as the bounds check is more robust and `isValid()` is a strict subset of this condition.

Applied to files:

  • src/install/isolated_install/Installer.zig
📚 Learning: 2026-01-05T23:04:01.518Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2026-01-05T23:04:01.518Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : Use `bun bd test <...test file>` to run tests with compiled code changes. Do not use `bun test` as it will not include your changes.

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/test/v8/v8.test.ts : Add corresponding test cases to test/v8/v8.test.ts using checkSameOutput() function to compare Node.js and Bun output

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-05T23:04:01.518Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2026-01-05T23:04:01.518Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : Use `bun:test` for files ending in `*.test.{ts,js,jsx,tsx,mjs,cjs}`. For test files without .test extension in test/js/node/test/{parallel,sequential}/*.js, use `bun bd <file>` instead of `bun bd test <file>` since they expect exit code 0.

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2025-10-19T02:44:46.354Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 23798
File: packages/bun-otel/context-propagation.test.ts:1-1
Timestamp: 2025-10-19T02:44:46.354Z
Learning: In the Bun repository, standalone packages under packages/ (e.g., bun-vscode, bun-inspector-protocol, bun-plugin-yaml, bun-plugin-svelte, bun-debug-adapter-protocol, bun-otel) co-locate their tests with package source code using *.test.ts files. This follows standard npm/monorepo patterns. The test/ directory hierarchy (test/js/bun/, test/cli/, test/js/node/) is reserved for testing Bun's core runtime APIs and built-in functionality, not standalone packages.

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-14T21:08:10.438Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/js/node/test/parallel/CLAUDE.md:0-0
Timestamp: 2026-01-14T21:08:10.438Z
Learning: Run Node.js compatibility tests using `bun bd <file-path>` command, not `bun bd test <file-path>`

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-14T21:08:10.438Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/js/node/test/parallel/CLAUDE.md:0-0
Timestamp: 2026-01-14T21:08:10.438Z
Learning: These are Node.js compatibility tests not written by Bun and cannot be modified

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-14T16:07:01.064Z
Learnt from: RiskyMH
Repo: oven-sh/bun PR: 24719
File: docs/bundler/executables.mdx:527-560
Timestamp: 2025-11-14T16:07:01.064Z
Learning: In the Bun repository, certain bundler features like compile with code splitting (--compile --splitting) are CLI-only and not supported in the Bun.build() JavaScript API. Tests for CLI-only features use backend: "cli" flag (e.g., test/bundler/bundler_compile_splitting.test.ts). The CompileBuildConfig interface correctly restricts these with splitting?: never;. When documenting CLI-only bundler features, add a note clarifying they're not available via the programmatic API.

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • src/install/lockfile/bun.lock.zig
  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Write JS builtins for Bun's Node.js compatibility and APIs, and run `bun bd` after changes

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • src/install/lockfile/bun.lock.zig
  • src/resolver/package_json.zig
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Applies to src/js/{builtins,node,bun,thirdparty,internal}/**/*.{ts,js} : Use `process.platform` and `process.arch` for platform detection; these values are inlined and dead-code eliminated at build time

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • src/install/lockfile/bun.lock.zig
  • src/install/npm.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/postinstall_optimizer.zig
  • src/install/PackageInstaller.zig
📚 Learning: 2025-10-26T01:32:04.844Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 24082
File: test/cli/test/coverage.test.ts:60-112
Timestamp: 2025-10-26T01:32:04.844Z
Learning: In the Bun repository test files (test/cli/test/*.test.ts), when spawning Bun CLI commands with Bun.spawnSync for testing, prefer using stdio: ["inherit", "inherit", "inherit"] to inherit stdio streams rather than piping them.

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Ensure V8 API tests compare identical C++ code output between Node.js and Bun through the test suite validation process

Applied to files:

  • test/cli/install/bun-install-cpu-os.test.ts
  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/src/napi/napi.zig : For each new V8 C++ method, add both GCC/Clang and MSVC mangled symbol names to the V8API struct in src/napi/napi.zig using extern fn declarations

Applied to files:

  • src/install/lockfile/bun.lock.zig
  • src/install/npm.zig
  • src/install/postinstall_optimizer.zig
  • src/resolver/package_json.zig
📚 Learning: 2025-11-20T19:51:32.288Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24880
File: packages/bun-vscode/package.json:382-385
Timestamp: 2025-11-20T19:51:32.288Z
Learning: In the Bun repository, dependencies may be explicitly added to package.json files (even when not directly imported in code) to force version upgrades on transitive dependencies, particularly as part of Aikido security scanner remediation to ensure vulnerable transitive dependencies resolve to patched versions.

Applied to files:

  • src/install/lockfile/bun.lock.zig
📚 Learning: 2025-10-16T02:17:35.237Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/analytics.zig:15-21
Timestamp: 2025-10-16T02:17:35.237Z
Learning: In src/analytics.zig and similar files using bun.EnvVar boolean environment variables: the new EnvVar API for boolean flags (e.g., bun.EnvVar.do_not_track.get(), bun.EnvVar.ci.get()) is designed to parse and return boolean values from environment variables, not just check for their presence. This is an intentional design change from the previous presence-based checks using bun.getenvZ().

Applied to files:

  • src/install/lockfile/bun.lock.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Run `bun run zig:check-all` to compile Zig code on all platforms when making platform-specific changes

Applied to files:

  • src/install/npm.zig
  • src/resolver/package_json.zig
📚 Learning: 2025-10-15T22:03:50.832Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/envvars.zig:135-144
Timestamp: 2025-10-15T22:03:50.832Z
Learning: In src/envvars.zig, the boolean feature flag cache uses a single atomic enum and should remain monotonic. Only the string cache (which uses two atomics: ptr and len) requires acquire/release ordering to prevent torn reads.

Applied to files:

  • src/install/lockfile.zig
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Applies to src/js/{builtins,node,bun,thirdparty,internal}/**/*.{ts,js} : Use string literal `require()` statements only; dynamic requires are not permitted

Applied to files:

  • src/install/postinstall_optimizer.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Applies to test/**/*.test.ts : Use `normalizeBunSnapshot` to normalize snapshot output in tests

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Applies to test/**/*.test.ts : Use Bun's Jest-compatible test runner with proper test fixtures and imports from `harness`

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Verify tests fail with `USE_SYSTEM_BUN=1 bun test <file>` and pass with `bun bd test <file>` - a test is invalid if it passes with `USE_SYSTEM_BUN=1`

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-05T23:04:01.518Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2026-01-05T23:04:01.518Z
Learning: When spawning Bun processes in tests, use `bunExe` and `bunEnv` from `harness` to ensure the same build of Bun is used and debug logging is silenced.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-08-30T09:09:18.384Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 22231
File: src/bundler/bundle_v2.zig:48-48
Timestamp: 2025-08-30T09:09:18.384Z
Learning: In Zig, when a module exports a top-level struct, import("./Module.zig") directly returns that struct type and can be used as a type alias without needing to access a field within the module. This is a common pattern in the Bun codebase.

Applied to files:

  • src/resolver/package_json.zig
📚 Learning: 2025-11-12T04:11:52.293Z
Learnt from: cirospaciari
Repo: oven-sh/bun PR: 24622
File: src/deps/uws/us_socket_t.zig:112-113
Timestamp: 2025-11-12T04:11:52.293Z
Learning: In Bun's Zig codebase, when passing u32 values to C FFI functions that expect c_uint parameters, no explicit intCast is needed because c_uint is equivalent to u32 on Bun's target platforms and Zig allows implicit coercion between equivalent types. This pattern is used consistently throughout src/deps/uws/us_socket_t.zig in functions like setTimeout, setLongTimeout, and setKeepalive.

Applied to files:

  • src/resolver/package_json.zig
📚 Learning: 2025-10-16T17:32:03.074Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/install/PackageManager/PackageManagerOptions.zig:187-193
Timestamp: 2025-10-16T17:32:03.074Z
Learning: In Bun's codebase (particularly in files like src/install/PackageManager/PackageManagerOptions.zig), mixing bun.EnvVar.*.get() and bun.EnvVar.*.platformGet() for environment variable lookups is intentional and safe. The code is protected by compile-time platform checks (Environment.isWindows, etc.), and compilation will fail if the wrong function is used on the wrong platform. This pattern should not be flagged as a consistency issue.

Applied to files:

  • src/resolver/package_json.zig
📚 Learning: 2025-10-26T04:50:17.892Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 24086
File: src/bun.js/api/server.zig:2534-2535
Timestamp: 2025-10-26T04:50:17.892Z
Learning: In src/bun.js/api/server.zig, u32 is acceptable for route indices and websocket_context_index fields, as the practical limit of 4 billion contexts will never be reached.

Applied to files:

  • src/resolver/package_json.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Zig code should be organized in `src/*.zig` for core runtime, JavaScript bindings, and package manager

Applied to files:

  • src/resolver/package_json.zig
📚 Learning: 2025-10-15T20:19:37.256Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23680
File: cmake/targets/BuildBun.cmake:822-822
Timestamp: 2025-10-15T20:19:37.256Z
Learning: In the Bun codebase, FFI (Foreign Function Interface) code is compiled separately using TinyCC (tcc), which barely supports C99. Headers like src/bun.js/api/FFI.h and src/bun.js/api/ffi-stdbool.h are only used for FFI compilation with tcc, not with the main compiler. Therefore, C standard changes to the main Bun target do not affect FFI code compilation.

Applied to files:

  • src/resolver/package_json.zig
🧬 Code graph analysis (1)
test/regression/issue/26156.test.ts (3)
src/bun.js/bindings/ConcatCStrings.h (1)
  • it (29-35)
test/harness.ts (1)
  • tempDir (277-284)
test/js/node/test_runner/fixtures/02-hooks.js (1)
  • JSON (7-7)
🔇 Additional comments (36)
src/install/lockfile/printer/tree_printer.zig (1)

139-146: LGTM: libc forwarded into disabled filtering.

This keeps the print/disable logic consistent with libc-aware resolution.

src/install/PackageManager/PackageManagerOptions.zig (2)

86-91: LGTM: libc option added with sensible default.


613-617: LGTM: CLI libc is propagated into options.

src/install/pnpm.zig (1)

625-627: LGTM: pnpm libc field mapped into package metadata.

src/install/lockfile/lockfile_json_stringify_for_debugging.zig (1)

316-326: LGTM: libc included in lockfile debug JSON output.

src/install/isolated_install/Installer.zig (2)

930-944: LGTM: libc propagated into lifecycle-script gating.

Keeps script skipping consistent with cpu/os filtering.


1323-1332: LGTM: native binlink replacement now libc-aware.

Good alignment with the new selection criteria.

test/regression/issue/26156.test.ts (2)

16-42: LGTM: help output includes --libc.

Simple and effective flag visibility check.


102-123: LGTM: invalid libc values are rejected.

Covers the expected error path cleanly.

src/install/lockfile/Tree.zig (1)

366-377: LGTM: libc included in disablement check and logging.

Nice parity with existing cpu/os mismatch reporting.

src/install/lockfile/bun.lock.zig (2)

761-769: LGTM: libc serialized when non-default.

Comma handling and Negatable serialization look correct.


1823-1832: LGTM: libc parsed from lockfile metadata.

Keeps text lockfile parsing consistent with new field support.

src/install/lockfile.zig (2)

407-416: LGTM: libc added to resolved-dependency disablement logic.

Matches the new meta matching behavior.


1026-1035: LGTM: migration path now carries libc metadata.

Good parity with os/cpu updates.

src/install/PackageInstaller.zig (3)

292-298: LGTM! Libc propagation to native binlink optimization looks correct.

The target_libc is correctly read from manager.options and passed to getNativeBinlinkReplacementPackageID alongside target_cpu and target_os, following the established pattern for platform-specific package selection.


1167-1177: LGTM! Libc parameter correctly added to lifecycle script filtering.

The shouldIgnoreLifecycleScripts call now includes this.manager.options.libc, consistent with the existing cpu and os parameters. This ensures lifecycle scripts are properly skipped for packages that don't match the target libc.


1362-1373: LGTM! Second call site for lifecycle script filtering updated consistently.

Both call sites for shouldIgnoreLifecycleScripts now include the libc parameter, ensuring consistent behavior across the trusted dependency path.

test/cli/install/bun-install-cpu-os.test.ts (4)

608-666: LGTM! Comprehensive libc filtering test.

The test correctly validates:

  • glibc filtering installs only glibc-compatible packages
  • musl filtering installs only musl-compatible packages
  • Proper cleanup between test runs including both bun.lockb and bun.lock

668-716: LGTM! Combined cpu/os/libc filter test validates the complete matrix.

This test ensures that all three platform constraints (cpu: x64, os: linux, libc: glibc) work together correctly, with only the exact matching package being installed.


718-742: LGTM! Error handling test for invalid libc.

The test correctly validates that an invalid libc value results in exit code 1 and appropriate error messaging, consistent with the existing invalid CPU/OS tests.


744-783: LGTM! Wildcard libc test ensures backward compatibility.

The --libc "*" wildcard correctly installs all packages regardless of libc constraint, matching the behavior of --cpu "*" and --os "*".

src/install/PackageManager/PackageManagerLifecycle.zig (1)

84-89: LGTM! Preinstall state determination now considers libc.

The isDisabled check correctly includes manager.options.libc, ensuring packages incompatible with the target libc are marked as done and not downloaded. This aligns with the existing cpu/os handling pattern.

src/install/lockfile/Package.zig (3)

60-62: LGTM! Public API updated to include libc parameter.

The isDisabled method signature correctly forwards the libc parameter to this.meta.isDisabled, maintaining consistency with the cpu and os parameters.


283-286: LGTM! Package metadata correctly populated from package.json.

The libc field is assigned alongside arch and os, following the established pattern for platform-specific metadata.


493-496: LGTM! Package metadata correctly populated from npm manifest.

The libc field is assigned from package_version.libc alongside cpu, os, and integrity, maintaining consistency with how other platform metadata is handled for npm packages.

src/resolver/package_json.zig (3)

65-67: LGTM — libc default aligns with arch/os defaults.


967-979: LGTM — libc parsing mirrors cpu/os negatable handling.


2167-2167: LGTM — Libc import is required for the new field.

src/install/lockfile/Package/Meta.zig (3)

10-15: Verify Meta extern layout stays lockfile‑compatible.

Meta is extern and serialized; the new libc field must fit into reclaimed padding. Please confirm @sizeOf(Npm.Libc) matches the padding size (u8) or adjust padding/bump the lockfile version to avoid compatibility breaks.

🛡️ Optional compile-time guard
 pub const Meta = extern struct {
     // ...
     libc: Npm.Libc = .all,
     _padding_libc: u8 = 0,
     // ...
 };
+
+comptime {
+    if (`@sizeOf`(Npm.Libc) != `@sizeOf`(u8)) {
+        `@compileError`("Meta layout assumes 1-byte Npm.Libc; adjust padding or bump lockfile version.");
+    }
+}

35-39: LGTM — libc is now part of the disable predicate.


62-69: LGTM — clone now copies libc.

src/install/postinstall_optimizer.zig (2)

48-67: LGTM — binlink replacement selection is now libc‑aware.


101-129: LGTM — lifecycle ignore decision now threads libc.

src/install/PackageManager/CommandLineArguments.zig (3)

54-56: LGTM — --libc flag is exposed in shared params.


253-256: LGTM — cli.libc default matches cpu/os pattern.


1022-1044: LGTM — --libc parsing mirrors cpu/os wildcard/negation handling.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/install/npm.zig Resolved
Comment thread test/regression/issue/26156.test.ts Outdated
Comment on lines +45 to +100
it("should correctly filter glibc vs musl optional dependencies", async () => {
// This test creates a mock scenario similar to the reported issue
// where packages like @rollup/rollup-linux-x64-gnu (glibc) and
// @rollup/rollup-linux-x64-musl (musl) should be filtered based on libc

using dir = tempDir("issue-26156-filtering", {
"package.json": JSON.stringify({
name: "test-libc-filtering-real",
version: "1.0.0",
// In a real scenario, these would be packages with libc field in their package.json
// The filtering happens based on the registry metadata
}),
});

// Test that explicit --libc glibc flag is accepted
await using proc1 = Bun.spawn({
cmd: [bunExe(), "install", "--libc", "glibc"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});

const exitCode1 = await proc1.exited;
expect(exitCode1).toBe(0);

// Test that explicit --libc musl flag is accepted
await rm(join(String(dir), "node_modules"), { recursive: true, force: true });
await rm(join(String(dir), "bun.lock"), { force: true });

await using proc2 = Bun.spawn({
cmd: [bunExe(), "install", "--libc", "musl"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});

const exitCode2 = await proc2.exited;
expect(exitCode2).toBe(0);

// Test that --libc * (wildcard) is accepted
await rm(join(String(dir), "node_modules"), { recursive: true, force: true });
await rm(join(String(dir), "bun.lock"), { force: true });

await using proc3 = Bun.spawn({
cmd: [bunExe(), "install", "--libc", "*"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});

const exitCode3 = await proc3.exited;
expect(exitCode3).toBe(0);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Test doesn’t validate libc filtering and leaves bun.lockb behind.

This block only asserts exit codes, and the optional deps aren’t defined, so it won’t catch a regression in libc-based selection. Additionally, deleting only bun.lock can leave bun.lockb in place, causing later installs to reuse the previous resolution and masking libc changes. Please add concrete libc-constrained packages and assert which one is installed, and clear both lockfile variants between runs.

🔧 Suggested cleanup fix for lockfiles
-  await rm(join(String(dir), "bun.lock"), { force: true });
+  await rm(join(String(dir), "bun.lock"), { force: true });
+  await rm(join(String(dir), "bun.lockb"), { force: true });
...
-  await rm(join(String(dir), "bun.lock"), { force: true });
+  await rm(join(String(dir), "bun.lock"), { force: true });
+  await rm(join(String(dir), "bun.lockb"), { force: true });
🤖 Prompt for AI Agents
In `@test/regression/issue/26156.test.ts` around lines 45 - 100, The test "should
correctly filter glibc vs musl optional dependencies" only checks exit codes and
leaves bun.lockb around, so update the test to (1) add concrete mock optional
deps with libc-specific package names in the tempDir package.json (e.g. include
both "@rollup/rollup-linux-x64-gnu" and "@rollup/rollup-linux-x64-musl" or
equivalent registry-mocked packages) so the installer must choose between them,
(2) after each Bun.spawn install (proc1/proc2/proc3) assert which package got
installed (verify node_modules contains the expected libc-specific package or
check bun.lock/bun.lockb contents), and (3) ensure you explicitly remove both
lockfile variants (bun.lock and bun.lockb) between runs instead of only bun.lock
so prior resolutions don't leak into subsequent installs.

Address review comments on PR #26159:

1. Changed `Libc.current` from compile-time const to runtime function
   `Libc.current()` that detects musl vs glibc at runtime. This handles
   cases where a glibc-compiled Bun binary runs on a musl system (e.g.,
   via gcompat on Alpine Linux).

2. Runtime detection checks for musl's dynamic loader paths:
   - /lib/ld-musl-x86_64.so.1 (x64)
   - /lib/ld-musl-aarch64.so.1 (arm64)
   The result is cached after first detection.

3. Updated all usages of `options.libc` to use `options.getLibc()` which
   resolves the `.none` default to the runtime-detected value.

4. Simplified regression test to focus on CLI interface testing. The
   detailed libc filtering is already tested in bun-install-cpu-os.test.ts
   using a mock registry.

5. Added cleanup of both bun.lock and bun.lockb between test runs.

Fixes #26156

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/install/npm.zig`:
- Around line 729-774: The global cached_current can race if Libc.current() is
called from multiple threads; replace the plain mutable global with a
thread-safe one-time initialization (e.g., use std.sync.Once or an equivalent
once-init helper) so detectLibcRuntime() is executed exactly once and cached
safely, or make cached_current an atomic and perform an atomic compare-exchange
when setting it; update the use in Libc.current() to call the once-init (or
atomic setter) instead of the current cached_current orelse pattern and ensure
detectLibcRuntime() is the initializer.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 34d1c70 and 04ed2fc.

📒 Files selected for processing (9)
  • src/install/PackageInstaller.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/PackageManager/PackageManagerLifecycle.zig
  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/isolated_install/Installer.zig
  • src/install/lockfile/Tree.zig
  • src/install/lockfile/printer/tree_printer.zig
  • src/install/npm.zig
  • test/regression/issue/26156.test.ts
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.zig

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.zig: Use the # prefix for private fields in Zig structs, e.g., struct { #foo: u32 };
Use Decl literals in Zig, e.g., const decl: Decl = .{ .binding = 0, .value = 0 };
Place @import statements at the bottom of the file in Zig (auto formatter will handle positioning)
Never use @import() inline inside functions in Zig; always place imports at the bottom of the file or containing struct

Files:

  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/lockfile/Tree.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/lockfile/printer/tree_printer.zig
  • src/install/npm.zig
  • src/install/isolated_install/Installer.zig
  • src/install/PackageManager/PackageManagerLifecycle.zig
  • src/install/PackageInstaller.zig
test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.{ts,js,jsx,tsx,mjs,cjs}: Use bun bd test <...test file> to run tests with compiled code changes. Do not use bun test as it will not include your changes.
Use bun:test for files ending in *.test.{ts,js,jsx,tsx,mjs,cjs}. For test files without .test extension in test/js/node/test/{parallel,sequential}/*.js, use bun bd <file> instead of bun bd test <file> since they expect exit code 0.
Do not set a timeout on tests. Bun already has timeouts built-in.

Files:

  • test/regression/issue/26156.test.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.ts: Use Bun's Jest-compatible test runner with proper test fixtures and imports from harness
Always use port: 0 when binding to ports in tests - never hardcode ports or use custom random port functions
Use normalizeBunSnapshot to normalize snapshot output in tests
Never write tests that check for 'panic', 'uncaught exception', or similar strings in test output as these will never fail in CI
Use tempDir from harness to create temporary directories in tests - do not use tmpdirSync or fs.mkdtempSync
In spawned process tests, use expect(stdout).toBe(...) BEFORE expect(exitCode).toBe(0) for more useful error messages
Do not use setTimeout in tests - await the condition to be met instead, as you are testing the CONDITION not TIME PASSING

Files:

  • test/regression/issue/26156.test.ts
🧠 Learnings (29)
📓 Common learnings
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Applies to src/js/{builtins,node,bun,thirdparty,internal}/**/*.{ts,js} : Use `process.platform` and `process.arch` for platform detection; these values are inlined and dead-code eliminated at build time
📚 Learning: 2025-10-16T17:32:03.074Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/install/PackageManager/PackageManagerOptions.zig:187-193
Timestamp: 2025-10-16T17:32:03.074Z
Learning: In Bun's codebase (particularly in files like src/install/PackageManager/PackageManagerOptions.zig), mixing bun.EnvVar.*.get() and bun.EnvVar.*.platformGet() for environment variable lookups is intentional and safe. The code is protected by compile-time platform checks (Environment.isWindows, etc.), and compilation will fail if the wrong function is used on the wrong platform. This pattern should not be flagged as a consistency issue.

Applied to files:

  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/npm.zig
📚 Learning: 2026-01-05T16:32:07.551Z
Learnt from: alii
Repo: oven-sh/bun PR: 25474
File: src/bun.js/event_loop/Sigusr1Handler.zig:0-0
Timestamp: 2026-01-05T16:32:07.551Z
Learning: In Zig codebases (e.g., Bun), treat std.posix.sigaction as returning void and do not perform runtime error handling for its failure. The Zig standard library views sigaction failures as programmer errors (unreachable) because they only occur with invalid signals like SIGKILL/SIGSTOP. Apply this pattern across Zig files that call sigaction (e.g., crash_handler.zig, main.zig, filter_run.zig, process.zig) and ensure failures are not handled as recoverable errors; prefer reaching an explicit unreachable/compile-time assumption when such failures are detected.

Applied to files:

  • src/install/PackageManager/PackageManagerOptions.zig
  • src/install/lockfile/Tree.zig
  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/lockfile/printer/tree_printer.zig
  • src/install/npm.zig
  • src/install/isolated_install/Installer.zig
  • src/install/PackageManager/PackageManagerLifecycle.zig
  • src/install/PackageInstaller.zig
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Applies to src/js/{builtins,node,bun,thirdparty,internal}/**/*.{ts,js} : Use `process.platform` and `process.arch` for platform detection; these values are inlined and dead-code eliminated at build time

Applied to files:

  • src/install/PackageManager/CommandLineArguments.zig
  • src/install/npm.zig
  • src/install/PackageInstaller.zig
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/src/napi/napi.zig : For each new V8 C++ method, add both GCC/Clang and MSVC mangled symbol names to the V8API struct in src/napi/napi.zig using extern fn declarations

Applied to files:

  • src/install/npm.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Zig code should be organized in `src/*.zig` for core runtime, JavaScript bindings, and package manager

Applied to files:

  • src/install/npm.zig
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Run `bun run zig:check-all` to compile Zig code on all platforms when making platform-specific changes

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-15T22:03:50.832Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/envvars.zig:135-144
Timestamp: 2025-10-15T22:03:50.832Z
Learning: In src/envvars.zig, the boolean feature flag cache uses a single atomic enum and should remain monotonic. Only the string cache (which uses two atomics: ptr and len) requires acquire/release ordering to prevent torn reads.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-16T21:24:52.779Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/crash_handler.zig:1415-1423
Timestamp: 2025-10-16T21:24:52.779Z
Learning: When a boolean EnvVar in src/envvars.zig is defined with a default value (e.g., `.default = false`), the `get()` method returns `bool` instead of `?bool`. This means you cannot distinguish between "environment variable not set" and "environment variable explicitly set to the default value". For opt-out scenarios where detection of explicit setting is needed (like `BUN_ENABLE_CRASH_REPORTING` on platforms where crash reporting defaults to enabled), either: (1) don't provide a default value so `get()` returns `?bool`, or (2) use the returned boolean directly instead of only checking if it's true.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-24T10:43:09.398Z
Learnt from: fmguerreiro
Repo: oven-sh/bun PR: 23774
File: src/install/PackageManager/updatePackageJSONAndInstall.zig:548-548
Timestamp: 2025-10-24T10:43:09.398Z
Learning: In Bun's Zig codebase, the `as(usize, intCast(...))` cast pattern triggers a Zig compiler bug that causes compilation to hang indefinitely when used in complex control flow contexts (loops + short-circuit operators + optional unwrapping). Avoid this pattern and use simpler alternatives like just `intCast(...)` if type casting is necessary.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-12-11T02:11:47.024Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 25462
File: src/ast/visitExpr.zig:1644-1695
Timestamp: 2025-12-11T02:11:47.024Z
Learning: In Bun's bundler feature flag implementation (src/ast/visitExpr.zig), the validation for feature() flag names intentionally only rejects UTF-16 strings (checking `is_utf16`) while allowing UTF-8 strings, even though the error message says "must be an ASCII string". This is the intended behavior and should not be changed to enforce strict ASCII validation.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-16T02:17:35.237Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23710
File: src/analytics.zig:15-21
Timestamp: 2025-10-16T02:17:35.237Z
Learning: In src/analytics.zig and similar files using bun.EnvVar boolean environment variables: the new EnvVar API for boolean flags (e.g., bun.EnvVar.do_not_track.get(), bun.EnvVar.ci.get()) is designed to parse and return boolean values from environment variables, not just check for their presence. This is an intentional design change from the previous presence-based checks using bun.getenvZ().

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-15T20:19:38.580Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23680
File: cmake/targets/BuildBun.cmake:822-822
Timestamp: 2025-10-15T20:19:38.580Z
Learning: In the Bun codebase, FFI is compiled with tcc (TinyCC), which barely supports C99. The headers `src/bun.js/api/FFI.h` and `src/bun.js/api/ffi-stdbool.h` are only used for FFI compilation with tcc, not for the main Bun target. Therefore, C23 compatibility concerns (such as bool/true/false keyword conflicts) do not apply to these FFI headers.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-10-17T01:21:35.060Z
Learnt from: taylordotfish
Repo: oven-sh/bun PR: 23755
File: src/bun.js/bindings/BunIDLConvert.h:79-95
Timestamp: 2025-10-17T01:21:35.060Z
Learning: In JavaScriptCore (used by Bun), the `toBoolean()` method implements ECMAScript's ToBoolean abstract operation, which is side-effect-free and cannot throw exceptions. It does not execute arbitrary JavaScript or invoke user-defined methods like Symbol.toPrimitive. Exception handling is not needed after toBoolean() calls.

Applied to files:

  • src/install/npm.zig
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/test/v8/v8.test.ts : Add corresponding test cases to test/v8/v8.test.ts using checkSameOutput() function to compare Node.js and Bun output

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-05T23:04:01.518Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2026-01-05T23:04:01.518Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : Use `bun bd test <...test file>` to run tests with compiled code changes. Do not use `bun test` as it will not include your changes.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-05T23:04:01.518Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2026-01-05T23:04:01.518Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : Use `bun:test` for files ending in `*.test.{ts,js,jsx,tsx,mjs,cjs}`. For test files without .test extension in test/js/node/test/{parallel,sequential}/*.js, use `bun bd <file>` instead of `bun bd test <file>` since they expect exit code 0.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-10-26T01:32:04.844Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 24082
File: test/cli/test/coverage.test.ts:60-112
Timestamp: 2025-10-26T01:32:04.844Z
Learning: In the Bun repository test files (test/cli/test/*.test.ts), when spawning Bun CLI commands with Bun.spawnSync for testing, prefer using stdio: ["inherit", "inherit", "inherit"] to inherit stdio streams rather than piping them.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-14T16:07:01.064Z
Learnt from: RiskyMH
Repo: oven-sh/bun PR: 24719
File: docs/bundler/executables.mdx:527-560
Timestamp: 2025-11-14T16:07:01.064Z
Learning: In the Bun repository, certain bundler features like compile with code splitting (--compile --splitting) are CLI-only and not supported in the Bun.build() JavaScript API. Tests for CLI-only features use backend: "cli" flag (e.g., test/bundler/bundler_compile_splitting.test.ts). The CompileBuildConfig interface correctly restricts these with splitting?: never;. When documenting CLI-only bundler features, add a note clarifying they're not available via the programmatic API.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-10-19T02:44:46.354Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 23798
File: packages/bun-otel/context-propagation.test.ts:1-1
Timestamp: 2025-10-19T02:44:46.354Z
Learning: In the Bun repository, standalone packages under packages/ (e.g., bun-vscode, bun-inspector-protocol, bun-plugin-yaml, bun-plugin-svelte, bun-debug-adapter-protocol, bun-otel) co-locate their tests with package source code using *.test.ts files. This follows standard npm/monorepo patterns. The test/ directory hierarchy (test/js/bun/, test/cli/, test/js/node/) is reserved for testing Bun's core runtime APIs and built-in functionality, not standalone packages.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-14T21:08:10.438Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/js/node/test/parallel/CLAUDE.md:0-0
Timestamp: 2026-01-14T21:08:10.438Z
Learning: Run Node.js compatibility tests using `bun bd <file-path>` command, not `bun bd test <file-path>`

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Applies to test/**/*.test.ts : Use `normalizeBunSnapshot` to normalize snapshot output in tests

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Applies to test/**/*.test.ts : Use Bun's Jest-compatible test runner with proper test fixtures and imports from `harness`

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Write JS builtins for Bun's Node.js compatibility and APIs, and run `bun bd` after changes

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-06T00:58:23.965Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24417
File: test/js/bun/spawn/spawn.test.ts:903-918
Timestamp: 2025-11-06T00:58:23.965Z
Learning: In Bun test files, `await using` with spawn() is appropriate for long-running processes that need guaranteed cleanup on scope exit or when explicitly testing disposal behavior. For short-lived processes that exit naturally (e.g., console.log scripts), the pattern `const proc = spawn(...); await proc.exited;` is standard and more common, as evidenced by 24 instances vs 4 `await using` instances in test/js/bun/spawn/spawn.test.ts.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-08T04:06:33.198Z
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 24491
File: test/js/bun/transpiler/declare-global.test.ts:17-17
Timestamp: 2025-11-08T04:06:33.198Z
Learning: In Bun test files, `await using` with Bun.spawn() is the preferred pattern for spawned processes regardless of whether they are short-lived or long-running. Do not suggest replacing `await using proc = Bun.spawn(...)` with `const proc = Bun.spawn(...); await proc.exited;`.

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-14T21:08:10.438Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/js/node/test/parallel/CLAUDE.md:0-0
Timestamp: 2026-01-14T21:08:10.438Z
Learning: These are Node.js compatibility tests not written by Bun and cannot be modified

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2026-01-15T03:22:50.711Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T03:22:50.711Z
Learning: Verify tests fail with `USE_SYSTEM_BUN=1 bun test <file>` and pass with `bun bd test <file>` - a test is invalid if it passes with `USE_SYSTEM_BUN=1`

Applied to files:

  • test/regression/issue/26156.test.ts
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Ensure V8 API tests compare identical C++ code output between Node.js and Bun through the test suite validation process

Applied to files:

  • test/regression/issue/26156.test.ts
🧬 Code graph analysis (1)
test/regression/issue/26156.test.ts (2)
test/js/node/module/module-resolve-filename-paths.test.js (1)
  • dirPath (42-42)
test/harness.ts (1)
  • tempDir (277-284)
🔇 Additional comments (19)
src/install/PackageInstaller.zig (3)

290-299: LGTM — libc-aware native binlink selection is wired correctly.

Passing the resolved libc into the replacement lookup matches the new platform filtering expectations.


1167-1179: LGTM — lifecycle script gating now includes libc.

This keeps lifecycle decisions consistent with libc-specific optional dependency filtering.


1362-1374: LGTM — libc propagation for trusted dependency scripts.

Good to see libc included in the optimizer’s ignore logic here as well.

src/install/npm.zig (2)

717-723: LGTM — libc matching semantics align with backward compatibility.

Treating .none/.all as compatible and handling target .all matches expected optional-dependency behavior.


784-789: LGTM — JS binding now uses runtime-detected libc.

Switching to current() keeps the JS helper consistent with the new runtime detection.

test/regression/issue/26156.test.ts (4)

23-27: LGTM — lockfile cleanup is thorough.

Removing both bun.lock and bun.lockb avoids stale resolutions between runs.


29-52: LGTM — CLI help coverage for --libc.

This ensures the flag is surfaced in user-facing help output.


54-103: LGTM — valid libc value parsing is covered.

The three accepted values are exercised with clean state between installs.


105-126: LGTM — invalid libc value handling is asserted.

Good coverage of exit code and error message content.

src/install/PackageManager/PackageManagerOptions.zig (3)

86-92: LGTM — libc option added with clear default.

The default .none plus inline comment is clear and consistent with other platform overrides.


129-132: LGTM — helper resolves effective libc cleanly.

getLibc() makes downstream call sites simpler and avoids duplicate logic.


618-623: LGTM — CLI libc resolution wired correctly.

Resolving .none to Npm.Libc.current() here keeps options consistent for the rest of the install flow.

src/install/isolated_install/Installer.zig (1)

1322-1332: Libc-aware native binlink replacement looks correct.

Plumbing target_libc into replacement selection keeps native binlink choices aligned with libc filtering.

src/install/PackageManager/PackageManagerLifecycle.zig (1)

84-88: Libc included in preinstall disable checks is correct.

This keeps preinstall state in sync with libc-aware dependency filtering.

src/install/PackageManager/CommandLineArguments.zig (3)

54-56: --libc flag addition is consistent with cpu/os overrides.

Help text is clear and matches the existing override pattern.


253-256: CLI args now store libc override for downstream options.

This cleanly mirrors cpu/os defaults and resolution flow.


1022-1044: Libc parsing mirrors cpu/os negatable handling.

Wildcard support and validation behavior look consistent.

src/install/lockfile/printer/tree_printer.zig (1)

139-146: Libc-aware disabled check keeps output consistent.

This aligns the tree printer with libc filtering decisions elsewhere.

src/install/lockfile/Tree.zig (1)

366-378: Libc-aware filtering and mismatch logging look correct.

Using target_libc here keeps filter decisions and verbose diagnostics aligned.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/install/npm.zig Resolved
Address thread safety review comment: The cached_current variable
could race if Libc.current() is called from multiple threads.

Changed to use std.once for thread-safe one-time initialization:
- cached_current_once ensures detectLibcRuntimeOnce() runs exactly once
- cached_current stores the result and is written during init

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@robobun

robobun commented Jan 16, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the thread safety review comment in commit a9ad1d5:

  • Changed from plain mutable global cached_current to use std.once for thread-safe one-time initialization
  • cached_current_once.call() ensures detectLibcRuntimeOnce() runs exactly once across all threads
  • The result is stored in cached_current which is written during initialization

This follows the same pattern used elsewhere in the codebase (e.g., src/output.zig:271).

@github-actions

Copy link
Copy Markdown
Contributor

Closing this PR because it has been inactive for more than 90 days.

@github-actions github-actions Bot closed this Apr 17, 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.

Bug: bunx installs incorrect musl binary for glibc WSL environments

1 participant