As most of the people on this list probably know already, ninja uses CreateProcess on Windows, which means that you can only run one command at a time without spawning a new subshell via "cmd /c". In addition to being inconvenient, this puts a pretty low upper limit on the length of your command(s); it's my understanding that this last issue is why ninja uses CreateProcess now. (However, ninja now supports response files, so that concern may no longer be valid.) This is also apparently one of the reasons why ninja required a special flag for supporting MSVC-style deps: <
https://github.com/ninja-build/ninja/pull/721#issuecomment-41292333>.
If CreateProcess is here to stay, one option would be for ninja to split the command line itself, e.g. by calling CommandLineToArgV, finding instances of "&" and "&&", splitting on them, and passing each sub-array of arguments to its own CreateProcess call. This is relatively straightforward (you wouldn't have to parse Windows command lines yourself) and still restores the most important feature that "cmd /c" had: the ability to run multiple commands. There might be some special cases to contend with (I think cmd /c changes how the rest of the line is parsed), but those shouldn't be too hard to address. Of course, you'd still need the cmd /c prefix for shell builtins and variables, but that would be a much less common occurrence.
Does the above sound sane? My main goal is to simplify working with ninja on Windows, especially for cases where it's inconvenient for the meta-build system to track whether "cmd /c" will be necessary. For instance, suppose you have the following:
rule link
command = gcc $in -o $out $post_build
build foo: link foo.c
build bar: link bar.c
post_build = && do_something
Only one of these actually requires wrapping with "cmd /c". Currently, the only solution is to always wrap in these cases, but that puts you into the same situation that precipitated removing the "cmd /c" wrapper from Ninja in the first place!
- Jim