cmMessenger.cxx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmMessenger.h"
  4. #include "cmDocumentationFormatter.h"
  5. #include "cmMessageMetadata.h"
  6. #include "cmStringAlgorithms.h"
  7. #include "cmSystemTools.h"
  8. #if !defined(CMAKE_BOOTSTRAP)
  9. # include "cmsys/SystemInformation.hxx"
  10. #endif
  11. #include <sstream>
  12. #include "cmsys/Terminal.h"
  13. MessageType cmMessenger::ConvertMessageType(MessageType t) const
  14. {
  15. bool warningsAsErrors;
  16. if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) {
  17. warningsAsErrors = this->GetDevWarningsAsErrors();
  18. if (warningsAsErrors && t == MessageType::AUTHOR_WARNING) {
  19. t = MessageType::AUTHOR_ERROR;
  20. } else if (!warningsAsErrors && t == MessageType::AUTHOR_ERROR) {
  21. t = MessageType::AUTHOR_WARNING;
  22. }
  23. } else if (t == MessageType::DEPRECATION_WARNING ||
  24. t == MessageType::DEPRECATION_ERROR) {
  25. warningsAsErrors = this->GetDeprecatedWarningsAsErrors();
  26. if (warningsAsErrors && t == MessageType::DEPRECATION_WARNING) {
  27. t = MessageType::DEPRECATION_ERROR;
  28. } else if (!warningsAsErrors && t == MessageType::DEPRECATION_ERROR) {
  29. t = MessageType::DEPRECATION_WARNING;
  30. }
  31. }
  32. return t;
  33. }
  34. bool cmMessenger::IsMessageTypeVisible(MessageType t) const
  35. {
  36. bool isVisible = true;
  37. if (t == MessageType::DEPRECATION_ERROR) {
  38. if (!this->GetDeprecatedWarningsAsErrors()) {
  39. isVisible = false;
  40. }
  41. } else if (t == MessageType::DEPRECATION_WARNING) {
  42. if (this->GetSuppressDeprecatedWarnings()) {
  43. isVisible = false;
  44. }
  45. } else if (t == MessageType::AUTHOR_ERROR) {
  46. if (!this->GetDevWarningsAsErrors()) {
  47. isVisible = false;
  48. }
  49. } else if (t == MessageType::AUTHOR_WARNING) {
  50. if (this->GetSuppressDevWarnings()) {
  51. isVisible = false;
  52. }
  53. }
  54. return isVisible;
  55. }
  56. static bool printMessagePreamble(MessageType t, std::ostream& msg)
  57. {
  58. // Construct the message header.
  59. if (t == MessageType::FATAL_ERROR) {
  60. msg << "CMake Error";
  61. } else if (t == MessageType::INTERNAL_ERROR) {
  62. msg << "CMake Internal Error (please report a bug)";
  63. } else if (t == MessageType::LOG) {
  64. msg << "CMake Debug Log";
  65. } else if (t == MessageType::DEPRECATION_ERROR) {
  66. msg << "CMake Deprecation Error";
  67. } else if (t == MessageType::DEPRECATION_WARNING) {
  68. msg << "CMake Deprecation Warning";
  69. } else if (t == MessageType::AUTHOR_WARNING) {
  70. msg << "CMake Warning (dev)";
  71. } else if (t == MessageType::AUTHOR_ERROR) {
  72. msg << "CMake Error (dev)";
  73. } else {
  74. msg << "CMake Warning";
  75. }
  76. return true;
  77. }
  78. static int getMessageColor(MessageType t)
  79. {
  80. switch (t) {
  81. case MessageType::INTERNAL_ERROR:
  82. case MessageType::FATAL_ERROR:
  83. case MessageType::AUTHOR_ERROR:
  84. return cmsysTerminal_Color_ForegroundRed;
  85. case MessageType::AUTHOR_WARNING:
  86. case MessageType::WARNING:
  87. return cmsysTerminal_Color_ForegroundYellow;
  88. default:
  89. return cmsysTerminal_Color_Normal;
  90. }
  91. }
  92. static void printMessageText(std::ostream& msg, std::string const& text)
  93. {
  94. msg << ":\n";
  95. cmDocumentationFormatter formatter;
  96. formatter.SetIndent(" ");
  97. formatter.PrintFormatted(msg, text.c_str());
  98. }
  99. static void displayMessage(MessageType t, std::ostringstream& msg)
  100. {
  101. // Add a note about warning suppression.
  102. if (t == MessageType::AUTHOR_WARNING) {
  103. msg << "This warning is for project developers. Use -Wno-dev to suppress "
  104. "it.";
  105. } else if (t == MessageType::AUTHOR_ERROR) {
  106. msg << "This error is for project developers. Use -Wno-error=dev to "
  107. "suppress it.";
  108. }
  109. // Add a terminating blank line.
  110. msg << "\n";
  111. #if !defined(CMAKE_BOOTSTRAP)
  112. // Add a C++ stack trace to internal errors.
  113. if (t == MessageType::INTERNAL_ERROR) {
  114. std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
  115. if (!stack.empty()) {
  116. if (cmHasLiteralPrefix(stack, "WARNING:")) {
  117. stack = "Note:" + stack.substr(8);
  118. }
  119. msg << stack << "\n";
  120. }
  121. }
  122. #endif
  123. // Output the message.
  124. cmMessageMetadata md;
  125. md.desiredColor = getMessageColor(t);
  126. if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
  127. t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
  128. cmSystemTools::SetErrorOccured();
  129. md.title = "Error";
  130. cmSystemTools::Message(msg.str(), md);
  131. } else {
  132. md.title = "Warning";
  133. cmSystemTools::Message(msg.str(), md);
  134. }
  135. }
  136. void cmMessenger::IssueMessage(MessageType t, const std::string& text,
  137. const cmListFileBacktrace& backtrace) const
  138. {
  139. bool force = false;
  140. if (!force) {
  141. // override the message type, if needed, for warnings and errors
  142. MessageType override = this->ConvertMessageType(t);
  143. if (override != t) {
  144. t = override;
  145. force = true;
  146. }
  147. }
  148. if (!force && !this->IsMessageTypeVisible(t)) {
  149. return;
  150. }
  151. this->DisplayMessage(t, text, backtrace);
  152. }
  153. void cmMessenger::DisplayMessage(MessageType t, const std::string& text,
  154. const cmListFileBacktrace& backtrace) const
  155. {
  156. std::ostringstream msg;
  157. if (!printMessagePreamble(t, msg)) {
  158. return;
  159. }
  160. // Add the immediate context.
  161. backtrace.PrintTitle(msg);
  162. printMessageText(msg, text);
  163. // Add the rest of the context.
  164. backtrace.PrintCallStack(msg);
  165. displayMessage(t, msg);
  166. }