@@ -478,6 +478,22 @@ std::expected<void, std::string> run_build_program(
478478 bool usesStdCompat = imports_module (srcText, " std.compat" );
479479 bool usesStd = usesStdCompat || imports_module (srcText, " std" );
480480
481+ // A rule package's interface is compiled by this same function, so what IT
482+ // imports decides what has to be built just as much as what build.mcpp
483+ // imports. Scanning only build.mcpp made a rule that said `import std;`
484+ // fail with `module 'std' not found` — the std module was never built,
485+ // because the program that triggers the build did not mention it.
486+ for (auto const & [logical, ifacePath] : env.hostModules ) {
487+ std::ifstream is (ifacePath);
488+ if (!is) continue ; // a missing interface is diagnosed by build_host_module
489+ std::ostringstream ss; ss << is.rdbuf ();
490+ const std::string t = ss.str ();
491+ if (t.find (" import mcpp" ) != std::string::npos) usesModule = true ;
492+ if (imports_module (t, " std.compat" )) usesStdCompat = true ;
493+ if (imports_module (t, " std" )) usesStd = true ;
494+ }
495+ usesStd = usesStd || usesStdCompat;
496+
481497 // The toolchain's own environment (MSVC's INCLUDE / LIB / VSLANG, which
482498 // detection synthesized from the located VC tools + Windows SDK). Needed
483499 // by every compile below, the module precompile included.
@@ -499,27 +515,6 @@ std::expected<void, std::string> run_build_program(
499515 mcppModuleObject = std::move (mf->object );
500516 }
501517
502- // #355 step 5: dependency-provided host modules (reusable build rules
503- // shipped as ordinary packages). Compiled HERE, with `base` and `std_flag`
504- // — the same flags the build.mcpp compile below gets — because a BMI is
505- // only usable by a compile that agrees with it. Doing this in a separate
506- // sub-build would leave that agreement to chance, and disagreement shows
507- // up as `module X CRC mismatch`, not as a clear error.
508- std::vector<fs::path> hostModuleObjects;
509- for (auto const & [logical, ifacePath] : env.hostModules ) {
510- auto hm = build_host_module (bdir, hostCompiler, base, std_flag, tc,
511- compileEnv, logical, ifacePath, moduleFlags);
512- if (!hm) return std::unexpected (hm.error ());
513- for (auto & f : hm->useFlags ) {
514- // GCC's marker is just `-fmodules`, already present when the
515- // bundled module was built; repeating it is harmless but noisy.
516- if (std::find (moduleFlags.begin (), moduleFlags.end (), f)
517- == moduleFlags.end ())
518- moduleFlags.push_back (f);
519- }
520- hostModuleObjects.push_back (std::move (hm->object ));
521- }
522-
523518 // ── `import std;` in build.mcpp ─────────────────────────────────────────
524519 //
525520 // mcpp asks projects to `import std;` everywhere and then made their build
@@ -606,6 +601,35 @@ std::expected<void, std::string> run_build_program(
606601 stdObjects.push_back (sm->compatObjectPath .string ());
607602 }
608603
604+ // #355 step 5: dependency-provided host modules (reusable build rules
605+ // shipped as ordinary packages). Compiled HERE, with `base` and `std_flag`
606+ // — the same flags the build.mcpp compile below gets — because a BMI is
607+ // only usable by a compile that agrees with it. Doing this in a separate
608+ // sub-build would leave that agreement to chance, and disagreement shows
609+ // up as `module X CRC mismatch`, not as a clear error.
610+ //
611+ // AFTER the std block, and that ordering is load-bearing: a rule may
612+ // `import std;` just as build.mcpp may, and it can only do so once the std
613+ // BMI exists and `stdFlags` names it. Compiling rules first — which is what
614+ // 2026.8.5.1 did — handed them an empty `stdFlags` and failed with
615+ // `module 'std' not found`.
616+ std::vector<fs::path> hostModuleObjects;
617+ for (auto const & [logical, ifacePath] : env.hostModules ) {
618+ std::vector<std::string> use = moduleFlags;
619+ use.insert (use.end (), stdFlags.begin (), stdFlags.end ());
620+ auto hm = build_host_module (bdir, hostCompiler, base, std_flag, tc,
621+ compileEnv, logical, ifacePath, use);
622+ if (!hm) return std::unexpected (hm.error ());
623+ for (auto & f : hm->useFlags ) {
624+ // GCC's marker is just `-fmodules`, already present when the
625+ // bundled module was built; repeating it is harmless but noisy.
626+ if (std::find (moduleFlags.begin (), moduleFlags.end (), f)
627+ == moduleFlags.end ())
628+ moduleFlags.push_back (f);
629+ }
630+ hostModuleObjects.push_back (std::move (hm->object ));
631+ }
632+
609633 // `-x c++` is required: the `.mcpp` extension is unknown to the compiler, so
610634 // without it the driver hands build.mcpp to the linker as a linker script.
611635 std::vector<std::string> compileArgv = { hostCompiler.string () };
0 commit comments