Commit 655e58d
authored
refactor(toolchain): one producer for host-compile flags; build.mcpp gains MSVC modules (2026.8.2.2) (#334)
* chore: bump to 2026.8.2.2 + host-compile design/plan docs
* refactor(toolchain): one producer for host-compile flags
Three places assembled the same host-compile flags independently:
flags.cppm for the main build, stdmod.cppm for the std module, and
build_program.cppm for build.mcpp. The resolvers (linkmodel, clang driver
model) were already shared; the ASSEMBLY was not, because the seam only
produced strings and the one consumer that needs argv — build.mcpp, which
execs directly with no shell — could not use it and hand-wrote the whole
thing a second time.
That split is where PR#332's batch came from. Every bug in it was the same
sentence: flags.cppm knew about quoting / the macOS deployment target / the
MSVC dialect, and the other two did not. A 0.0.9x fix had already corrected
the same file once for the same reason (musl->static re-derived), and
stdmod.cppm carried a comment instructing the reader to keep it in sync with
flags.cppm by hand — the failure mode this repo wrote check_version_pins.sh
to stop.
Tokens are now the source of truth and strings are rendered from them, not
the reverse. mcpp.toolchain.hostflags composes the resolvers once; the three
consumers render with ninja escaping, shell quoting, or not at all.
The knobs on HostFlagOptions are documented divergences, not switches to
preserve accidents: the host helper keeps trusting clang's cfg on
macOS/Windows (the macOS link needs libc++abi/unwind handling the main
build's needs_explicit_libcxx path owns), the std module states
-stdlib=libc++ explicitly (flags.cppm cannot — the same string feeds C
compiles), and binutils -B / runtime dirs belong only to the one-shot host
link.
Pure refactor, verified as such: the global cxxflags/cflags/ldflags lines in
build.ninja AND stdmod's std_build_commands are byte-identical before and
after, under both gcc@16.1.0 and llvm@22.1.8, each from a clean target and
dep cache. Byte-identity is not cosmetic here — std_build_commands feeds the
std cache directory name, so a reordered flag would invalidate every user's
std BMIs for no gain.
hostflags lives in its own module rather than inside build_program.cppm's
anonymous namespace: PR#332 established that adding a function there can
miscompile a neighbouring one under clang 22.1.8 + C++20 modules + -O2.
* feat(build.mcpp): named modules wherever mcpp can build a host program
`import mcpp;` / `import std;` in a build.mcpp used to fail under native MSVC
with "not yet supported", and the stated reason was that mcpp had not wired up
cl.exe's .ifc pipeline. That reason was wrong: the main build has compiled
named modules with cl.exe for a while — e2e 99 produces real .ifc artifacts on
every Windows CI run, and ninja_backend has emitted /interface /TP /ifcOutput
and /scanDependencies all along. What was missing was only that build.mcpp
hand-rolled its own compile path and never read those tables.
build_mcpp_module now dispatches on BmiTraits + CommandDialect — the same rows
the main build uses — so cl.exe needed no new pipeline, just the row that was
already there. The gate is gone.
bmi_reference_tokens covers the shape difference the traits do not have to
care about: `-fmodule-file=std=<p>` is one argv word, `/reference std=<p>` is
two, and only an argv consumer notices. The traits keep storing the string
form for the ninja channel.
The capability-parity guard in test_hostflags.cpp is the part meant to
outlast this change: it walks every CompilerId and fails if a family is
missing a dialect row, a module row, or host flags. Stating "build.mcpp has no
capability list of its own" in prose is exactly how the MSVC gate outlived its
own justification.
* fix(toolchain): keep -stdlib=libc++ where the std module has always put it
Placing it after the libc++ -isystem flags instead of right after
-nostdinc++ changed the std module's command string, and that string is part
of the std cache identity (std_build_commands feeds the cache directory
name) — every user's std BMIs would have been invalidated for a reordering
that buys nothing. Caught only because the first byte-equality check scanned
the whole shared cache directory and compared stale entries alongside fresh
ones; the check now wipes the std cache first so it compares like with like.
Also moves the bundled mcpp module's compile out of build_program.cppm's
anonymous namespace into mcpp.build.hostprogram. Growing that namespace
reproduced PR#332's clang miscompilation exactly — Segmentation fault: 11 on
every macOS build.mcpp e2e, in contract_env, which this change never touched.
* test(hostflags): pin the rendered flag strings
Byte-equality with what earlier releases emitted is a compatibility surface
here, not an implementation detail: stdmod folds its compile command into
std_build_commands and the std cache directory name is derived from the
metadata containing it, so a reordered flag invalidates every user's std BMIs.
Verifying that by inspecting the cache after a build turned out to be
unreliable — the cache is shared and accumulates entries from every toolchain
used since, so the first check compared stale entries alongside fresh ones and
passed while the string had in fact moved. These tests assert the spelling
directly from a synthetic model, deterministically, and keep asserting it.
* fix(build.mcpp): state the deployment target even when trusting clang's cfg; drop -x for cl
Two failures the local runs could not see, both the same shape — a branch
that was dead while the MSVC gate existed, or a platform this machine is not.
host_compile_tokens returned early on the trust-cfg path, which on macOS IS
the build.mcpp path: no clang flags and no deployment target, so the std BMI
(built for 14.0) was rejected by a TU compiled without it. Trusting the cfg
means contributing no include paths or stdlib selection — not contributing
nothing. The deployment target is emitted regardless now, which is what the
hand-written host_base_flags did deliberately ("FIRST and unconditionally")
before this refactor absorbed it.
The `-x none` before the module objects was unconditional and harmless only
while cl.exe could not reach it. Removing the module gate made the dead
branch live, and cl answered `D9002: ignoring unknown option '-x'` — after
compiling the .ifc and reaching the link, which is further than build.mcpp
has ever gone under MSVC.
* fix(toolchain): per-file C++ force for cl, so object inputs stay objects
cl.exe rejected the std and mcpp module objects with
"C2018: character 'U+10' is not permitted here" — it was compiling them as
C++ source. `/TP` is not the counterpart of `-x c++`: GNU's is positional and
lasts until `-x none`, cl's applies to EVERY input on the line, so the
objects that follow are fed to the C++ frontend.
The dialect now carries the per-FILE form (`/Tp<file>`) alongside the
positional one, and the build.mcpp compile uses whichever the driver has.
That is the same structural difference the row already records for libFlag
(prefix vs suffix): the two drivers are not spelling the same concept
differently, they have different concepts.
* fix(build.mcpp): reference the std BMI through the token helper too
cl answered "C2230: could not find module 'std'" because the std reference
was still built by string concatenation, producing one argv element with a
space inside it. bmi_reference_tokens existed for exactly this and was only
applied to the bundled mcpp module.
Same shape for the third time — a table entry written for the ninja STRING
channel concatenated into an argv element — so it now has a test that covers
every family and both spellings, plus one for the language-force tokens. The
compiler's own diagnostics name neither the flag nor the reason, which is why
this kept costing a CI round each time.1 parent 7169332 commit 655e58d
15 files changed
Lines changed: 1429 additions & 352 deletions
File tree
- .agents/docs
- docs
- zh
- src
- build
- toolchain
- tests
- e2e
- unit
Lines changed: 240 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 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 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 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 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
0 commit comments