diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx index aab53f1119..edcb1efd8f 100644 --- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx +++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx @@ -4,6 +4,7 @@ #include "cmsys/Directory.hxx" +#include "cmDiagnostics.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -97,7 +98,7 @@ bool cmCTestEmptyBinaryDirectoryCommand(std::vector const& args, if (!EmptyBinaryDirectory(args[0], err)) { cmMakefile& mf = status.GetMakefile(); mf.GetMessenger()->DisplayMessage( - MessageType::FATAL_ERROR, + MessageType::FATAL_ERROR, cmDiagnostics::CMD_NONE, cmStrCat("Did not remove the binary directory:\n ", args[0], "\nbecause:\n ", err), mf.GetBacktrace()); diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index ee12b1d254..ba090f5dd0 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -21,7 +21,6 @@ #include "cmTarget.h" #include "cmTargetExport.h" #include "cmValue.h" -#include "cmake.h" class cmSourceFile; @@ -244,8 +243,13 @@ void cmExportBuildFileGenerator::ComplainAboutDuplicateTarget( void cmExportBuildFileGenerator::IssueMessage(MessageType type, std::string const& message) const { - this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( - type, message, this->LG->GetMakefile()->GetBacktrace()); + this->LG->GetMakefile()->IssueMessage(type, message); +} + +void cmExportBuildFileGenerator::IssueDiagnostic( + cmDiagnosticCategory category, std::string const& message) const +{ + this->LG->GetMakefile()->IssueDiagnostic(category, message); } std::string cmExportBuildFileGenerator::InstallNameDir( diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 575d8e2149..b3ee5d461b 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -11,6 +11,7 @@ #include +#include "cmDiagnostics.h" #include "cmExportFileGenerator.h" #include "cmStateTypes.h" @@ -88,6 +89,8 @@ protected: void IssueMessage(MessageType type, std::string const& message) const override; + void IssueDiagnostic(cmDiagnosticCategory category, + std::string const& message) const override; /** Fill in properties indicating built file locations. */ void SetImportLocationProperty(std::string const& config, diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index f53cba7529..fdd1879b90 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -12,6 +12,7 @@ #include +#include "cmDiagnostics.h" #include "cmGeneratorExpression.h" #include "cmMessageType.h" @@ -123,6 +124,8 @@ protected: virtual void IssueMessage(MessageType type, std::string const& message) const = 0; + virtual void IssueDiagnostic(cmDiagnosticCategory category, + std::string const& message) const = 0; void ReportError(std::string const& errorMessage) const { diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index db754808fc..00e7c35395 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -24,7 +24,6 @@ #include "cmTarget.h" #include "cmTargetExport.h" #include "cmValue.h" -#include "cmake.h" cmExportInstallFileGenerator::cmExportInstallFileGenerator( cmInstallExportGenerator* iegen) @@ -338,9 +337,15 @@ void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget( void cmExportInstallFileGenerator::IssueMessage( MessageType type, std::string const& message) const { - this->IEGen->GetLocalGenerator()->GetCMakeInstance()->IssueMessage( - type, message, - this->IEGen->GetLocalGenerator()->GetMakefile()->GetBacktrace()); + cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator(); + lg->GetMakefile()->IssueMessage(type, message); +} + +void cmExportInstallFileGenerator::IssueDiagnostic( + cmDiagnosticCategory category, std::string const& message) const +{ + cmLocalGenerator const* const lg = this->IEGen->GetLocalGenerator(); + lg->GetMakefile()->IssueDiagnostic(category, message); } std::string cmExportInstallFileGenerator::InstallNameDir( diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 5a72903dc1..ad0bdd3065 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -12,6 +12,7 @@ #include +#include "cmDiagnostics.h" #include "cmExportFileGenerator.h" #include "cmGeneratorExpression.h" #include "cmInstallExportGenerator.h" @@ -96,6 +97,8 @@ protected: void IssueMessage(MessageType type, std::string const& message) const override; + void IssueDiagnostic(cmDiagnosticCategory category, + std::string const& message) const override; /** Generate a per-configuration file for the targets. */ virtual bool GenerateImportFileConfig(std::string const& config); diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 3bb036907f..ec1d076d8a 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -6,6 +6,7 @@ #include #include +#include #include #include "cmGenExContext.h" @@ -54,6 +55,15 @@ void cmExportTryCompileFileGenerator::IssueMessage( } } +void cmExportTryCompileFileGenerator::IssueDiagnostic( + cmDiagnosticCategory category, std::string const& message) const +{ + cm::string_view const cname = + cmDiagnostics::GetCategoryString(category).substr(4); + cmSystemTools::Message( + cmStrCat("CMake Diagnostic ("_s, cname, "): "_s, message), "Diagnostic"); +} + bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os) { std::set emitted; diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index f877a17029..432a53cda9 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -9,6 +9,7 @@ #include #include +#include "cmDiagnostics.h" #include "cmExportCMakeConfigGenerator.h" class cmGeneratorTarget; @@ -32,6 +33,8 @@ protected: std::string const& /*targetName*/) const override {}; void IssueMessage(MessageType type, std::string const& message) const override; + void IssueDiagnostic(cmDiagnosticCategory category, + std::string const& message) const override; bool GenerateMainFile(std::ostream& os) override; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3c1982579d..2603ef4e5f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -240,10 +240,17 @@ cmLocalGenerator::CreateRulePlaceholderExpander(cmBuildStep buildStep) const cmLocalGenerator::~cmLocalGenerator() = default; -void cmLocalGenerator::IssueMessage(MessageType t, - std::string const& text) const +void cmLocalGenerator::IssueMessage(MessageType type, std::string const& text, + cmListFileBacktrace const& bt) const { - this->GetCMakeInstance()->IssueMessage(t, text, this->DirectoryBacktrace); + this->GetMakefile()->IssueMessage(type, text, bt); +} + +void cmLocalGenerator::IssueDiagnostic(cmDiagnosticCategory category, + std::string const& text, + cmListFileBacktrace const& bt) const +{ + this->GetMakefile()->IssueDiagnostic(category, text, bt); } void cmLocalGenerator::ComputeObjectMaxPath() diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 50e710ff61..3196c73113 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -17,6 +17,7 @@ #include #include "cmCustomCommandTypes.h" +#include "cmDiagnostics.h" #include "cmGeneratorOptions.h" #include "cmGeneratorTarget.h" #include "cmListFileCache.h" @@ -569,7 +570,19 @@ public: bool IsNinjaMulti() const; bool IsWindowsVSIDE() const; - void IssueMessage(MessageType t, std::string const& text) const; + void IssueMessage(MessageType type, std::string const& text) const + { + this->IssueMessage(type, text, this->DirectoryBacktrace); + } + void IssueMessage(MessageType type, std::string const& text, + cmListFileBacktrace const& bt) const; + void IssueDiagnostic(cmDiagnosticCategory category, + std::string const& text) const + { + this->IssueDiagnostic(category, text, this->DirectoryBacktrace); + } + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmListFileBacktrace const& bt) const; void CreateEvaluationFileOutputs(); void CreateEvaluationFileOutputs(std::string const& config); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index a45d8c0bd8..cd5bb73af3 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -214,7 +214,8 @@ cmDirectoryId cmMakefile::GetDirectoryId() const return std::string(buf); } -void cmMakefile::IssueMessage(MessageType t, std::string const& text) const +void cmMakefile::IssueMessage(MessageType t, std::string const& text, + cmListFileBacktrace const& bt) const { if (!this->ExecutionStatusStack.empty()) { if ((t == MessageType::FATAL_ERROR) || @@ -222,7 +223,21 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const this->ExecutionStatusStack.back()->SetNestedError(); } } - this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace); + this->GetCMakeInstance()->IssueMessage(t, text, bt); +} + +void cmMakefile::IssueDiagnostic(cmDiagnosticCategory category, + std::string const& text, + cmListFileBacktrace const& bt) const +{ + if (!this->ExecutionStatusStack.empty()) { + cmDiagnosticAction const action = this->GetDiagnosticAction(category); + if (action >= cmDiagnosticAction::SendError) { + this->ExecutionStatusStack.back()->SetNestedError(); + } + } + this->GetCMakeInstance()->IssueDiagnostic(category, text, + this->GetStateSnapshot(), bt); } Message::LogLevel cmMakefile::GetCurrentLogLevel() const diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 706fe0184e..09843c97d5 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -1037,7 +1037,20 @@ public: cmMakefile* Makefile; }; - void IssueMessage(MessageType t, std::string const& text) const; + void IssueMessage(MessageType t, std::string const& text) const + { + this->IssueMessage(t, text, this->Backtrace); + } + void IssueMessage(MessageType t, std::string const& text, + cmListFileBacktrace const& bt) const; + + void IssueDiagnostic(cmDiagnosticCategory category, + std::string const& text) const + { + this->IssueDiagnostic(category, text, this->Backtrace); + } + void IssueDiagnostic(cmDiagnosticCategory category, std::string const& text, + cmListFileBacktrace const& bt) const; Message::LogLevel GetCurrentLogLevel() const; /** Set whether or not to report a CMP0000 violation. */ diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index e19f4ef8a2..e58f2bc779 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -10,6 +10,7 @@ #include #include "cmConfigureLog.h" +#include "cmDiagnostics.h" #include "cmExecutionStatus.h" #include "cmList.h" #include "cmMakefile.h" @@ -57,7 +58,7 @@ void ReportCheckResult(cm::string_view what, std::string result, mf.DisplayStatus(IndentText(std::move(text), mf), -1); } else { mf.GetMessenger()->DisplayMessage( - MessageType::AUTHOR_WARNING, + MessageType::AUTHOR_WARNING, cmDiagnostics::CMD_NONE, cmStrCat("Ignored "_s, what, " without CHECK_START"_s), mf.GetBacktrace()); } @@ -194,7 +195,8 @@ bool cmMessageCommand(std::vector const& args, case Message::LogLevel::LOG_ERROR: case Message::LogLevel::LOG_WARNING: // we've overridden the message type, above, so display it directly - mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace()); + mf.GetMessenger()->DisplayMessage(type, cmDiagnostics::CMD_NONE, message, + mf.GetBacktrace()); break; case Message::LogLevel::LOG_NOTICE: diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index ad439cbda1..9cc706e452 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -2,9 +2,15 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmMessenger.h" +#include +#include + +#include + #include "cmDocumentationFormatter.h" #include "cmMessageMetadata.h" #include "cmMessageType.h" +#include "cmStateSnapshot.h" #include "cmStdIoTerminal.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -15,9 +21,6 @@ # include "cmSarifLog.h" #endif -#include -#include - #ifdef CMake_ENABLE_DEBUGGER # include "cmDebuggerAdapter.h" #endif @@ -69,23 +72,34 @@ void printMessageText(std::ostream& msg, std::string const& text) formatter.PrintFormatted(msg, text); } -void displayMessage(MessageType t, std::ostringstream& msg) +void displayMessage(MessageType type, cmDiagnosticCategory category, + std::ostringstream& msg) { // Add a note about warning suppression. - if (t == MessageType::AUTHOR_WARNING) { + if (type == MessageType::AUTHOR_WARNING) { msg << "This warning is for project developers. Use -Wno-dev to suppress " "it."; - } else if (t == MessageType::AUTHOR_ERROR) { + } else if (type == MessageType::AUTHOR_ERROR) { msg << "This error is for project developers. Use -Wno-error=dev to " "suppress it."; } + if (category == cmDiagnostics::CMD_AUTHOR) { + // Add a note about warning suppression. + if (type == MessageType::WARNING) { + msg << "This warning is for project developers. " + "Use -Wno-author to suppress it."; + } else if (type == MessageType::FATAL_ERROR) { + msg << "This error is for project developers. " + "Use -Wno-error=author to suppress it."; + } + } // Add a terminating blank line. msg << '\n'; #if !defined(CMAKE_BOOTSTRAP) // Add a C++ stack trace to internal errors. - if (t == MessageType::INTERNAL_ERROR) { + if (type == MessageType::INTERNAL_ERROR) { std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0); if (!stack.empty()) { if (cmHasLiteralPrefix(stack, "WARNING:")) { @@ -98,9 +112,11 @@ void displayMessage(MessageType t, std::ostringstream& msg) // Output the message. cmMessageMetadata md; - md.attrs = getMessageColor(t); - if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR || - t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) { + md.attrs = getMessageColor(type); + if (type == MessageType::FATAL_ERROR || + type == MessageType::INTERNAL_ERROR || + type == MessageType::DEPRECATION_ERROR || + type == MessageType::AUTHOR_ERROR) { cmSystemTools::SetErrorOccurred(); md.title = "Error"; } else { @@ -197,17 +213,46 @@ void cmMessenger::IssueMessage(MessageType t, std::string const& text, } if (force || this->IsMessageTypeVisible(t)) { - this->DisplayMessage(t, text, backtrace); + this->DisplayMessage(t, cmDiagnostics::CMD_NONE, text, backtrace); } } -void cmMessenger::DisplayMessage(MessageType t, std::string const& text, +void cmMessenger::IssueDiagnostic(cmDiagnosticCategory category, + std::string const& text, + cmStateSnapshot const& context, + cmListFileBacktrace const& backtrace) const +{ + cmDiagnosticAction const action = context.GetDiagnostic(category); + switch (action) { + case cmDiagnostics::FatalError: + cmSystemTools::SetFatalErrorOccurred(); + CM_FALLTHROUGH; + case cmDiagnostics::SendError: + cmSystemTools::SetErrorOccurred(); + this->DisplayMessage(MessageType::FATAL_ERROR, category, text, + backtrace); + break; + case cmDiagnostics::Warn: + this->DisplayMessage(MessageType::WARNING, category, text, backtrace); + break; + default: + return; + } +} + +void cmMessenger::DisplayMessage(MessageType type, + cmDiagnosticCategory category, + std::string const& text, cmListFileBacktrace const& backtrace) const { std::ostringstream msg; // Print the message preamble. - msg << "CMake " << getMessageTypeStr(t); + msg << "CMake " << getMessageTypeStr(type); + if (category != cmDiagnostics::CMD_NONE) { + cm::string_view const cname = cmDiagnostics::GetCategoryString(category); + msg << " (" << cname.substr(4) << ')'; + } // Add the immediate context. this->PrintBacktraceTitle(msg, backtrace); @@ -217,16 +262,16 @@ void cmMessenger::DisplayMessage(MessageType t, std::string const& text, // Add the rest of the context. PrintCallStack(msg, backtrace, this->TopSource); - displayMessage(t, msg); + displayMessage(type, category, msg); #ifndef CMAKE_BOOTSTRAP // Add message to SARIF logs - this->SarifLog.LogMessage(t, text, backtrace); + this->SarifLog.LogMessage(type, text, backtrace); #endif #ifdef CMake_ENABLE_DEBUGGER if (DebuggerAdapter) { - DebuggerAdapter->OnMessageOutput(t, msg.str()); + DebuggerAdapter->OnMessageOutput(type, msg.str()); } #endif } diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h index ad04b77447..4f5d17014e 100644 --- a/Source/cmMessenger.h +++ b/Source/cmMessenger.h @@ -10,6 +10,7 @@ #include +#include "cmDiagnostics.h" #include "cmListFileCache.h" #include "cmMessageType.h" // IWYU pragma: keep @@ -17,6 +18,8 @@ # include "cmSarifLog.h" #endif +class cmStateSnapshot; + #ifdef CMake_ENABLE_DEBUGGER namespace cmDebugger { class cmDebuggerAdapter; @@ -27,10 +30,16 @@ class cmMessenger { public: void IssueMessage( - MessageType t, std::string const& text, + MessageType type, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; - void DisplayMessage(MessageType t, std::string const& text, + void IssueDiagnostic( + cmDiagnosticCategory category, std::string const& text, + cmStateSnapshot const& context, + cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; + + void DisplayMessage(MessageType type, cmDiagnosticCategory category, + std::string const& text, cmListFileBacktrace const& backtrace) const; void SetTopSource(cm::optional topSource); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 201fbaa375..2312e630cb 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3836,6 +3836,14 @@ void cmake::IssueMessage(MessageType t, std::string const& text, this->Messenger->IssueMessage(t, text, backtrace); } +void cmake::IssueDiagnostic(cmDiagnosticCategory category, + std::string const& text, + cmStateSnapshot const& state, + cmListFileBacktrace const& backtrace) const +{ + this->Messenger->IssueDiagnostic(category, text, state, backtrace); +} + std::vector cmake::GetDebugConfigs() { cmList configs; diff --git a/Source/cmake.h b/Source/cmake.h index 38aef9eea7..402467256d 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -19,6 +19,7 @@ #include #include "cmBuildArgs.h" +#include "cmDiagnostics.h" #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" @@ -654,6 +655,16 @@ public: void IssueMessage( MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; + void IssueDiagnostic( + cmDiagnosticCategory category, std::string const& text, + cmStateSnapshot const& state, + cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; + void IssueDiagnostic( + cmDiagnosticCategory category, std::string const& text, + cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const + { + this->IssueDiagnostic(category, text, this->CurrentSnapshot, backtrace); + } //! run the --build option int Build(cmBuildArgs buildArgs, std::vector targets,