If I build up the COMMAND for add_custom_command in a variable, and that variable’s value has spaces in it (as it might if the string combines args like “x y”, or “-o outfile.txt”), then the content of that variable gets quotes (") put around it where it appears in the generated build.ninja. The problem is this results in an ill-formed actual command, because there’s already a separate quotation started with “cd…”:
cmd.exe /C “cd /D C:\source\antlr\use-antlr4-vcpkg\cmake-build-dbg-mgw\test_rig && “x y””
If I type the same literal text in under COMMAND in add_custom_command, it doesn’t get extra quotes. This second behavior is the desired one, but I also wouldn’t have expected a difference. I was able to replicate the first condition by typing “x y” instead of x y. If I have x y without the quotes, I get:
cmd.exe /C “cd /D C:\source\antlr\use-antlr4-vcpkg\cmake-build-dbg-mgw\test_rig && x y”
I think I understand that the difference in using variables to build the command versus putting the raw text of the command after COMMAND must have to do with how arguments are expanded in CMake. I guess to prevent a single arg from getting splatted across multiple CMake function args just because it happens to have a space in it, it gets quotes added.
However it seems like quite the footgun in this case. You can build up a string(s) for the command in stages using variables, but the moment a space is involved it breaks. Is it a bug that this results in ill-formed code in build.ninja? If this is intended behavior, there should be a big fat warning in the CMake add_custom_command documentation. Also would be handy if CMake could warn about this.
How even would you properly escape the inner quotes of an arg unless cmd.exe supports quote escape sequences within the argument following /C? I’m thinking of the case of what if you had to pass a command a path with spaces in it as a single arg. It seems like this implementation breaks building from a path with spaces in it.
Maybe the bug is the generated build.ninja SHOULDN’T be quoting the whole command after the /C in the first place. As I understand it, cmd.exe /C foo bar should work without outer quotes around “foo bar” so the default form of the command is including spurious quotes on the outside of the “cd …”.
My implied question in posting this is, am I overlooking something obvious or am I correct in these conclusions? I find it hard to believe what must be as basic a feature as add_custom_command could be completely broken (at least on Windows) if your command path includes spaces and contain such a footgun as the fact you can’t build your whole COMMAND string in a variable (must be passed as separate args) yet this isn’t warned about in the documentation.