Repository navigation
a target the toolchain cannot serve is served by the host, silently #507
Description
mcpp build --target x86_64-windows-gnu on a machine with no mingw payload does not install one and does not refuse. It uses the native gcc, reports the effective triple as the host's, and the build fails much later inside the sources.
Measured
CI, 2026-08-25, mcpp 2026.8.25.1, mcpplibs/openkal-windows. The runner had installed exactly one toolchain:
First run no toolchain configured — installing gcc@16.1.0 (glibc, native ABI) as default
Then:
Target x86_64-windows-gnu → x86_64-unknown-linux-gnu
kernel-abi openkal (openkal-windows@0.1.5, graph)
…
src/stream.cpp:68:9: error: 'GetFileType' was not declared in this scope
src/stream.cpp:69:9: error: 'FlushFileBuffers' was not declared in this scope
src/stream.cpp:70:33: error: 'GetLastError' was not declared in this scope
x86_64-windows-gnu → x86_64-unknown-linux-gnu is the whole defect in one line: the target that was asked for and the target that was resolved are different operating systems, and nothing said so.
The same shape reaches the linker in mcpplibs/openkal-uefi, whose job asks for the same triple:
…/xim-x-binutils/2.42/bin/ld: unrecognized option '--subsystem'
collect2: error: ld returned 1 exit status
The control
On a machine that has the payload, the same commit and the same command are correct:
Resolved gcc@16.1.0 → x86_64-windows-gnu → …/xim-x-mingw-cross-gcc/16.1.0/bin/x86_64-w64-mingw32-g++
Target x86_64-windows-gnu → x86_64-w64-windows-gnu
Finished dev [unoptimized + debuginfo] in 0.11s
So the resolution is right when the payload exists and degrades to the host when it does not.
Why the degradation is not acceptable here
The consumer's CI is written expecting the lazy install to happen — its own comment says so:
every row of this matrix is a machine that has never targeted this triple, which is precisely where mcpp's lazy install of the target C library shows. The first build compiles sources needing its headers before they exist; the second has them.
It runs the build twice for that reason. Neither run installed a mingw payload.
Either outcome would be fine; silence is not:
- install the payload the target row names, as the consumer expects, or
- refuse, naming the target and the payload that is missing.
What must not happen is compiling Windows sources for Linux and reporting it as an undeclared identifier — a message that names a symbol rather than the decision that produced it.
Not a regression from a recent release
x86_64-windows-gnu → x86_64-unknown-linux-gnu appears identically under 2026.8.24.6 and 2026.8.25.1.
Related: #504 is the reporting side of the same confusion — toolchain list answers "can a payload serve this" and presents it as "can this be built".
Activity
Sunrisepeak commentedon Aug 25, 2026
Fixed in 2026.8.25.2 (#506), both halves.
Refuse — the requested target and the resolved one must name one operating system. The report already carried the evidence; this asserts on it rather than deriving the question again:
Scope is the OS only —
x86_64-windows-gnu → x86_64-w64-windows-gnuis the normalisation that line reports, and refusing on the whole triple would reject every correct cross build.Install — the mechanism behind the silent fallback turned out to be narrower than this issue described, and the cross-validation channel is what surfaced it:
The first-run branch answers "this machine has no toolchain, give it one" and the answer is a host payload;
--targetwas never read there.autoInstall=truewas always present on the payload path — it was simply never reached. The branch now feeds into that path instead of bypassing it.e2e 293 asserts both directions and was verified to fail against the pre-fix binary. Seven ecosystem repositories were built against this before the release and again after it, green both times.