Commit 463dedf
* docs: xlings as mcpp's runtime substrate — design and implementation plan
* fix(pack): the self-contained wrapper broke /proc/self/exe and never said so
Launching through the bundled loader makes the kernel set /proc/self/exe to
the loader. Every "find my resources next to the executable" path then
resolves against lib/ -- silently. mcpp#375 reported this as a user's own
workaround; it is in fact what mcpp's own self-contained mode produces, and
the docs explained the ELF constraint that forces the launch without ever
stating its consequence.
The ELF spec forbids $ORIGIN in PT_INTERP, so the launch itself cannot go
away. What can is the silence: the wrapper now exports MCPP_BUNDLE_DIR, and
both entry points carry it because they are documented as interchangeable.
Applications that cannot be changed are pointed at --mode vendored, where
PT_INTERP is the host loader and /proc/self/exe is correct.
* docs: retract the c_runtime axis — it answered the reporter's method, not their problem
#375 is titled "let the app link against the system libc". That is the
reporter's SOLUTION. Their problem is that the artifact cannot be distributed.
The design took the title at face value and proposed a [build] c_runtime axis
whose one new capability was host-coupled -- linking the artifact against the
host's libc.
That crosses the boundary this ecosystem exists to hold. xlings is a userspace
distribution and its hermetic policy names, first on the forbidden list, any
.so under /usr/lib* or /lib* -- libc included. mcpp should not use the host
when it does not have to.
Removing that one value leaves the axis with nothing: self-contained is
already spelled --target x86_64-linux-musl, and toolchain-coupled is today's
behaviour. It would also have created a second answerer for "may I use the
host's libc", which [build] allow_host_libs already owns.
The problem has three hermetic answers and all three already exist: emit xpkg
into the ecosystem (xlings repoints the binary at install time), a static musl
target, or pack --mode self-contained. Two of them work today; the third was
broken, and that is what the previous commit fixed. What was missing was never
a mechanism -- it was that none of the three is discoverable.
The axis is kept in the document as a rejected option rather than deleted. It
had passed 12 contract tests, 7 renderer tests and a five-assertion e2e; green
tests cannot tell you a feature should not exist, and the next person reading
#375 will have the same idea.
* feat(xlings): read the subos's own description instead of inferring it
A program needs bootstrap, discovery and configuration. xlings had the first
two and, until it grew the subos_info block, nothing for the third -- its own
module comment names the consequence by number: mcpp#352, a GLFW binary that
links fine and exits 255 because nothing told it where the GL drivers are.
mcpp is the consumer of the third one, and it reads rather than knows. That is
the property that matters: mcpp must never contain the string
LIBGL_DRIVERS_PATH, because the moment it does the graphics stack has two
owners and the next capability xlings adds becomes an mcpp code change instead
of a declaration.
Every degradation fills the `note` field and callers must print it. A subos
with no block is not exotic -- mcpp's own sandbox subos was measured in
exactly that state, 356 workspace entries and no self-description -- and
silence there is what made #352 expensive to find.
family_of duplicates a five-row mapping that xlings also has. The alternative
was asking the xlings binary, which costs a subprocess in the hot path and
fails precisely where it matters: a sandbox xlings that has not been updated.
Every row is pinned in tests, so a drift is a test failure rather than a
silent ABI disagreement.
* feat(run): a program mcpp launches gets its subos's environment
A program needs three things: it links, it finds its libraries, and it is told
where its runtime data lives. mcpp supplied the first two and nothing for the
third. xlings's graphics packages declare LIBGL_DRIVERS_PATH and friends into
the subos; `xlings subos use` applied them and `mcpp run` did not. That gap is
mcpp#352 -- a GLFW binary that links cleanly and exits 255 with no output,
because nothing ever told it where the GL drivers are.
mcpp carries whatever the subos declares and knows what none of it means. The
e2e probes a variable with no graphics meaning on purpose: naming a real one
would suggest mcpp has an opinion about it, and the moment it does the
graphics stack has two owners.
Resolved at run time rather than cached with the build. These values belong to
the subos, not to the build, so a user who switches subos between `mcpp build`
and `mcpp run` has to get the new ones; it is one file read.
The subos is derived from the toolchain binary rather than from a global, so a
toolchain inherited from another home resolves to that home's subos -- the one
whose payloads the binary was actually linked against. MCPP_SUBOS_DIR
overrides it, which is how the e2e exercises this without going near a real
subos: an earlier test wrote through a symlink and permanently broke a real
toolchain.
* docs: three ways to ship, none of which uses the host's libc
mcpp#375 asked for a supported way to make a distributable artifact and
proposed one: link against the system libc. Three routes already produce a
distributable artifact and none of them does that -- through the ecosystem
(xlings repoints the ELF at install time), a static musl target, or a bundle
carrying the toolchain's own glibc. The gap was never a mechanism. It was that
the page opened with "use mcpp pack" and never said what the alternatives
were, so the reader who wanted something else had to invent it.
The note about route A is the one that answers #375 directly: a freshly built
binary's PT_INTERP names the build machine's payload, and hand-copying that
file elsewhere fails. That is a property of hand-copying, not of the artifact
-- installed through xlings the ELF is repointed at the target's own payloads.
Saying so is what stops the next reader concluding the artifact is broken and
reaching for the host's loader to "fix" it.
* chore: 2026.8.8.1, and track xlings 2026.8.7.1
The xlings pin moves because this release consumes something new from it: the
subos_info block a subos writes to describe itself. Reading it against an
older xlings degrades quietly by design, but CI should exercise the version
that actually has it.
The bootstrap pin stays at 2026.8.6.2. It is where the self-host starts, not
what the release ships -- moving it would send every CI job looking for a
version that does not exist yet.
* fix(run): the cached fast path dropped the subos environment
`mcpp run` has two paths and only one of them had been taught about subos
declarations. The full path resolves the toolchain and applies them; the fast
path skips prepare_build entirely and built its own child environment. So a
program got its environment on the run right after a build and lost it on
every run after that -- for a GL application, "it worked once and now the
window is black", with nothing in between to attribute it to.
WHICH subos is a build property and is now recorded in the build cache. WHAT
it declares is the subos's own and is re-read on every run, so installing a
graphics stack between two runs takes effect without a rebuild. That split is
also why MCPP_SUBOS_DIR moved out of the derivation: an override means "for
this invocation", and caching one would let a single `MCPP_SUBOS_DIR=… mcpp
run` silently redirect every later run.
Found by an assertion that the test did not originally have. The first version
ran `mcpp run` once, passed, and proved nothing about the path it was written
for. The fast-path check now runs first and fails loudly if the second run did
NOT take the fast path -- without it the assertion below it is vacuous and
would keep passing after the coverage silently went away. It caught a second
defect immediately: the new cache line was written before `profile=` and
parsed after `cacheMode=`, so every entry read back as stale and the fast path
was disabled for everyone.
Two dead capability tokens, and a guard so there is no third. `# requires:
linux` and `# requires: llvm` are not capabilities run_all.sh ever sets, so
65_toolchain_runtime_dirs_for_run.sh had never executed in CI -- and it
passes. The skip line for a token that cannot exist reads exactly like the
skip line for one that legitimately does not, which is what let it sit. The
runner now refuses to start when a test declares a token outside the known
universe.
The xlings pin goes back to 2026.8.6.3. It was moved to 2026.8.7.1 for tidiness
rather than need -- subos_info degrades quietly on an older xlings by design --
and CI's fresh-sandbox jobs failed with the toolchain's own g++ exiting 127,
the signature of an interpreter that is not where the binary says it is.
Whether that is a real incompatibility is worth knowing, but not on the back of
a change that does not need it.
* fix(xlings): the env list separator is the platform's, not a literal ':'
Windows CI caught this; no amount of reading would have. resolve_env joined
and split its lists on ':', which on Windows is both the wrong separator (it
is ';') and a character that appears INSIDE every absolute path. So
de-duplication split "C:\x" into "C" and "\x", matched nothing, and the
joined value came back as "C:\...\x:C:\...\x" -- a list that grows on every
nested invocation and that no consumer can parse.
This repository has made the same mistake before, in the other direction:
find_first_of(";:") over a Windows PATH cuts at the drive-letter colon.
The three test expectations that failed were also wrong, but differently, and
the difference matters: they compared against a path JOIN while the code does
a literal substitution. The literal one is correct -- the separator inside a
declaration belongs to the subos manifest, and rewriting it to the host's
spelling would be editing a value we do not own. The assertions now say so,
and the dedup test additionally asserts the result contains NO separator at
all, which is the property that actually failed.
* fix(xlings): drop a ranges spelling that crashed the clang 20 frontend
Windows CI: `clang++: error: clang frontend command failed due to signal`,
with the diagnostic file named subos_info-*.cppm. No message beyond the
signal, so the offending construct is identified by removal rather than by a
compiler telling us.
The one exotic thing in the file was `std::ranges::find` with a member-pointer
projection into std::pair; `std::ranges::sort` went with it for the same
reason. Both are replaced by plain loops, which nothing here needed to be
fancier than.
Ruled out first: importing mcpp.platform, added in the previous commit and the
only other change to this file between the run that failed a test assertion
and the run that crashed the compiler. Four modules already import
mcpp.libs.json and mcpp.platform together (bmi_cache, stdmod, post_install,
prepare), so that combination is not it.
Stated plainly because it matters for the next person: this is a hypothesis
confirmed only by CI going green, not by a local reproduction. The crash needs
clang 20.1.7 targeting MSVC and I have no such host.
---------
Co-authored-by: speak-agent <x.d2learn.org@gmail.com>
1 parent 8783350 commit 463dedf
15 files changed
Lines changed: 2314 additions & 14 deletions
File tree
- .agents/docs
- docs
- zh
- src
- build
- pack
- xlings
- tests
- e2e
- unit
Lines changed: 597 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 840 additions & 0 deletions
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
7 | 40 | | |
8 | 41 | | |
9 | 42 | | |
| |||
128 | 161 | | |
129 | 162 | | |
130 | 163 | | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
131 | 195 | | |
132 | 196 | | |
133 | 197 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
6 | 32 | | |
7 | 33 | | |
8 | 34 | | |
| |||
120 | 146 | | |
121 | 147 | | |
122 | 148 | | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
123 | 175 | | |
124 | 176 | | |
125 | 177 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
23 | 25 | | |
24 | 26 | | |
25 | 27 | | |
| |||
60 | 62 | | |
61 | 63 | | |
62 | 64 | | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
63 | 71 | | |
64 | 72 | | |
65 | 73 | | |
| |||
139 | 147 | | |
140 | 148 | | |
141 | 149 | | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
142 | 160 | | |
143 | 161 | | |
144 | 162 | | |
| |||
167 | 185 | | |
168 | 186 | | |
169 | 187 | | |
170 | | - | |
| 188 | + | |
| 189 | + | |
171 | 190 | | |
172 | 191 | | |
173 | 192 | | |
| |||
182 | 201 | | |
183 | 202 | | |
184 | 203 | | |
185 | | - | |
| 204 | + | |
186 | 205 | | |
187 | 206 | | |
188 | 207 | | |
| |||
210 | 229 | | |
211 | 230 | | |
212 | 231 | | |
| 232 | + | |
213 | 233 | | |
214 | 234 | | |
215 | 235 | | |
| |||
287 | 307 | | |
288 | 308 | | |
289 | 309 | | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
290 | 359 | | |
291 | 360 | | |
292 | 361 | | |
| |||
398 | 467 | | |
399 | 468 | | |
400 | 469 | | |
| 470 | + | |
401 | 471 | | |
402 | 472 | | |
403 | 473 | | |
404 | 474 | | |
405 | 475 | | |
406 | | - | |
| 476 | + | |
| 477 | + | |
407 | 478 | | |
408 | 479 | | |
409 | 480 | | |
| |||
754 | 825 | | |
755 | 826 | | |
756 | 827 | | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
757 | 847 | | |
758 | 848 | | |
759 | 849 | | |
| |||
827 | 917 | | |
828 | 918 | | |
829 | 919 | | |
| 920 | + | |
| 921 | + | |
830 | 922 | | |
831 | 923 | | |
832 | 924 | | |
| |||
1213 | 1305 | | |
1214 | 1306 | | |
1215 | 1307 | | |
| 1308 | + | |
| 1309 | + | |
| 1310 | + | |
1216 | 1311 | | |
1217 | 1312 | | |
1218 | 1313 | | |
| |||
1283 | 1378 | | |
1284 | 1379 | | |
1285 | 1380 | | |
| 1381 | + | |
| 1382 | + | |
| 1383 | + | |
| 1384 | + | |
1286 | 1385 | | |
1287 | 1386 | | |
1288 | 1387 | | |
| |||
0 commit comments