You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
toolchain post-install fixup: glibc@2.44 binding cannot resolve after 2.44.3 was published (every clean machine fails) #660
After xim:glibc@2.44.3 was published, every mcpp verb that resolves a toolchain fails on a clean
machine:
error: toolchain post-install fixup: selected RuntimeBinding glibc@2.44 requires payload
'/home/runner/.mcpp/registry/data/xpkgs/xim-x-glibc/2.44', but no installed payload is its
resolution; mcpp will not fall back to another directory entry
The binding resolves to glibc@2.44 and demands the directory xim-x-glibc/2.44 exactly. A clean
machine installs the newest of the 2.44 line — 2.44.3 — into xim-x-glibc/2.44.3, and nothing
matches.
Timeline
Last green CI run
2026-09-16 16:01 UTC
xim-pkgindex a6c2fe67 — fix(glibc): 2.44.3 (#852)
between those two
First failing CI run
2026-09-16 19:07 UTC
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.44 on 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
mcpp 2026.9.15.1 (.github/versions.env)
xlings v2026.8.17.2
Consumer: Sunrisepeak/lsp-mcpp-private, CI runs 35138626160 / 35141001192 / 35142035831
Reproduces on ubuntu-24.04 runners and on both cross-build targets
What would resolve it
Either the binding should accept a directory entry that satisfies 2.44 (2.44.3 does), or the
resolution 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.3 should have been considered a resolution of 2.44 in the first place.
mcpp then treats glibc@2.44 as 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 entry
A clean store installs the newest of the 2.44 line — 2.44.3 since 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 the v2026.8.17.2 our CI pins) into an isolated XLINGS_HOME. It still records glibc@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.44 in [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 has xim-x-glibc/2.44 on 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 exactly 2.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.2
One directory, 2.44.2. The binding wants xim-x-glibc/2.44, and no version of the package
creates that directory except 2.44 itself — 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.44
2.44
xim-x-glibc/2.44
matches, but the artifact has its loader under lib/ while the recipe declares lib64/ (openxlings/xim-pkgindex#853)
2.44.2
xim-x-glibc/2.44.2
no match
2.44.3
xim-x-glibc/2.44.3
no match
Pinning cannot fix it. I tried both: 2.44 fails the loader check, 2.44.2 installs 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.44 from 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.44 artifact "has its loader under lib/ while the recipe declares lib64/". That is wrong, and so is the upstream report it cites
(openxlings/xim-pkgindex#853, since retracted and closed). Installing xim:glibc@2.44 into an empty
store gives:
lib64 is a symlink, so the declared lib64/ld-linux-x86-64.so.2 resolves. I had read a tar -tzf | grep ld-linux listing, which cannot show a symlink whose own name lacks the pattern.
Pinning xim:glibc@2.44 is 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 on ubuntu-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 key cfg() 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-abi
host, host_os and target_os are 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:
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 because 2.44 is 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.2 and 2.44.3 install 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.
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:glibc without a version; Fetcher::resolve_xpkg_path rejects 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 only registry/data/xpkgs is not reinstalled, so a cache holding another glibc revision left the declared payload absent. The directory scan that accepted a unique 2.44.x for 2.44 concealed 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:
For consumers: the [feature-xlings.host-glibc] pin and --features host-glibc are 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.
Activity
Sunrisepeak commentedon Sep 16, 2026
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.
mcpp then treats
glibc@2.44as an exact directory name and refuses anything else:A clean store installs the newest of the 2.44 line —
2.44.3since xim-pkgindex#852 — intoxim-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 isolatedXLINGS_HOME. It still recordsglibc@2.44. So this is not an old-xlings artefact; it is whatxlings 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: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 has
xim-x-glibc/2.44on disk and keeps working. Moving that one directory aside reproducesCI'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 (adirectory named exactly
2.44). Either xlings should record the resolved version, or mcpp shouldaccept a directory that satisfies the line it asked for. A consuming project cannot bridge it.
Sunrisepeak commentedon Sep 16, 2026
Measured directly, by printing the store before anything installs:
One directory,
2.44.2. The binding wantsxim-x-glibc/2.44, and no version of the packagecreates that directory except
2.44itself — each installs under its own name. So this is not aquestion of choosing the right member of the line:
2.44xim-x-glibc/2.44lib/while the recipe declareslib64/(openxlings/xim-pkgindex#853)xim-x-glibc/2.44.2xim-x-glibc/2.44.3Pinning cannot fix it. I tried both:
2.44fails the loader check,2.44.2installs a directorythe 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 downloadalongside 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.
Sunrisepeak commentedon Sep 16, 2026
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 underlib/while the recipe declareslib64/". That is wrong, and so is the upstream report it cites(openxlings/xim-pkgindex#853, since retracted and closed). Installing
xim:glibc@2.44into an emptystore gives:
lib64is a symlink, so the declaredlib64/ld-linux-x86-64.so.2resolves. I had read atar -tzf | grep ld-linuxlisting, which cannot show a symlink whose own name lacks the pattern.Pinning
xim:glibc@2.44is therefore sound: it installs the directory the binding names, and thepost-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 on
ubuntu-24.04). The difference is what they build:mcpp build(xim:node, xim:python, xim:rust, xim:glibc@2.44)mcpp build --target aarch64-macos(xim:node, xim:python, xim:rust)The glibc payload is a property of the build host — a Linux host resolves a RuntimeBinding
whatever it builds for. But every key
cfg()accepts is evaluated against the target:host,host_osandtarget_osare all rejected. So a manifest cannot express a host-siderequirement 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:
So the pin goes in
[feature-xlings.host-glibc]and the cross-building job asks for it explicitly: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 requiresa directory of that exact name. It survives only because
2.44is still a concrete version; theday 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 resolvedversion, 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.
The declared C runtime is installed before the fixup consumes it; the…
ci: gate a moved C-runtime revision against a cache-shaped mcpp home (#…
Sunrisepeak commentedon 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.
xlings subos use <n> --sandbox, CN mirror, installing through xlings:xim:glibc@2.44.3;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.CI builds against mcpp 2026.9.17.2 (mcpp-community/mcpp#660) (#436)