Pārlūkot izejas kodu

Merge topic 'cmake-verbose-print-build-tool-command'

8451a3f0b5 cmGlobalGenerator: use a stream for output in `Build`
e060666531 cmake: write the build command itself with `--verbose`
b017c9f127 cmGlobalGenerator: fix off-by-one for `&&` command joining
c715fd8d76 cmGlobalGenerator: quote commands in `::Build` output
d6c0e827bc cmGlobalGenerator: add a `QuotedPrintable` method for commands
28ee3bef34 cmGlobalGenerator: add missing spaces in output
465ab8d872 cmGlobalGenerator: use `cmStrCat` in `::Build`
81d45dabc4 cmOutputConverter: add a `static` version of `EscapeForShell`

Acked-by: Kitware Robot <[email protected]>
Tested-by: buildbot <[email protected]>
Acked-by: Alex <[email protected]>
Merge-request: !8183
Brad King 2 gadi atpakaļ
vecāks
revīzija
5b063510f9

+ 5 - 0
Help/release/dev/cmake-verbose-print-build-tool-command.rst

@@ -0,0 +1,5 @@
+cmake-verbose-print-build-tool-command
+--------------------------------------
+
+* ``cmake --build $dir --verbose`` will now print the working directory and
+  command line used to perform the build.

+ 1 - 3
Source/CTest/cmCTestBuildAndTestHandler.cxx

@@ -246,7 +246,6 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
         return 1;
       }
     }
-    std::string output;
     const char* config = nullptr;
     if (!this->CTest->GetConfigType().empty()) {
       config = this->CTest->GetConfigType().c_str();
@@ -259,9 +258,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
                                 PackageResolveMode::Disable);
     int retVal = cm.GetGlobalGenerator()->Build(
       cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
-      this->BuildProject, { tar }, output, this->BuildMakeProgram, config,
+      this->BuildProject, { tar }, out, this->BuildMakeProgram, config,
       buildOptions, false, remainingTime);
-    out << output;
     // if the build failed then return
     if (retVal) {
       if (outstring) {

+ 51 - 25
Source/cmGlobalGenerator.cxx

@@ -47,6 +47,7 @@
 #include "cmMSVC60LinkLineComputer.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmRange.h"
 #include "cmSourceFile.h"
@@ -73,6 +74,23 @@ const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
 
 class cmInstalledFile;
 
+namespace detail {
+std::string GeneratedMakeCommand::QuotedPrintable() const
+{
+  std::string output;
+  const char* sep = "";
+  int flags = 0;
+#if !defined(_WIN32)
+  flags |= cmOutputConverter::Shell_Flag_IsUnix;
+#endif
+  for (auto const& arg : this->PrimaryCommand) {
+    output += cmStrCat(sep, cmOutputConverter::EscapeForShell(arg, flags));
+    sep = " ";
+  }
+  return output;
+}
+}
+
 bool cmTarget::StrictTargetComparison::operator()(cmTarget const* t1,
                                                   cmTarget const* t2) const
 {
@@ -2058,9 +2076,12 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
     mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
   cmBuildOptions defaultBuildOptions(false, fast, PackageResolveMode::Disable);
 
-  return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
-                     config, defaultBuildOptions, true,
-                     this->TryCompileTimeout);
+  std::stringstream ostr;
+  auto ret =
+    this->Build(jobs, srcdir, bindir, projectName, newTarget, ostr, "", config,
+                defaultBuildOptions, true, this->TryCompileTimeout);
+  output = ostr.str();
+  return ret;
 }
 
 std::vector<cmGlobalGenerator::GeneratedMakeCommand>
@@ -2085,7 +2106,7 @@ void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
 int cmGlobalGenerator::Build(
   int jobs, const std::string& /*unused*/, const std::string& bindir,
   const std::string& projectName, const std::vector<std::string>& targets,
-  std::string& output, const std::string& makeCommandCSTR,
+  std::ostream& ostr, const std::string& makeCommandCSTR,
   const std::string& config, const cmBuildOptions& buildOptions, bool verbose,
   cmDuration timeout, cmSystemTools::OutputOption outputflag,
   std::vector<std::string> const& nativeOptions)
@@ -2096,16 +2117,13 @@ int cmGlobalGenerator::Build(
    * Run an executable command and put the stdout in output.
    */
   cmWorkingDirectory workdir(bindir);
-  output += "Change Dir: ";
-  output += bindir;
-  output += "\n";
+  ostr << "Change Dir: '" << bindir << '\'' << std::endl;
   if (workdir.Failed()) {
     cmSystemTools::SetRunCommandHideConsole(hideconsole);
     std::string err = cmStrCat("Failed to change directory: ",
                                std::strerror(workdir.GetLastResult()));
     cmSystemTools::Error(err);
-    output += err;
-    output += "\n";
+    ostr << err << std::endl;
     return 1;
   }
   std::string realConfig = config;
@@ -2134,9 +2152,8 @@ int cmGlobalGenerator::Build(
       this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
                                  { "clean" }, realConfig, jobs, verbose,
                                  buildOptions);
-    output += "\nRun Clean Command:";
-    output += cleanCommand.front().Printable();
-    output += "\n";
+    ostr << "\nRun Clean Command: " << cleanCommand.front().QuotedPrintable()
+         << std::endl;
     if (cleanCommand.size() != 1) {
       this->GetCMakeInstance()->IssueMessage(MessageType::INTERNAL_ERROR,
                                              "The generator did not produce "
@@ -2149,27 +2166,33 @@ int cmGlobalGenerator::Build(
                                          nullptr, outputflag, timeout)) {
       cmSystemTools::SetRunCommandHideConsole(hideconsole);
       cmSystemTools::Error("Generator: execution of make clean failed.");
-      output += *outputPtr;
-      output += "\nGenerator: execution of make clean failed.\n";
+      ostr << *outputPtr << "\nGenerator: execution of make clean failed."
+           << std::endl;
 
       return 1;
     }
-    output += *outputPtr;
+    ostr << *outputPtr;
   }
 
   // now build
   std::string makeCommandStr;
-  output += "\nRun Build Command(s):";
+  std::string outputMakeCommandStr;
+  bool isWatcomWMake = this->CMakeInstance->GetState()->UseWatcomWMake();
+  bool needBuildOutput = isWatcomWMake;
+  std::string buildOutput;
+  ostr << "\nRun Build Command(s): ";
 
   retVal = 0;
   for (auto command = makeCommand.begin();
        command != makeCommand.end() && retVal == 0; ++command) {
     makeCommandStr = command->Printable();
-    if (command != makeCommand.end()) {
+    outputMakeCommandStr = command->QuotedPrintable();
+    if ((command + 1) != makeCommand.end()) {
       makeCommandStr += " && ";
+      outputMakeCommandStr += " && ";
     }
 
-    output += makeCommandStr;
+    ostr << outputMakeCommandStr << std::endl;
     if (!cmSystemTools::RunSingleCommand(command->PrimaryCommand, outputPtr,
                                          outputPtr, &retVal, nullptr,
                                          outputflag, timeout)) {
@@ -2177,21 +2200,24 @@ int cmGlobalGenerator::Build(
       cmSystemTools::Error(
         "Generator: execution of make failed. Make command was: " +
         makeCommandStr);
-      output += *outputPtr;
-      output += "\nGenerator: execution of make failed. Make command was: " +
-        makeCommandStr + "\n";
+      ostr << *outputPtr
+           << "\nGenerator: execution of make failed. Make command was: "
+           << outputMakeCommandStr << std::endl;
 
       return 1;
     }
-    output += *outputPtr;
+    ostr << *outputPtr << std::flush;
+    if (needBuildOutput) {
+      buildOutput += *outputPtr;
+    }
   }
-  output += "\n";
+  ostr << std::endl;
   cmSystemTools::SetRunCommandHideConsole(hideconsole);
 
   // The OpenWatcom tools do not return an error code when a link
   // library is not found!
-  if (this->CMakeInstance->GetState()->UseWatcomWMake() && retVal == 0 &&
-      output.find("W1008: cannot open") != std::string::npos) {
+  if (isWatcomWMake && retVal == 0 &&
+      buildOutput.find("W1008: cannot open") != std::string::npos) {
     retVal = 1;
   }
 

+ 2 - 1
Source/cmGlobalGenerator.h

@@ -85,6 +85,7 @@ struct GeneratedMakeCommand
   }
 
   std::string Printable() const { return cmJoin(this->PrimaryCommand, " "); }
+  std::string QuotedPrintable() const;
 
   std::vector<std::string> PrimaryCommand;
   bool RequiresOutputForward = false;
@@ -233,7 +234,7 @@ public:
   int Build(
     int jobs, const std::string& srcdir, const std::string& bindir,
     const std::string& projectName,
-    std::vector<std::string> const& targetNames, std::string& output,
+    std::vector<std::string> const& targetNames, std::ostream& ostr,
     const std::string& makeProgram, const std::string& config,
     const cmBuildOptions& buildOptions, bool verbose, cmDuration timeout,
     cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE,

+ 10 - 5
Source/cmOutputConverter.cxx

@@ -243,11 +243,6 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str,
                                               bool unescapeNinjaConfiguration,
                                               bool forResponse) const
 {
-  // Do not escape shell operators.
-  if (cmOutputConverterIsShellOperator(str)) {
-    return std::string(str);
-  }
-
   // Compute the flags for the target shell environment.
   int flags = 0;
   if (this->GetState()->UseWindowsVSIDE()) {
@@ -283,6 +278,16 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str,
     flags |= Shell_Flag_IsUnix;
   }
 
+  return cmOutputConverter::EscapeForShell(str, flags);
+}
+
+std::string cmOutputConverter::EscapeForShell(cm::string_view str, int flags)
+{
+  // Do not escape shell operators.
+  if (cmOutputConverterIsShellOperator(str)) {
+    return std::string(str);
+  }
+
   return Shell_GetArgument(str, flags);
 }
 

+ 1 - 0
Source/cmOutputConverter.h

@@ -107,6 +107,7 @@ public:
                              bool forEcho = false, bool useWatcomQuote = false,
                              bool unescapeNinjaConfiguration = false,
                              bool forResponse = false) const;
+  static std::string EscapeForShell(cm::string_view str, int flags);
 
   enum class WrapQuotes
   {

+ 9 - 3
Source/cmake.cxx

@@ -3732,7 +3732,6 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
       return 1;
     }
   }
-  std::string output;
   std::string projName;
   cmValue cachedProjectName =
     this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
@@ -3806,10 +3805,17 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
   }
 
   this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs);
-  return this->GlobalGenerator->Build(
-    jobs, "", dir, projName, targets, output, "", config, buildOptions,
+  std::stringstream ostr;
+  // `cmGlobalGenerator::Build` logs metadata about what directory and commands
+  // are being executed to the `output` parameter. If CMake is verbose, print
+  // this out.
+  std::ostream& verbose_ostr = verbose ? std::cout : ostr;
+  int buildresult = this->GlobalGenerator->Build(
+    jobs, "", dir, projName, targets, verbose_ostr, "", config, buildOptions,
     verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH,
     nativeOptions);
+
+  return buildresult;
 }
 
 bool cmake::Open(const std::string& dir, bool dryRun)

+ 1 - 1
Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt

@@ -1 +1 @@
-^ninja: no work to do
+ninja: no work to do