@@ -97,9 +97,17 @@ struct CompileRequest {
9797 // Directory of concurrency tokens. Empty disables the cap (hazard 2).
9898 std::filesystem::path semaphore;
9999 int maxCompilers{0 };
100- std::vector<std::string> argv; // compiler and its arguments
101- // The file `argv` was read from; handed to the supervisor unchanged.
102- std::filesystem::path argvFile;
100+ // The compiler invocation, as ONE shell command line.
101+ //
102+ // Not a token list: the backend has already joined and quoted the flags for
103+ // ninja, and splitting that string back into argv would need to reimplement
104+ // the shell's rules — the exact assumption ("one flag element == one argv
105+ // token") that has been wrong here before. ninja runs every command through
106+ // a shell already, so going through one costs no portability.
107+ std::string command;
108+ // The file `command` was read from; handed to the supervisor unchanged, so
109+ // there is one representation and no re-quoting.
110+ std::filesystem::path commandFile;
103111};
104112
105113// Phase 1 — returns 0 as soon as the BMI is published, leaving code generation
@@ -110,7 +118,7 @@ int compile_release_at_bmi(const CompileRequest& req);
110118// then records the status. Never invoked directly by a build edge.
111119int supervise (const std::filesystem::path& slot,
112120 const std::filesystem::path& semaphoreToken,
113- const std::vector<std::string>& argv );
121+ std::string_view command );
114122
115123// Phase 2 — blocks until the compiler for `slot` finished, replays what it
116124// wrote, and propagates its status. `object`, when given, must exist: a
@@ -209,8 +217,9 @@ bool spawn_detached(const std::vector<std::string>& argv) {
209217 return true ;
210218}
211219
212- int run_to_completion (const std::vector<std::string>& argv ,
220+ int run_to_completion (std::string_view command ,
213221 const std::filesystem::path& logPath) {
222+ const std::vector<std::string> argv{" cmd.exe" , " /c" , std::string (command)};
214223 SECURITY_ATTRIBUTES sa{sizeof (sa), nullptr , TRUE };
215224 HANDLE log = ::CreateFileA (logPath.string ().c_str (), GENERIC_WRITE ,
216225 FILE_SHARE_READ , &sa, CREATE_ALWAYS ,
@@ -268,8 +277,9 @@ bool spawn_detached(const std::vector<std::string>& argv) {
268277 return rc == 0 ;
269278}
270279
271- int run_to_completion (const std::vector<std::string>& argv ,
280+ int run_to_completion (std::string_view command ,
272281 const std::filesystem::path& logPath) {
282+ const std::vector<std::string> argv{" /bin/sh" , " -c" , std::string (command)};
273283 posix_spawn_file_actions_t fa;
274284 ::posix_spawn_file_actions_init (&fa);
275285 ::posix_spawn_file_actions_addopen (&fa, 0 , " /dev/null" , O_RDONLY , 0 );
@@ -292,7 +302,7 @@ int run_to_completion(const std::vector<std::string>& argv,
292302} // namespace
293303
294304int compile_release_at_bmi (const CompileRequest& req) {
295- if (req.argv .empty () || req.self .empty ()) return 2 ;
305+ if (req.command .empty () || req.self .empty ()) return 2 ;
296306
297307 std::error_code ec;
298308 if (!req.slot .parent_path ().empty ())
@@ -315,7 +325,7 @@ int compile_release_at_bmi(const CompileRequest& req) {
315325 // on how long a compiler command may be.
316326 std::vector<std::string> sup{req.self .string (), " bmi-supervise" ,
317327 " --slot" , req.slot .string (),
318- " --argv -file" , req.argvFile .string ()};
328+ " --command -file" , req.commandFile .string ()};
319329 if (!token.empty ()) { sup.push_back (" --token" ); sup.push_back (token.string ()); }
320330 if (!spawn_detached (sup)) return 2 ;
321331
@@ -337,8 +347,8 @@ int compile_release_at_bmi(const CompileRequest& req) {
337347
338348int supervise (const std::filesystem::path& slot,
339349 const std::filesystem::path& semaphoreToken,
340- const std::vector<std::string>& argv ) {
341- const int rc = run_to_completion (argv , suffixed (slot, " .log" ));
350+ std::string_view command ) {
351+ const int rc = run_to_completion (command , suffixed (slot, " .log" ));
342352 if (!semaphoreToken.empty ()) {
343353 std::error_code ec;
344354 std::filesystem::remove (semaphoreToken, ec);
0 commit comments