Skip to content

feat(toolchain): gcc@system is rejected, and says what to do instead - #441

Closed
Sunrisepeak wants to merge 1 commit into
mainfrom
feat/system-origin-is-msvc-only
Closed

feat(toolchain): gcc@system is rejected, and says what to do instead#441
Sunrisepeak wants to merge 1 commit into
mainfrom
feat/system-origin-is-msvc-only

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

@system is available for MSVC only, and that is deliberate rather than incidental.

xlings depends on the host as little as it can: a toolchain comes from a payload, which is what makes "the manifest says 14.44.35207" true on every machine instead of on the one that happened to have it. Offering gcc@system invites that uncertainty back, and the alternative is one command away.

MSVC is the exception because Windows is: Visual Studio is frequently already installed and cannot always be redistributed, so refusing to use it would mean refusing to build. That is a platform fact, not an instance of a general capability — so it is not generalised.

Why reject rather than leave unimplemented

Until now gcc@system parsed into a spec that meant "no version", then failed somewhere further in with a message about something else. It is now refused at the parse, with the version form and the reason for the one exception:

'gcc@system' is not a thing — mcpp does not build with the machine's own gcc.
  A toolchain comes from a payload, so a manifest means the same thing on every machine.
  Name a version instead: `gcc@<version>` (`mcpp toolchain list` shows what is available).
  Only `msvc@system` exists, because Visual Studio cannot always be redistributed.

The test asserts the refusal and that the message names the alternative — a refusal that does not is just a wall. Verified against a guard that never fires.

Follows the architecture review (.agents/docs/2026-08-16-toolchain-architecture-review.md §1). That section's first draft proposed generalising @system to all families; it was wrong, and the doc now records both the correction and the reason.

`@system` is available for MSVC only, and that is deliberate rather than
incidental. xlings depends on the host as little as it can: a toolchain comes
from a payload, which is what makes "the manifest says 14.44.35207" true on
every machine instead of on the one that happened to have it. Offering
`gcc@system` invites that uncertainty back, and the alternative is one
command away.

MSVC is the exception because Windows is. Visual Studio is frequently already
installed and cannot always be redistributed, so refusing to use it would
mean refusing to build. A platform fact, not a general capability -- so it is
not generalised.

Until now the spelling was merely unimplemented, which means it failed later,
somewhere else, with a message about something else. It is now refused at the
parse, with the version form and the reason for the one exception.

Test asserts the refusal AND that the message names the alternative -- a
refusal that does not is just a wall. Verified against a guard that never
fires.
@Sunrisepeak

Copy link
Copy Markdown
Member Author

Closing — this solves a problem I invented.

gcc@system never existed as a feature or a request. It came from the first draft of my own architecture review, where I read is_system_toolchain() being gated on Family::Msvc as an asymmetry to remove and proposed generalising it. That was backwards: xlings is a user-space OS and mcpp is built to minimise host dependence, so a host-provided toolchain is the thing the design avoids, not a capability it lacks. msvc@system exists because Visual Studio cannot always be redistributed — a platform concession, not a pattern.

Having been corrected on the direction, I then wrote a rejection for the spelling I had invented. That is scope created out of my own mistake, and the code is not free: it is a special case in the parser for a spelling nobody writes, which already fails today (it resolves to xim:gcc@system and is not found).

It also asserts something false. The message says "Only msvc@system exists", but prepare.cppm:1376 has a deliberate bare-system escape hatch:

} else if (tcSpec.has_value() && *tcSpec == "system") {
    // Explicit user opt-in to system PATH compiler — kept as escape hatch.

So the one place host dependence is genuinely offered is spelled system, with no family — and I was about to ship a message denying it.

The review doc's §1 is being corrected to drop the invented framing entirely. What survives there is the finding that was real and independent of it: one platform exception spread across 26 branches, three duplicated spellings of the same layout rule, and a resolution comment claiming 4 steps for a chain with 9 inputs.

@Sunrisepeak
Sunrisepeak deleted the feat/system-origin-is-msvc-only branch August 16, 2026 13:09
Sunrisepeak added a commit that referenced this pull request Aug 16, 2026
…#437) (#442)

* docs(review): §1's premise was invented — correct it

The first draft read `is_system_toolchain()` being gated on `Family::Msvc`
as an asymmetry and proposed supporting `gcc@system`. That is backwards.
xlings is a user-space OS and mcpp is built on it to keep host dependence to
a minimum: a toolchain comes from a payload, which is what makes "the
manifest says 14.44.35207" true on every machine rather than on the one that
happened to have it. `msvc@system` is a Windows concession — Visual Studio is
often already installed and cannot always be redistributed — not a general
capability with three families missing.

`gcc@system` was never a feature or a request. I invented it, and after being
corrected on the direction I wrote an explicit rejection for the spelling I
had invented, which is scope grown out of my own mistake. That PR (#441) is
closed.

Its message was also factually wrong: it claimed "only msvc@system exists",
while prepare.cppm:1376 keeps a deliberate bare-`system` escape hatch for the
PATH compiler. The one place host dependence IS offered is spelled with no
family at all — recorded here so the next review does not read it as a
missing capability either.

What survives is the finding that never depended on any of that: one platform
exception spread across 26 branches (13 in lifecycle.cppm, 13 in
prepare.cppm, zero for gcc/llvm/mingw), three duplicated spellings of the
same layout rule, and a resolution comment claiming 4 steps for a chain with
9 inputs. The remedy is to resolve Origin ONCE and dispatch on it — contain
the exception, do not spread or generalise it.

* fix(toolchain): the host helper must link the way the main build does (#437)

On macOS a project builds and its `build.mcpp` does not — same toolchain,
same environment, two link paths disagreeing.

The main build deliberately forces `-fuse-ld=lld` there, and flags.cppm says
why in its own words: "Xcode 15.4's ld aborting at launch on macos-14 CI when
its libc++ resolution was diverted". The host helper takes the trust-cfg
branch in hostflags.cppm, which returns NO link tokens, so clang++ falls back
to Xcode's /usr/bin/ld. That binary is itself a C++ Mach-O linked against
libc++, running inside the DYLD_* the payload toolchain sets up, so dyld
resolves ITS libc++ to the payload's copy — which lacks __ZdaPv, and ld
aborts before linking anything.

The cfg picks runtimes; it has never picked a linker. So trusting it is right
and incomplete, and the fix is to keep trusting it while still naming the
linker on macOS. lld ships with the very toolchain doing the compile, so it
cannot be diverted to a libc++ it was not built against.

This is the same shape as the rest of this round: one rule with two
implementations, one of which knows something the other does not — like the
three duplicated spellings in the review's §1 and doctor's fourth copy of the
payload layout in §3b.

Root cause and reasoning recorded in
.agents/docs/2026-08-13-build-optimization-status.md §9a-3, which previously
stopped at "not guessing further, cannot reproduce on Linux"; the review doc
picks it up as §3e.

No unit test: the decision is inside `if constexpr (is_macos)` and compiles
out on the platform CI would run one on, so the test could not fail. The gate
is the macOS e2e suite, where 11 tests carry a build.mcpp.

* docs(review): record what landed today and what deliberately did not

The four open items all move a spec/schema layer or cross repositories, and
none of them belongs in a release window. Each is written up to the point
where it can be started directly.

---------

Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
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.

2 participants