Repository navigation
toolchain post-install fixup: glibc@2.44 binding cannot resolve after 2.44.3 was published (every clean machine fails) #660
Description
Activity
Root cause located, and it rules out the two workarounds a consuming project might try.
The binding is recorded by xlings, as a line name, not a version.
// <registry>/subos/default/.xlings.json "subos_info": { "created_by": "xlings 2026.9.16.1", "runtime": "glibc@2.44", "host_glibc": "2.39" }
mcpp then treats
glibc@2.44as an exact directory name and refuses anything else:error: toolchain post-install fixup: selected RuntimeBinding glibc@2.44 requires payload '.../xim-x-glibc/2.44', but no installed payload is its resolution; mcpp will not fall back to another directory entryA clean store installs the newest of the 2.44 line —
2.44.3since xim-pkgindex#852 — into
xim-x-glibc/2.44.3, and nothing matches.Upgrading xlings does not help. I created a fresh subos with the current xlings
(2026.9.16.1, a month newer than thev2026.8.17.2our CI pins) into an isolated
XLINGS_HOME. It still recordsglibc@2.44. So this is not an old-xlings artefact; it is what
xlings writes today.Pinning glibc does not help either, and makes it worse. Declaring
xim:glibc@2.44in
[xlings.workspace]installs the directory the binding wants, and then:Linux: payload '.../xim-x-glibc/2.44' is stale/incomplete: no dynamic loader was found under lib64/ or lib/ macOS: xlings install xim:glibc@2.44 (a C library that platform has no use for)2.44 is the version whose missing default directory 2.44.3 exists to fix, so the pin installs a
payload the fixup then rejects for a second reason. Five platforms failed instead of three.Why it is invisible to developers. A machine that installed glibc before 2.44.3 was published
still hasxim-x-glibc/2.44on disk and keeps working. Moving that one directory aside reproduces
CI's failure locally in seconds — which is how the above was measured.So the disagreement is between what xlings records (
glibc@2.44, a line) and what mcpp requires (a
directory named exactly2.44). Either xlings should record the resolved version, or mcpp should
accept a directory that satisfies the line it asked for. A consuming project cannot bridge it.Measured directly, by printing the store before anything installs:
What glibc the restored store has 2.44.2: /home/runner/.mcpp/registry/data/xpkgs/xim-x-glibc/2.44.2/lib/ld-linux-x86-64.so.2One directory,
2.44.2. The binding wantsxim-x-glibc/2.44, and no version of the package
creates that directory except2.44itself — each installs under its own name. So this is not a
question of choosing the right member of the line:installed directory binding wants 2.442.44 xim-x-glibc/2.44matches, but the artifact has its loader under lib/while the recipe declareslib64/(openxlings/xim-pkgindex#853)2.44.2 xim-x-glibc/2.44.2no match 2.44.3 xim-x-glibc/2.44.3no match Pinning cannot fix it. I tried both:
2.44fails the loader check,2.44.2installs a directory
the binding will not look at.Why it used to work. Runs green before 2026-09-16 16:01 restored a cache that still contained
xim-x-glibc/2.44from an earlier install, so the binding found its directory; the 2.44.2 download
alongside it was incidental. Once that cache rotated out, nothing recreates the directory, and the
project has no way to ask for it — the only version that would create it is the one #853 makes
unusable.So a consuming project is stuck between the two issues: #660 requires a directory named
2.44, and
#853 makes the only package that creates it fail the post-install check.Correcting my own two comments above, and adding the finding that actually unblocked it.
A consuming project can bridge it — I was wrong about that. The bridge is ugly, but it works,
and the reason it took so long to find is itself a gap worth reporting.First, a retraction. The second comment's table says the
2.44artifact "has its loader under
lib/while the recipe declareslib64/". That is wrong, and so is the upstream report it cites
(openxlings/xim-pkgindex#853, since retracted and closed). Installingxim:glibc@2.44into an empty
store gives:lrwxrwxrwx lib64 -> lib .../2.44/lib/ld-linux-x86-64.so.2lib64is a symlink, so the declaredlib64/ld-linux-x86-64.so.2resolves. I had read a
tar -tzf | grep ld-linuxlisting, which cannot show a symlink whose own name lacks the pattern.
Pinningxim:glibc@2.44is therefore sound: it installs the directory the binding names, and the
post-install check passes.What was left, and it is a mcpp gap of its own. With the pin in
[target.'cfg(os = "linux")'.xlings.workspace], one CI job passed and two failed — same commit,
same runner OS (all three onubuntu-24.04). The difference is what they build:job command provisioning list result unit tests mcpp build(xim:node, xim:python, xim:rust, xim:glibc@2.44)pass cross-build mcpp build --target aarch64-macos(xim:node, xim:python, xim:rust)fail The glibc payload is a property of the build host — a Linux host resolves a RuntimeBinding
whatever it builds for. But every keycfg()accepts is evaluated against the target:$ mcpp build --strict error: [target.'cfg(host_os = "linux")'] names 'host_os' in its cfg() predicate, which mcpp does not know, so the section never applies (ignored). Supported keys: arch, env, family, os, c++-abi, c-abi, compiler, compiler-runtime, kernel-abihost,host_osandtarget_osare all rejected. So a manifest cannot express a host-side
requirement at all — which is a problem beyond this issue, since a host glibc, a host toolchain
payload and a host build tool are all things a cross-compiling project may legitimately need.The bridge, for anyone else stuck here: features are not target-derived. Verified with a
probe package that does not exist, so the only possible output is proof that provisioning ran:$ mcpp build --target aarch64-macos --features hostprobe Provisioning [xlings.workspace] entries (xim:definitely-no-such-pkg-xyz)So the pin goes in
[feature-xlings.host-glibc]and the cross-building job asks for it explicitly:mcpp build --features host-glibc --profile release --target aarch64-macos -> Provisioning [xlings.workspace] entries (xim:node, xim:python, xim:rust, xim:glibc@2.44) -> Downloading xim:glibc@2.44 40.4 MB (resolves to 2.44, not 2.44.3)Both cross-build jobs now pass.
That leaves two separate asks:
-
This issue stands. xlings records the binding as a line name (
glibc@2.44) and mcpp requires
a directory of that exact name. It survives only because2.44is still a concrete version; the
day that entry is retired, every pin like mine breaks at once and there is no replacement, since
2.44.2and2.44.3install under their own names. Either xlings should record the resolved
version, or mcpp should accept a directory that satisfies the line it asked for. -
A host predicate. Without one, "the host needs X" can only be said by feature flags passed at
every cross-compiling call site — which is a workaround wearing a feature's clothes, and is
invisible to anyone reading the manifest alone.
Happy to open (2) as its own issue if you would rather keep this one to the binding.
-
- added a commit that references this issue
on Sep 17, 2026 - added a commit that references this issue
on Sep 17, 2026 Fixed in mcpp 2026.9.17.2 (#663), released and indexed.
The cause was not the version-line binding. mcpp never installed the glibc payload its default SubOS declares. The two loops meant to do it passed
xim:glibcwithout a version;Fetcher::resolve_xpkg_pathrejects such a target, and the rejection was logged at debug level and discarded. The payload therefore existed only when xlings installed it as a dependency of a toolchain. A toolchain restored from a CI cache that keeps onlyregistry/data/xpkgsis not reinstalled, so a cache holding another glibc revision left the declared payload absent. The directory scan that accepted a unique2.44.xfor2.44concealed this until #852 put two revisions side by side. Upgrading xlings alone does not fix it: xlings 2026.9.14.1 with a cache-shaped store fails the same way.Change. mcpp installs
xim:glibc@<declared version>before the first toolchain fixup that consumes it (gcc and llvm payloads on Linux only; no process starts when the payload is present). The payload lookup is exact. Offline, the error names the coordinate to provide. The xlings shipped beside the mcpp executable is now acquired ahead of the PATH xlings.Verified.
- e2e 737: red on 2026.9.17.1, green on 2026.9.17.2.
xlings subos use <n> --sandbox, CN mirror, installing through xlings:- fresh home: green;
- cache shape, offline: error names
xim:glibc@2.44.3; - cache shape, online: installs 2.44.3 and runs;
- index dependency: green.
- ci: gate a moved C-runtime revision against a cache-shaped mcpp home (mcpp#660) openxlings/xim-pkgindex#855 adds a gate for future runtime revisions. It was red with 2026.9.17.1 and green with 2026.9.17.2 on the #852 base/head pair, in Actions.
For consumers: the
[feature-xlings.host-glibc]pin and--features host-glibcare no longer needed once CI installs 2026.9.17.2. The host-predicate question (cfg(host_os)) is independent and would be better tracked in its own issue.
Summary
After
xim:glibc@2.44.3was published, every mcpp verb that resolves a toolchain fails on a cleanmachine:
The binding resolves to
glibc@2.44and demands the directoryxim-x-glibc/2.44exactly. A cleanmachine installs the newest of the 2.44 line —
2.44.3— intoxim-x-glibc/2.44.3, and nothingmatches.
Timeline
xim-pkgindexa6c2fe67 —fix(glibc): 2.44.3(#852)Every run since fails the same way.
What makes it clear this is the binding, not a project change
Three jobs in one run failed with the identical error while downloading three unrelated things:
Anything that triggers toolchain resolution hits it. No change in the consuming project can produce
that pattern.
Why it does not reproduce on a developer machine
A machine that installed glibc before 2.44.3 was published already has
xim-x-glibc/2.44on disk,so the binding finds its directory and the build succeeds. Only a clean store — CI, a new
contributor, a fresh container — installs 2.44.3 and fails. Locally green, CI red, from the same
commit.
Environment
.github/versions.env)Sunrisepeak/lsp-mcpp-private, CI runs 35138626160 / 35141001192 / 35142035831What would resolve it
Either the binding should accept a directory entry that satisfies
2.44(2.44.3 does), or theresolution should name the exact version it wants so the store installs that one. The error already
says "mcpp will not fall back to another directory entry", so the refusal looks deliberate — the
question is whether
2.44.3should have been considered a resolution of2.44in the first place.