@@ -274,6 +274,32 @@ int cmd_toolchain_any(const mcpplibs::cmdline::ParsedArgs& p) {
274274
275275int run (int argc, char ** argv) {
276276 namespace cl = mcpplibs::cmdline;
277+
278+ // Internal split-schedule executor. Everything after `--` is the
279+ // compiler's argv, including flags with the same names as these options.
280+ // Dispatch before global option scans: child words never configure mcpp.
281+ if (argc > 1 && std::string_view (argv[1 ]) == " __compiler-cap" ) {
282+ std::filesystem::path semaphore;
283+ int cap = 0 , i = 2 ;
284+ for (; i < argc && std::string_view (argv[i]) != " --" ; ++i) {
285+ const std::string_view option = argv[i];
286+ if ((option != " --sem" && option != " --cap" ) || i + 1 >= argc) {
287+ std::println (stderr, " error: __compiler-cap: expected --sem <dir> --cap <N> -- <compiler>..." );
288+ return 2 ;
289+ }
290+ const std::string_view value = argv[++i];
291+ if (option == " --sem" ) semaphore = value;
292+ else {
293+ const auto [end, ec] = std::from_chars (value.data (), value.data () + value.size (), cap);
294+ if (ec != std::errc{} || end != value.data () + value.size ()) return 2 ;
295+ }
296+ }
297+ if (semaphore.empty () || cap <= 0 || i + 1 >= argc) return 2 ;
298+ std::vector<std::string> command;
299+ for (++i; i < argc; ++i) command.emplace_back (argv[i]);
300+ return mcpp::build::schedule::detach::run_capped (command, semaphore, cap);
301+ }
302+
277303 ReportUnnarrowablePaths reportUnnarrowable_;
278304
279305 // What a build that waits for this one is told it waits for (mcpp#839):
@@ -1493,30 +1519,6 @@ int run(int argc, char** argv) {
14931519 // check and no `prepare`. On the MSVC ABI the first build after upgrading
14941520 // to 2026.9.28.2 re-runs each action once, because its command line gained
14951521 // the directory.
1496- // Internal split-schedule executor. Everything after `--` is the
1497- // compiler's argv, including flags with the same names as these options.
1498- if (std::string_view (argv[1 ]) == " __compiler-cap" ) {
1499- std::filesystem::path semaphore;
1500- int cap = 0 , i = 2 ;
1501- for (; i < argc && std::string_view (argv[i]) != " --" ; ++i) {
1502- const std::string_view option = argv[i];
1503- if ((option != " --sem" && option != " --cap" ) || i + 1 >= argc) {
1504- std::println (stderr, " error: __compiler-cap: expected --sem <dir> --cap <N> -- <compiler>..." );
1505- return 2 ;
1506- }
1507- const std::string_view value = argv[++i];
1508- if (option == " --sem" ) semaphore = value;
1509- else {
1510- const auto [end, ec] = std::from_chars (value.data (), value.data () + value.size (), cap);
1511- if (ec != std::errc{} || end != value.data () + value.size ()) return 2 ;
1512- }
1513- }
1514- if (semaphore.empty () || cap <= 0 || i + 1 >= argc) return 2 ;
1515- std::vector<std::string> command;
1516- for (++i; i < argc; ++i) command.emplace_back (argv[i]);
1517- return mcpp::build::schedule::detach::run_capped (command, semaphore, cap);
1518- }
1519-
15201522 // `mcpp depfile-filter --raw <file> --out <file> -- <compiler argv>...`
15211523 // (internal: written into build.ninja for GCC on a Windows host, WS2 of
15221524 // the 2026-09-28 design). Runs the compile with inherited stdio and no
0 commit comments