summaryrefslogtreecommitdiffstats
path: root/Source/cmMessageCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmMessageCommand.cxx')
-rw-r--r--Source/cmMessageCommand.cxx229
1 files changed, 229 insertions, 0 deletions
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
new file mode 100644
index 0000000..bf8183b
--- /dev/null
+++ b/Source/cmMessageCommand.cxx
@@ -0,0 +1,229 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmMessageCommand.h"
+
+#include <cassert>
+#include <utility>
+
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmMessenger.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+namespace {
+
+enum class CheckingType
+{
+ UNDEFINED,
+ CHECK_START,
+ CHECK_PASS,
+ CHECK_FAIL
+};
+
+std::string IndentText(std::string text, cmMakefile& mf)
+{
+ auto indent =
+ cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), "");
+
+ const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() ||
+ mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW");
+ if (showContext) {
+ auto context = cmJoin(
+ cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), ".");
+ if (!context.empty()) {
+ indent.insert(0u, cmStrCat("["_s, context, "] "_s));
+ }
+ }
+
+ if (!indent.empty()) {
+ cmSystemTools::ReplaceString(text, "\n", "\n" + indent);
+ text.insert(0u, indent);
+ }
+ return text;
+}
+
+void ReportCheckResult(cm::string_view what, std::string result,
+ cmMakefile& mf)
+{
+ if (mf.GetCMakeInstance()->HasCheckInProgress()) {
+ auto text = mf.GetCMakeInstance()->GetTopCheckInProgressMessage() + " - " +
+ std::move(result);
+ mf.DisplayStatus(IndentText(std::move(text), mf), -1);
+ } else {
+ mf.GetMessenger()->DisplayMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("Ignored "_s, what, " without CHECK_START"_s),
+ mf.GetBacktrace());
+ }
+}
+
+} // anonymous namespace
+
+// cmLibraryCommand
+bool cmMessageCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ auto& mf = status.GetMakefile();
+
+ auto i = args.cbegin();
+
+ auto type = MessageType::MESSAGE;
+ auto fatal = false;
+ auto level = cmake::LogLevel::LOG_UNDEFINED;
+ auto checkingType = CheckingType::UNDEFINED;
+ if (*i == "SEND_ERROR") {
+ type = MessageType::FATAL_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
+ ++i;
+ } else if (*i == "FATAL_ERROR") {
+ fatal = true;
+ type = MessageType::FATAL_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
+ ++i;
+ } else if (*i == "WARNING") {
+ type = MessageType::WARNING;
+ level = cmake::LogLevel::LOG_WARNING;
+ ++i;
+ } else if (*i == "AUTHOR_WARNING") {
+ if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
+ !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
+ fatal = true;
+ type = MessageType::AUTHOR_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
+ } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
+ type = MessageType::AUTHOR_WARNING;
+ level = cmake::LogLevel::LOG_WARNING;
+ } else {
+ return true;
+ }
+ ++i;
+ } else if (*i == "CHECK_START") {
+ level = cmake::LogLevel::LOG_STATUS;
+ checkingType = CheckingType::CHECK_START;
+ ++i;
+ } else if (*i == "CHECK_PASS") {
+ level = cmake::LogLevel::LOG_STATUS;
+ checkingType = CheckingType::CHECK_PASS;
+ ++i;
+ } else if (*i == "CHECK_FAIL") {
+ level = cmake::LogLevel::LOG_STATUS;
+ checkingType = CheckingType::CHECK_FAIL;
+ ++i;
+ } else if (*i == "STATUS") {
+ level = cmake::LogLevel::LOG_STATUS;
+ ++i;
+ } else if (*i == "VERBOSE") {
+ level = cmake::LogLevel::LOG_VERBOSE;
+ ++i;
+ } else if (*i == "DEBUG") {
+ level = cmake::LogLevel::LOG_DEBUG;
+ ++i;
+ } else if (*i == "TRACE") {
+ level = cmake::LogLevel::LOG_TRACE;
+ ++i;
+ } else if (*i == "DEPRECATION") {
+ if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) {
+ fatal = true;
+ type = MessageType::DEPRECATION_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
+ } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") ||
+ mf.IsOn("CMAKE_WARN_DEPRECATED")) {
+ type = MessageType::DEPRECATION_WARNING;
+ level = cmake::LogLevel::LOG_WARNING;
+ } else {
+ return true;
+ }
+ ++i;
+ } else if (*i == "NOTICE") {
+ // `NOTICE` message type is going to be output to stderr
+ level = cmake::LogLevel::LOG_NOTICE;
+ ++i;
+ } else {
+ // Messages w/o any type are `NOTICE`s
+ level = cmake::LogLevel::LOG_NOTICE;
+ }
+ assert("Message log level expected to be set" &&
+ level != cmake::LogLevel::LOG_UNDEFINED);
+
+ auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel();
+ assert("Expected a valid log level here" &&
+ desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
+
+ // Command line option takes precedence over the cache variable
+ if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) {
+ const auto desiredLevelFromCache =
+ cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
+ if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) {
+ desiredLevel = desiredLevelFromCache;
+ }
+ }
+
+ if (desiredLevel < level) {
+ // Suppress the message
+ return true;
+ }
+
+ auto message = cmJoin(cmMakeRange(i, args.cend()), "");
+
+ switch (level) {
+ case cmake::LogLevel::LOG_ERROR:
+ case cmake::LogLevel::LOG_WARNING:
+ // we've overridden the message type, above, so display it directly
+ mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace());
+ break;
+
+ case cmake::LogLevel::LOG_NOTICE:
+ cmSystemTools::Message(IndentText(message, mf));
+ break;
+
+ case cmake::LogLevel::LOG_STATUS:
+ switch (checkingType) {
+ case CheckingType::CHECK_START:
+ mf.DisplayStatus(IndentText(message, mf), -1);
+ mf.GetCMakeInstance()->PushCheckInProgressMessage(message);
+ break;
+
+ case CheckingType::CHECK_PASS:
+ ReportCheckResult("CHECK_PASS"_s, message, mf);
+ break;
+
+ case CheckingType::CHECK_FAIL:
+ ReportCheckResult("CHECK_FAIL"_s, message, mf);
+ break;
+
+ default:
+ mf.DisplayStatus(IndentText(message, mf), -1);
+ break;
+ }
+ break;
+
+ case cmake::LogLevel::LOG_VERBOSE:
+ case cmake::LogLevel::LOG_DEBUG:
+ case cmake::LogLevel::LOG_TRACE:
+ mf.DisplayStatus(IndentText(message, mf), -1);
+ break;
+
+ default:
+ assert("Unexpected log level! Review the `cmMessageCommand.cxx`." &&
+ false);
+ break;
+ }
+
+ if (fatal) {
+ cmSystemTools::SetFatalErrorOccured();
+ }
+ return true;
+}