Browse Source

Ninja: Wrap rules using '>' shell redirection with 'cmd /C' on Windows

This is needed for the clang-scan-deps rule added by commit 0e21e55fc5
(Clang: Record Clang 16.0 C++ modules flags only for GNU-like front-end,
2023-03-16).

Fixes: #24611
Brad King 2 years ago
parent
commit
1b7c26da49
1 changed files with 18 additions and 1 deletions
  1. 18 1
      Source/cmLocalNinjaGenerator.cxx

+ 18 - 1
Source/cmLocalNinjaGenerator.cxx

@@ -456,6 +456,22 @@ std::string cmLocalNinjaGenerator::WriteCommandScript(
   return scriptPath;
 }
 
+#ifdef _WIN32
+namespace {
+bool RuleNeedsCMD(std::string const& cmd)
+{
+  std::vector<std::string> args;
+  cmSystemTools::ParseWindowsCommandLine(cmd.c_str(), args);
+  auto it = std::find_if(args.cbegin(), args.cend(),
+                         [](std::string const& arg) -> bool {
+                           // FIXME: Detect more windows shell operators.
+                           return cmHasLiteralPrefix(arg, ">");
+                         });
+  return it != args.cend();
+}
+}
+#endif
+
 std::string cmLocalNinjaGenerator::BuildCommandLine(
   std::vector<std::string> const& cmdLines, std::string const& outputConfig,
   std::string const& commandConfig, std::string const& customStep,
@@ -499,7 +515,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
 
   std::ostringstream cmd;
 #ifdef _WIN32
-  bool const needCMD = cmdLines.size() > 1;
+  bool const needCMD =
+    cmdLines.size() > 1 || (customStep.empty() && RuleNeedsCMD(cmdLines[0]));
   for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li) {
     if (li != cmdLines.begin()) {
       cmd << " && ";