Skip to content

useShellEnv: don't auto-export lib/ for libc-style bottles#85

Merged
jhheider merged 1 commit into
pkgxdev:mainfrom
tannevaled:feat/no-lib-export-for-libc
May 20, 2026
Merged

useShellEnv: don't auto-export lib/ for libc-style bottles#85
jhheider merged 1 commit into
pkgxdev:mainfrom
tannevaled:feat/no-lib-export-for-libc

Conversation

@tannevaled
Copy link
Copy Markdown
Contributor

Summary

For most projects, adding \${prefix}/lib/ to LD_LIBRARY_PATH / LIBRARY_PATH is exactly what you want: subsequent commands in the pkgx env find the bottle's shared libraries.

For projects that ship libc itself (gnu.org/glibc; musl bottles when they land) the auto-export is harmful: every executable in the env tries to load the bottle's libc.so.6, but the host's own ld-linux is the one doing the loading. When the bottle's libc is newer than what the host's ld-linux supports, every command in the env breaks:

mkdir: /lib/ld-linux-aarch64.so.1: version `GLIBC_2.35' not found
(required by /opt/gnu.org/glibc/v2.43.0/lib/libc.so.6)

This blocks gnu.org/glibc from being a usable pantry recipe — currently the only workaround is to install glibc's shared libraries into a sub-directory like lib/glibc-X.Y/ so the top lib/ doesn't contain libc.so.6. That's a hack in the recipe; the right place to fix it is here in libpkgx.

Change

Add a small hardcoded NO_LIB_EXPORT set listing projects whose lib/ and include/ must NOT be auto-added:

const NO_LIB_EXPORT: ReadonlySet<string> = new Set([
  'gnu.org/glibc',
])

For projects in this set, LIBRARY_PATH / LD_LIBRARY_PATH (set later from LIBRARY_PATH) and CPATH all skip the bottle. The archaic block at the centre of useShellEnv.ts:map() gains a single conjunction:

if (archaic && !NO_LIB_EXPORT.has(installation.pkg.project)) {
  vars.LIBRARY_PATH = compact_add(vars.LIBRARY_PATH, installation.path.join("lib").chuzzle()?.string)
  vars.CPATH = compact_add(vars.CPATH, installation.path.join("include").chuzzle()?.string)
}

Consumers that explicitly want to link against the glibc bottle do so via a sysroot route (-B, -isystem, -Wl,--dynamic-linker=…), not via env auto-population. The bottle's bin/ (getconf, ldconfig, …) still ends up in PATH normally.

Tests

Added a regression test in src/hooks/useShellEnv.test.ts asserting that gnu.org/glibc's lib/ is NOT exported while curl.se's lib/ still is (existing behaviour preserved).

Full suite: 76 passed (was 75), 0 failed.

v1 vs v2

This is the v1 implementation: the set is intentionally minimal and hardcoded. v2 should express the opt-out in the bottle's own metadata (a small .pkgx-meta.json file or similar) so the pantry can add new libc-style bottles without a coordinated libpkgx release. Happy to follow up with a v2 PR if there's interest in the direction.

Refs

🤖 Generated with Claude Code

For most projects, adding `${prefix}/lib/` to `LD_LIBRARY_PATH` /
`LIBRARY_PATH` is exactly what you want: subsequent commands in the
pkgx env find the bottle's shared libraries.

For projects that *ship libc itself* (gnu.org/glibc; musl bottles
when they land) the auto-export is harmful: every executable in the
env tries to load the bottle's libc.so.6, but the host's own
ld-linux is the one doing the loading. When the bottle's libc is
newer than what the host's ld-linux supports, every command in the
env breaks:

    mkdir: /lib/ld-linux-aarch64.so.1: version `GLIBC_2.35' not found
    (required by /opt/gnu.org/glibc/v2.43.0/lib/libc.so.6)

Add a small hardcoded `NO_LIB_EXPORT` set listing projects whose
`lib/` and `include/` must NOT be auto-added. For these projects,
LIBRARY_PATH / LD_LIBRARY_PATH (set later from LIBRARY_PATH) and
CPATH all skip the bottle. Consumers that explicitly want to link
against this glibc bottle do so via a sysroot route (`-B`, `-isystem`,
`-Wl,--dynamic-linker=…`), not via env auto-population.

This is the v1 implementation; the set is intentionally minimal and
hardcoded. v2 should express the opt-out in the bottle's own metadata
so the pantry can add new libc-style bottles without a coordinated
libpkgx release.

Refs:
- pkgxdev/pantry#12968 (gnu.org/glibc PR) — the use case. The PR
  currently works around this by installing libs under lib/glibc-X.Y/
  to keep the top lib/ free of libc.so.6. With this libpkgx change,
  glibc can ship libs at the conventional lib/ path.
- pkgxdev/pantry#5080 (mxcl's Feb 2024 glibc attempt — same root cause).

Includes a regression test that asserts gnu.org/glibc's lib/ is NOT
exported while curl.se's lib/ still is (current behaviour preserved).
Copilot AI review requested due to automatic review settings May 20, 2026 14:05
@coveralls
Copy link
Copy Markdown

Coverage Report for CI Build 26167830176

Warning

No base build found for commit cdcae9e on main.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 82.877%

Details

  • Patch coverage: 22 of 22 lines across 1 file are fully covered (100%).

Uncovered Changes

No uncovered changes found.

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 2941
Covered Lines: 2491
Line Coverage: 84.7%
Relevant Branches: 744
Covered Branches: 563
Branch Coverage: 75.67%
Branches in Coverage %: Yes
Coverage Strength: 2968.86 hits per line

💛 - Coveralls

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates useShellEnv to avoid auto-exporting lib/ and include/ paths for “libc-style” bottles (starting with gnu.org/glibc), preventing LD_LIBRARY_PATH pollution that can break execution on hosts with older ld-linux than the bottle’s glibc requires.

Changes:

  • Add a hardcoded NO_LIB_EXPORT allowlist of projects whose lib//include/ should not be auto-added to LIBRARY_PATH/CPATH (and therefore not to LD_LIBRARY_PATH).
  • Gate the existing “archaic” lib/ + include/ auto-add behind !NO_LIB_EXPORT.has(project).
  • Add regression coverage ensuring gnu.org/glibc is skipped while a normal library-bearing project (eg curl.se) is still exported.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/hooks/useShellEnv.ts Adds NO_LIB_EXPORT and skips lib//include/ auto-export for libc-shipping projects.
src/hooks/useShellEnv.test.ts Adds regression test asserting glibc’s lib/ is not added while curl’s lib/ remains added.
fixtures/projects/gnu.org/glibc/package.yml Adds fixture pantry entry so tests can resolve the gnu.org/glibc project.
fixtures/projects/curl.se/package.yml Adds fixture pantry entry so tests can resolve the curl.se project.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jhheider
Copy link
Copy Markdown
Contributor

elegant.

@jhheider jhheider merged commit 928b4cb into pkgxdev:main May 20, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants