Diagnostics: Add IssueDiagnostics methods

Create methods to issue diagnostics. Diagnostics are similar to
messages, except that they are associated with a diagnostic category,
and the diagnostic state determines their severity. Also, add overloads
of methods to issue messages and diagnostics that accept a backtrace, as
a number of places must currently bypass layers in order to pass a
custom backtrace. These are also sub-optimal because the lower level
APIs require the diagnostic state to be explicitly passed by the caller,
which we would prefer to avoid whenever possible.
This commit is contained in:
Matthew Woehlke
2026-03-20 14:20:23 -04:00
parent 29192751b1
commit 436bfb628c
17 changed files with 190 additions and 35 deletions
@@ -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<std::string> 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());
+7 -3
View File
@@ -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(
+3
View File
@@ -11,6 +11,7 @@
#include <cmext/algorithm>
#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,
+3
View File
@@ -12,6 +12,7 @@
#include <cm/string_view>
#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
{
+9 -4
View File
@@ -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(
+3
View File
@@ -12,6 +12,7 @@
#include <cm/string_view>
#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);
@@ -6,6 +6,7 @@
#include <utility>
#include <cm/memory>
#include <cm/string_view>
#include <cmext/string_view>
#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<cmGeneratorTarget const*> emitted;
+3
View File
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
#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;
+10 -3
View File
@@ -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()
+14 -1
View File
@@ -17,6 +17,7 @@
#include <cm/optional>
#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);
+17 -2
View File
@@ -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
+14 -1
View File
@@ -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. */
+4 -2
View File
@@ -10,6 +10,7 @@
#include <cmext/string_view>
#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<std::string> 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:
+61 -16
View File
@@ -2,9 +2,15 @@
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmMessenger.h"
#include <sstream>
#include <utility>
#include <cm/string_view>
#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 <sstream>
#include <utility>
#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
}
+11 -2
View File
@@ -10,6 +10,7 @@
#include <cm/optional>
#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<std::string> topSource);
+8
View File
@@ -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<std::string> cmake::GetDebugConfigs()
{
cmList configs;
+11
View File
@@ -19,6 +19,7 @@
#include <cmext/string_view>
#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<std::string> targets,