cmMessenger.cxx 4.8 KB

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