@@ -16,6 +16,7 @@ import mcpp.build.plan;
1616import mcpp.platform;
1717import mcpp.toolchain.clang;
1818import mcpp.toolchain.detect;
19+ import mcpp.toolchain.dialect;
1920import mcpp.toolchain.linkmodel;
2021import mcpp.toolchain.provider;
2122import mcpp.toolchain.registry;
@@ -122,10 +123,13 @@ std::string atomic_link_flag(const std::vector<std::filesystem::path>& linkDirs,
122123CompileFlags compute_flags (const BuildPlan& plan) {
123124 CompileFlags f;
124125
125- // ProviderCapabilities: centralised query point for per-toolchain decisions.
126- // Prefer caps.* checks over ad-hoc is_clang()/is_musl_target() calls for
127- // any new branching added to this function.
126+ // Central query points for per-toolchain decisions — prefer these over
127+ // ad-hoc is_clang()/is_gcc() calls:
128+ // caps — what the toolchain can do (scan-deps, stdlib id, …)
129+ // d — how a flag is SPELT (GNU "-I" vs MSVC "/I")
130+ // traits — BMI mechanics + module-flag spellings
128131 auto caps = mcpp::toolchain::capabilities_for (plan.toolchain );
132+ const auto & d = mcpp::toolchain::dialect_for (plan.toolchain );
129133
130134 // macOS minimum supported OS version for produced binaries.
131135 // Precedence: MACOSX_DEPLOYMENT_TARGET env (explicit per-invocation
@@ -152,7 +156,7 @@ CompileFlags compute_flags(const BuildPlan& plan) {
152156 std::string include_flags;
153157 for (auto & inc : plan.manifest .buildConfig .includeDirs ) {
154158 auto abs = inc.is_absolute () ? inc : (plan.projectRoot / inc);
155- include_flags += " -I " + escape_path (abs);
159+ include_flags += std::format ( " {}{} " , d. includePrefix , escape_path (abs) );
156160 }
157161
158162 // Sysroot / payload paths — resolved ONCE by the toolchain link model
@@ -208,11 +212,11 @@ CompileFlags compute_flags(const BuildPlan& plan) {
208212 f.sysroot = link_toolchain_flags;
209213 }
210214
211- // Binutils -B flag
215+ // Binutils -B flag — a GCC/libstdc++ payload concern (musl bundles its
216+ // own as/ld; Clang and MSVC never take an external binutils).
212217 bool isMuslTc = mcpp::toolchain::is_musl_target (plan.toolchain );
213- bool isClang = mcpp::toolchain::is_clang (plan.toolchain );
214218 std::filesystem::path binutilsBin;
215- if (!isMuslTc && !isClang ) {
219+ if (!isMuslTc && caps. stdlib_id == " libstdc++ " ) {
216220 auto ar = mcpp::toolchain::archive_tool (plan.toolchain );
217221 if (!ar.empty ())
218222 binutilsBin = ar.parent_path ();
@@ -231,8 +235,8 @@ CompileFlags compute_flags(const BuildPlan& plan) {
231235 // unless the profile pins -O0.
232236 auto & prof = plan.manifest .buildConfig ;
233237 std::string opt_flag = isMuslTc && prof.optLevel != " 0"
234- ? " -Og" : (" -O " + prof.optLevel );
235- if (prof.debug ) opt_flag += " -g " ;
238+ ? " -Og" : std::format (" {}{} " , d. optPrefix , prof.optLevel );
239+ if (prof.debug ) opt_flag += std::format ( " {} " , d. debugFlags ) ;
236240 if (prof.lto ) opt_flag += " -flto" ;
237241
238242 // User link flags
@@ -247,20 +251,25 @@ CompileFlags compute_flags(const BuildPlan& plan) {
247251 plan.manifest .buildConfig .cStandard .empty () ? " c11" : plan.manifest .buildConfig .cStandard ;
248252
249253 // Assemble
250- // -fmodules is a GCC-only flag; Clang uses a different module ABI and does
251- // not need it. caps.stdlib_id distinguishes GCC (libstdc++) from Clang
252- // (libc++ / msvc-stl) without an extra is_clang() call.
253- std::string module_flag = (caps.stdlib_id == " libstdc++" ) ? " -fmodules" : " " ;
254+ // Module-flag spellings come from BmiTraits: GCC needs -fmodules on every
255+ // TU (BMIs implicit); Clang/MSVC reference the staged std BMI and a BMI
256+ // search dir explicitly (spelled -fmodule-file=/-fprebuilt-module-path vs
257+ // /reference//ifcSearchDir).
258+ auto traits = mcpp::toolchain::bmi_traits (plan.toolchain );
259+ std::string module_flag{traits.compileModulesFlag };
254260 std::string std_module_flag;
255- if (isClang && !plan.stdBmiPath .empty ()) {
256- std_module_flag = " -fmodule-file=std=" + escape_path (staged_std_bmi_path (plan));
261+ if (!traits.stdBmiUsePrefix .empty () && !plan.stdBmiPath .empty ()) {
262+ std_module_flag = std::string (traits.stdBmiUsePrefix )
263+ + escape_path (staged_std_bmi_path (plan));
257264 }
258265 std::string std_compat_module_flag;
259- if (isClang && !plan.stdCompatBmiPath .empty ()) {
266+ if (!traits.stdCompatBmiUsePrefix .empty () && !plan.stdCompatBmiPath .empty ()) {
267+ // NOTE: staging path is Clang's today; registry-dispatch when the
268+ // MSVC backend lands (std.compat.ixx staging).
260269 auto compatDst = mcpp::toolchain::clang::staged_std_compat_bmi_path (plan.outputDir );
261- std_compat_module_flag = " -fmodule-file=std.compat=" + escape_path (compatDst);
270+ std_compat_module_flag = std::string (traits.stdCompatBmiUsePrefix )
271+ + escape_path (compatDst);
262272 }
263- auto traits = mcpp::toolchain::bmi_traits (plan.toolchain );
264273 std::string prebuilt_module_flag;
265274 if (traits.needsPrebuiltModulePath ) {
266275 // Absolute path: a bare `pcm.cache` / `gcm.cache` works at ninja
@@ -272,22 +281,32 @@ CompileFlags compute_flags(const BuildPlan& plan) {
272281 // resolution fails with `module 'X' not found`. The other
273282 // `-fmodule-file=` flags in this block are already escape_path'd
274283 // (absolute) for the same reason — this one was a leftover.
275- prebuilt_module_flag = std::format ( " -fprebuilt-module-path={} " ,
276- escape_path (plan.outputDir / traits.bmiDir ) );
284+ prebuilt_module_flag = std::string (traits. bmiSearchPrefix )
285+ + escape_path (plan.outputDir / traits.bmiDir );
277286 }
278287 std::string cxx_std_flag =
279- plan.cppStandardFlag .empty () ? std::string (" -std=c++23" ) : plan.cppStandardFlag ;
288+ plan.cppStandardFlag .empty ()
289+ ? std::format (" {}c++23" , d.stdPrefix ) : plan.cppStandardFlag ;
280290 f.cxx = std::format (" {}{}{}{}{}{}{}{}{}{}" , cxx_std_flag, module_flag, std_module_flag,
281291 std_compat_module_flag, prebuilt_module_flag,
282292 opt_flag, pic_flag, compile_toolchain_flags, b_flag, include_flags);
283- f.cc = std::format (" -std= {}{}{}{}{}{}" , c_std, opt_flag, pic_flag, compile_toolchain_flags ,
284- b_flag, include_flags);
293+ f.cc = std::format (" {}{}{}{}{}{}{} " , d. stdPrefix , c_std, opt_flag, pic_flag,
294+ compile_toolchain_flags, b_flag, include_flags);
285295
286296 // Link flags
287297 f.staticStdlib = plan.manifest .buildConfig .staticStdlib ;
288298 f.linkage = plan.manifest .buildConfig .linkage ;
289299 std::string full_static = (mcpp::platform::supports_full_static && f.linkage == " static" ) ? " -static" : " " ;
290- std::string static_stdlib = (f.staticStdlib && !isClang && !mcpp::platform::is_windows) ? " -static-libstdc++" : " " ;
300+ // Static C++ stdlib: a libstdc++ (GCC/MinGW) concern. On Windows a MinGW
301+ // toolchain also statically links libgcc, so produced binaries don't
302+ // depend on libstdc++-6.dll / libgcc_s DLLs from the toolchain dir
303+ // (portable-by-default, same spirit as the macOS static-libc++ path).
304+ std::string static_stdlib;
305+ if (f.staticStdlib && caps.stdlib_id == " libstdc++" ) {
306+ static_stdlib = " -static-libstdc++" ;
307+ if constexpr (mcpp::platform::is_windows)
308+ static_stdlib += " -static-libgcc" ;
309+ }
291310 std::string runtime_dirs;
292311 if constexpr (mcpp::platform::supports_rpath) {
293312 // Toolchain runtime dirs (glibc/gcc) as before...
@@ -320,7 +339,16 @@ CompileFlags compute_flags(const BuildPlan& plan) {
320339 if (prof.strip ) link_extra += " -s" ;
321340
322341 if constexpr (mcpp::platform::is_windows) {
323- f.ld = user_ldflags + link_extra;
342+ // PE link: no rpath/loader/payload model. MSVC-ABI Clang needs
343+ // nothing extra (MSVC STL/SDK via the driver); MinGW adds the static
344+ // libstdc++/libgcc pair (static_stdlib above) and -B so its own
345+ // binutils resolve, plus `-static` for full static when requested
346+ // (MinGW supports it, unlike MSVC-ABI links).
347+ std::string mingw_static =
348+ (caps.stdlib_id == " libstdc++" && f.linkage == " static" )
349+ ? " -static" : " " ;
350+ f.ld = std::format (" {}{}{}{}{}" , mingw_static, static_stdlib, b_flag,
351+ user_ldflags, link_extra);
324352 } else if constexpr (mcpp::platform::needs_explicit_libcxx) {
325353 // macOS. Two min-version concerns (see xlings
326354 // .agents/docs/2026-06-05-macos-min-version-support.md):
0 commit comments