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"
8 #include <cm/string_view>
9 #include <cmext/string_view>
11 #include "cmExecutionStatus.h"
12 #include "cmMakefile.h"
13 #include "cmMessageType.h"
14 #include "cmMessenger.h"
16 #include "cmStringAlgorithms.h"
17 #include "cmSystemTools.h"
22 enum class CheckingType
30 std::string IndentText(std::string text, cmMakefile& mf)
33 cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), "");
35 const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() ||
36 mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW");
38 auto context = cmJoin(
39 cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), ".");
40 if (!context.empty()) {
41 indent.insert(0u, cmStrCat("["_s, context, "] "_s));
45 if (!indent.empty()) {
46 cmSystemTools::ReplaceString(text, "\n", "\n" + indent);
47 text.insert(0u, indent);
52 void ReportCheckResult(cm::string_view what, std::string result,
55 if (mf.GetCMakeInstance()->HasCheckInProgress()) {
56 auto text = mf.GetCMakeInstance()->GetTopCheckInProgressMessage() + " - " +
58 mf.DisplayStatus(IndentText(std::move(text), mf), -1);
60 mf.GetMessenger()->DisplayMessage(
61 MessageType::AUTHOR_WARNING,
62 cmStrCat("Ignored "_s, what, " without CHECK_START"_s),
67 } // anonymous namespace
70 bool cmMessageCommand(std::vector<std::string> const& args,
71 cmExecutionStatus& status)
74 status.SetError("called with incorrect number of arguments");
78 auto& mf = status.GetMakefile();
80 auto i = args.cbegin();
82 auto type = MessageType::MESSAGE;
84 auto level = Message::LogLevel::LOG_UNDEFINED;
85 auto checkingType = CheckingType::UNDEFINED;
86 if (*i == "SEND_ERROR") {
87 type = MessageType::FATAL_ERROR;
88 level = Message::LogLevel::LOG_ERROR;
90 } else if (*i == "FATAL_ERROR") {
92 type = MessageType::FATAL_ERROR;
93 level = Message::LogLevel::LOG_ERROR;
95 } else if (*i == "WARNING") {
96 type = MessageType::WARNING;
97 level = Message::LogLevel::LOG_WARNING;
99 } else if (*i == "AUTHOR_WARNING") {
100 if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
101 !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
103 type = MessageType::AUTHOR_ERROR;
104 level = Message::LogLevel::LOG_ERROR;
105 } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
106 type = MessageType::AUTHOR_WARNING;
107 level = Message::LogLevel::LOG_WARNING;
112 } else if (*i == "CHECK_START") {
113 level = Message::LogLevel::LOG_STATUS;
114 checkingType = CheckingType::CHECK_START;
116 } else if (*i == "CHECK_PASS") {
117 level = Message::LogLevel::LOG_STATUS;
118 checkingType = CheckingType::CHECK_PASS;
120 } else if (*i == "CHECK_FAIL") {
121 level = Message::LogLevel::LOG_STATUS;
122 checkingType = CheckingType::CHECK_FAIL;
124 } else if (*i == "STATUS") {
125 level = Message::LogLevel::LOG_STATUS;
127 } else if (*i == "VERBOSE") {
128 level = Message::LogLevel::LOG_VERBOSE;
130 } else if (*i == "DEBUG") {
131 level = Message::LogLevel::LOG_DEBUG;
133 } else if (*i == "TRACE") {
134 level = Message::LogLevel::LOG_TRACE;
136 } else if (*i == "DEPRECATION") {
137 if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) {
139 type = MessageType::DEPRECATION_ERROR;
140 level = Message::LogLevel::LOG_ERROR;
141 } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") ||
142 mf.IsOn("CMAKE_WARN_DEPRECATED")) {
143 type = MessageType::DEPRECATION_WARNING;
144 level = Message::LogLevel::LOG_WARNING;
149 } else if (*i == "NOTICE") {
150 // `NOTICE` message type is going to be output to stderr
151 level = Message::LogLevel::LOG_NOTICE;
154 // Messages w/o any type are `NOTICE`s
155 level = Message::LogLevel::LOG_NOTICE;
157 assert("Message log level expected to be set" &&
158 level != Message::LogLevel::LOG_UNDEFINED);
160 Message::LogLevel desiredLevel = mf.GetCurrentLogLevel();
162 if (desiredLevel < level) {
163 // Suppress the message
167 auto message = cmJoin(cmMakeRange(i, args.cend()), "");
170 case Message::LogLevel::LOG_ERROR:
171 case Message::LogLevel::LOG_WARNING:
172 // we've overridden the message type, above, so display it directly
173 mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace());
176 case Message::LogLevel::LOG_NOTICE:
177 cmSystemTools::Message(IndentText(message, mf));
180 case Message::LogLevel::LOG_STATUS:
181 switch (checkingType) {
182 case CheckingType::CHECK_START:
183 mf.DisplayStatus(IndentText(message, mf), -1);
184 mf.GetCMakeInstance()->PushCheckInProgressMessage(message);
187 case CheckingType::CHECK_PASS:
188 ReportCheckResult("CHECK_PASS"_s, message, mf);
191 case CheckingType::CHECK_FAIL:
192 ReportCheckResult("CHECK_FAIL"_s, message, mf);
196 mf.DisplayStatus(IndentText(message, mf), -1);
201 case Message::LogLevel::LOG_VERBOSE:
202 case Message::LogLevel::LOG_DEBUG:
203 case Message::LogLevel::LOG_TRACE:
204 mf.DisplayStatus(IndentText(message, mf), -1);
208 assert("Unexpected log level! Review the `cmMessageCommand.cxx`." &&
214 cmSystemTools::SetFatalErrorOccurred();