cmMessageCommand.cxx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 "cmMessageCommand.h"
  4. #include "cmExecutionStatus.h"
  5. #include "cmMakefile.h"
  6. #include "cmMessageType.h"
  7. #include "cmMessenger.h"
  8. #include "cmRange.h"
  9. #include "cmStringAlgorithms.h"
  10. #include "cmSystemTools.h"
  11. #include "cmake.h"
  12. #include <cassert>
  13. // cmLibraryCommand
  14. bool cmMessageCommand(std::vector<std::string> const& args,
  15. cmExecutionStatus& status)
  16. {
  17. if (args.empty()) {
  18. status.SetError("called with incorrect number of arguments");
  19. return false;
  20. }
  21. auto i = args.cbegin();
  22. auto type = MessageType::MESSAGE;
  23. auto fatal = false;
  24. auto level = cmake::LogLevel::LOG_UNDEFINED;
  25. if (*i == "SEND_ERROR") {
  26. type = MessageType::FATAL_ERROR;
  27. level = cmake::LogLevel::LOG_ERROR;
  28. ++i;
  29. } else if (*i == "FATAL_ERROR") {
  30. fatal = true;
  31. type = MessageType::FATAL_ERROR;
  32. level = cmake::LogLevel::LOG_ERROR;
  33. ++i;
  34. } else if (*i == "WARNING") {
  35. type = MessageType::WARNING;
  36. level = cmake::LogLevel::LOG_WARNING;
  37. ++i;
  38. } else if (*i == "AUTHOR_WARNING") {
  39. if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
  40. !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
  41. fatal = true;
  42. type = MessageType::AUTHOR_ERROR;
  43. level = cmake::LogLevel::LOG_ERROR;
  44. } else if (!status.GetMakefile().IsOn(
  45. "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
  46. type = MessageType::AUTHOR_WARNING;
  47. level = cmake::LogLevel::LOG_WARNING;
  48. } else {
  49. return true;
  50. }
  51. ++i;
  52. } else if (*i == "STATUS") {
  53. level = cmake::LogLevel::LOG_STATUS;
  54. ++i;
  55. } else if (*i == "VERBOSE") {
  56. level = cmake::LogLevel::LOG_VERBOSE;
  57. ++i;
  58. } else if (*i == "DEBUG") {
  59. level = cmake::LogLevel::LOG_DEBUG;
  60. ++i;
  61. } else if (*i == "TRACE") {
  62. level = cmake::LogLevel::LOG_TRACE;
  63. ++i;
  64. } else if (*i == "DEPRECATION") {
  65. if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) {
  66. fatal = true;
  67. type = MessageType::DEPRECATION_ERROR;
  68. level = cmake::LogLevel::LOG_ERROR;
  69. } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") ||
  70. status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) {
  71. type = MessageType::DEPRECATION_WARNING;
  72. level = cmake::LogLevel::LOG_WARNING;
  73. } else {
  74. return true;
  75. }
  76. ++i;
  77. } else if (*i == "NOTICE") {
  78. // `NOTICE` message type is going to be output to stderr
  79. level = cmake::LogLevel::LOG_NOTICE;
  80. ++i;
  81. } else {
  82. // Messages w/o any type are `NOTICE`s
  83. level = cmake::LogLevel::LOG_NOTICE;
  84. }
  85. assert("Message log level expected to be set" &&
  86. level != cmake::LogLevel::LOG_UNDEFINED);
  87. auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel();
  88. assert("Expected a valid log level here" &&
  89. desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
  90. if (desiredLevel < level) {
  91. // Suppress the message
  92. return true;
  93. }
  94. auto message = cmJoin(cmMakeRange(i, args.cend()), "");
  95. if (cmake::LogLevel::LOG_NOTICE <= level) {
  96. // Check if any indentation has requested:
  97. // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces
  98. // to be joined and prepended to the message lines.
  99. auto indent = cmJoin(cmExpandedList(status.GetMakefile().GetSafeDefinition(
  100. "CMAKE_MESSAGE_INDENT")),
  101. "");
  102. // Make every line of the `message` indented
  103. // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted`
  104. // here cuz it appends `\n` to the EOM ;-(
  105. cmSystemTools::ReplaceString(message, "\n", "\n" + indent);
  106. message = indent + message;
  107. }
  108. switch (level) {
  109. case cmake::LogLevel::LOG_ERROR:
  110. case cmake::LogLevel::LOG_WARNING:
  111. // we've overridden the message type, above, so display it directly
  112. status.GetMakefile().GetMessenger()->DisplayMessage(
  113. type, message, status.GetMakefile().GetBacktrace());
  114. break;
  115. case cmake::LogLevel::LOG_NOTICE:
  116. cmSystemTools::Message(message);
  117. break;
  118. case cmake::LogLevel::LOG_STATUS:
  119. case cmake::LogLevel::LOG_VERBOSE:
  120. case cmake::LogLevel::LOG_DEBUG:
  121. case cmake::LogLevel::LOG_TRACE:
  122. status.GetMakefile().DisplayStatus(message, -1);
  123. break;
  124. default:
  125. assert("Unexpected log level! Review the `cmMessageCommand.cxx`." &&
  126. false);
  127. break;
  128. }
  129. if (fatal) {
  130. cmSystemTools::SetFatalErrorOccured();
  131. }
  132. return true;
  133. }