Commit e138207c authored by Craig Scott's avatar Craig Scott Committed by Kitware Robot

Merge topic 'message-new-types-and-logging'

599587fe message(): Minor code modernization
6cc93b37 message(): Add support for log levels
377d1b78 cmSystemTools: Remove unused message-related code, simplify logic
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Brad King's avatarBrad King <brad.king@kitware.com>
Merge-request: !3268
parents ea026fb2 599587fe
Pipeline #135942 passed with stage
in 0 seconds
......@@ -116,6 +116,9 @@ _cmake()
2>/dev/null )' -- "$quoted" ) )
return
;;
--loglevel)
COMPREPLY=( $(compgen -W 'error warning notice status verbose debug trace' -- $cur ) )
;;
--help-command)
COMPREPLY=( $( compgen -W '$( cmake --help-command-list 2>/dev/null|
grep -v "^cmake version " )' -- "$cur" ) )
......
......@@ -9,24 +9,56 @@ Display a message to the user.
The optional ``<mode>`` keyword determines the type of message:
::
(none) = Important information
STATUS = Incidental information
WARNING = CMake Warning, continue processing
AUTHOR_WARNING = CMake Warning (dev), continue processing
SEND_ERROR = CMake Error, continue processing,
but skip generation
FATAL_ERROR = CMake Error, stop processing and generation
DEPRECATION = CMake Deprecation Error or Warning if variable
CMAKE_ERROR_DEPRECATED or CMAKE_WARN_DEPRECATED
is enabled, respectively, else no message.
The CMake command-line tool displays STATUS messages on stdout and all
other message types on stderr. The CMake GUI displays all messages in
its log area. The interactive dialogs (ccmake and CMakeSetup) show
``STATUS`` messages one at a time on a status line and other messages in
interactive pop-up boxes.
``FATAL_ERROR``
CMake Error, stop processing and generation.
``SEND_ERROR``
CMake Error, continue processing, but skip generation.
``WARNING``
CMake Warning, continue processing.
``AUTHOR_WARNING``
CMake Warning (dev), continue processing.
``DEPRECATION``
CMake Deprecation Error or Warning if variable
:variable:`CMAKE_ERROR_DEPRECATED` or :variable:`CMAKE_WARN_DEPRECATED`
is enabled, respectively, else no message.
(none) or ``NOTICE``
Important message printed to stderr to attract user's attention.
``STATUS``
The main interesting messages that project users might be interested in.
Ideally these should be concise, no more than a single line, but still
informative.
``VERBOSE``
Detailed informational messages intended for project users. These messages
should provide additional details that won't be of interest in most cases,
but which may be useful to those building the project when they want deeper
insight into what's happening.
``DEBUG``
Detailed informational messages intended for developers working on the
project itself as opposed to users who just want to build it. These messages
will not typically be of interest to other users building the project and
will often be closely related to internal implementation details.
``TRACE``
Fine-grained messages with very low-level implementation details. Messages
using this log level would normally only be temporary and would expect to be
removed before releasing the project, packaging up the files, etc.
The CMake command-line tool displays ``STATUS`` to ``TRACE`` messages on stdout
with the message preceded by two hyphens and a space. All other message types
are sent to stderr and are not prefixed with hyphens. The CMake GUI displays
all messages in its log area. The interactive dialogs (:manual:`ccmake(1)`
and :manual:`cmake-gui(1)`) show ``STATUS`` to ``TRACE`` messages one at a
time on a status line and other messages in interactive pop-up boxes.
The ``--loglevel`` command-line option to each of these tools can be used to
control which messages will be shown.
CMake Warning and Error message text displays using a simple markup
language. Non-indented text is formatted in line-wrapped paragraphs
......
......@@ -200,6 +200,12 @@ Options
from the top of a binary tree for a CMake project it will dump
additional information such as the cache, log files etc.
``--loglevel=<error|warning|notice|status|verbose|debug|trace>``
Set the log level.
The :command:`message` command will only output messages of the specified
log level or higher. The default log level is ``status``.
``--debug-trycompile``
Do not delete the :command:`try_compile` build tree.
Only useful on one :command:`try_compile` at a time.
......
new-message-types-and-logging
-----------------------------
* The :command:`message` command learned new types: ``NOTICE``, ``VERBOSE``,
``DEBUG`` and ``TRACE``.
* The :manual:`cmake(1)` command learned a new CLI option ``--loglevel``.
......@@ -8,6 +8,9 @@
#include "cmMessenger.h"
#include "cmRange.h"
#include "cmSystemTools.h"
#include "cmake.h"
#include <cassert>
class cmExecutionStatus;
......@@ -19,49 +22,88 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
this->SetError("called with incorrect number of arguments");
return false;
}
std::vector<std::string>::const_iterator i = args.begin();
auto i = args.cbegin();
MessageType type = MessageType::MESSAGE;
bool status = false;
bool fatal = false;
auto type = MessageType::MESSAGE;
auto status = false;
auto fatal = false;
auto level = cmake::LogLevel::LOG_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 (this->Makefile->IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
fatal = true;
type = MessageType::AUTHOR_ERROR;
level = cmake::LogLevel::LOG_ERROR;
} else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
type = MessageType::AUTHOR_WARNING;
level = cmake::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
} else if (*i == "STATUS") {
status = true;
level = cmake::LogLevel::LOG_STATUS;
++i;
} else if (*i == "VERBOSE") {
status = true;
level = cmake::LogLevel::LOG_VERBOSE;
++i;
} else if (*i == "DEBUG") {
status = true;
level = cmake::LogLevel::LOG_DEBUG;
++i;
} else if (*i == "TRACE") {
status = true;
level = cmake::LogLevel::LOG_TRACE;
++i;
} else if (*i == "DEPRECATION") {
if (this->Makefile->IsOn("CMAKE_ERROR_DEPRECATED")) {
fatal = true;
type = MessageType::DEPRECATION_ERROR;
level = cmake::LogLevel::LOG_ERROR;
} else if ((!this->Makefile->IsSet("CMAKE_WARN_DEPRECATED") ||
this->Makefile->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 = this->Makefile->GetCMakeInstance()->GetLogLevel();
assert("Expected a valid log level here" &&
desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
if (desiredLevel < level) {
// Suppress the message
return true;
}
std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
auto message = cmJoin(cmMakeRange(i, args.cend()), "");
if (type != MessageType::MESSAGE) {
// we've overridden the message type, above, so display it directly
......
......@@ -168,7 +168,6 @@ bool cmSystemTools::s_RunCommandHideConsole = false;
bool cmSystemTools::s_DisableRunCommandOutput = false;
bool cmSystemTools::s_ErrorOccured = false;
bool cmSystemTools::s_FatalErrorOccured = false;
bool cmSystemTools::s_DisableMessages = false;
bool cmSystemTools::s_ForceUnixPaths = false;
// replace replace with with as many times as it shows up in source.
......@@ -326,14 +325,11 @@ void cmSystemTools::Stdout(const std::string& s)
void cmSystemTools::Message(const std::string& m, const char* title)
{
if (s_DisableMessages) {
return;
}
if (s_MessageCallback) {
s_MessageCallback(m, title);
return;
} else {
std::cerr << m << std::endl;
}
std::cerr << m << std::endl << std::flush;
}
void cmSystemTools::ReportLastSystemError(const char* msg)
......
......@@ -266,8 +266,6 @@ public:
static size_t CalculateCommandLineLengthLimit();
static void EnableMessages() { s_DisableMessages = false; }
static void DisableMessages() { s_DisableMessages = true; }
static void DisableRunCommandOutput() { s_DisableRunCommandOutput = true; }
static void EnableRunCommandOutput() { s_DisableRunCommandOutput = false; }
static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; }
......@@ -540,7 +538,6 @@ private:
static bool s_RunCommandHideConsole;
static bool s_ErrorOccured;
static bool s_FatalErrorOccured;
static bool s_DisableMessages;
static bool s_DisableRunCommandOutput;
};
......
......@@ -718,6 +718,14 @@ void cmake::SetArgs(const std::vector<std::string>& args)
} else if (arg.find("--debug-output", 0) == 0) {
std::cout << "Running with debug output on.\n";
this->SetDebugOutputOn(true);
} else if (arg.find("--loglevel=", 0) == 0) {
const auto logLevel =
StringToLogLevel(arg.substr(sizeof("--loglevel=") - 1));
if (logLevel == LogLevel::LOG_UNDEFINED) {
cmSystemTools::Error("Invalid level specified for --loglevel");
return;
}
this->SetLogLevel(logLevel);
} else if (arg.find("--trace-expand", 0) == 0) {
std::cout << "Running with expanded trace output on.\n";
this->SetTrace(true);
......@@ -828,6 +836,25 @@ void cmake::SetArgs(const std::vector<std::string>& args)
}
}
cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
{
using LevelsPair = std::pair<std::string, LogLevel>;
static const std::vector<LevelsPair> levels = {
{ "error", LogLevel::LOG_ERROR }, { "warning", LogLevel::LOG_WARNING },
{ "notice", LogLevel::LOG_NOTICE }, { "status", LogLevel::LOG_STATUS },
{ "verbose", LogLevel::LOG_VERBOSE }, { "debug", LogLevel::LOG_DEBUG },
{ "trace", LogLevel::LOG_TRACE }
};
const auto levelStrLowCase = cmSystemTools::LowerCase(levelStr);
const auto it = std::find_if(levels.cbegin(), levels.cend(),
[&levelStrLowCase](const LevelsPair& p) {
return p.first == levelStrLowCase;
});
return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED;
}
void cmake::SetDirectoriesFromFile(const char* arg)
{
// Check if the argument refers to a CMakeCache.txt or
......
......@@ -96,6 +96,19 @@ public:
FIND_PACKAGE_MODE
};
/** \brief Define log level constants. */
enum LogLevel
{
LOG_UNDEFINED,
LOG_ERROR,
LOG_WARNING,
LOG_NOTICE,
LOG_STATUS,
LOG_VERBOSE,
LOG_DEBUG,
LOG_TRACE
};
struct GeneratorInfo
{
std::string name;
......@@ -331,6 +344,11 @@ public:
*/
cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache; }
// Get the selected log level for `message()` commands during the cmake run.
LogLevel GetLogLevel() const { return this->MessageLogLevel; }
void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; }
static LogLevel StringToLogLevel(const std::string& levelStr);
// Do we want debug output during the cmake run.
bool GetDebugOutput() { return this->DebugOutput; }
void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
......@@ -524,6 +542,8 @@ private:
std::vector<std::string> TraceOnlyThisSources;
LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
void UpdateConversionPathTable();
// Print a list of valid generators to stderr.
......
......@@ -95,6 +95,8 @@ static const char* cmDocumentationOptions[][2] = {
"Generate graphviz of dependencies, see "
"CMakeGraphVizOptions.cmake for more." },
{ "--system-information [file]", "Dump information about this system." },
{ "--loglevel=<error|warn|notice|status|verbose|debug|trace>",
"Set the verbosity of messages from CMake files." },
{ "--debug-trycompile",
"Do not delete the try_compile build tree. Only "
"useful on one try_compile at a time." },
......
......@@ -10,3 +10,45 @@ run_cmake(warnmessage)
# separately
run_cmake(errormessage_deprecated)
run_cmake(errormessage_dev)
run_cmake_command(
message-loglevel-invalid
${CMAKE_COMMAND} --loglevel=blah -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# Checking various combinations of `message(...)` and log levels `WARNING` to `TRACE`
# - no CLI option -> `WARNING` to `STATUS` output
run_cmake_command(
message-loglevel-default
${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# - Only `WARNING` output
run_cmake_command(
message-loglevel-warning
${CMAKE_COMMAND} --loglevel=warning -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# - Only `WARNING` and `NOTICE` output
run_cmake_command(
message-loglevel-notice
${CMAKE_COMMAND} --loglevel=notice -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# - `WARNING` to `STATUS` output
run_cmake_command(
message-loglevel-status
${CMAKE_COMMAND} --loglevel=status -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# - `WARNING` to `VERBOSE` output
run_cmake_command(
message-loglevel-verbose
${CMAKE_COMMAND} --loglevel=verbose -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# - `WARNING` to `DEBUG` output
run_cmake_command(
message-loglevel-debug
${CMAKE_COMMAND} --loglevel=debug -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# - `WARNING` to `TRACE` output
run_cmake_command(
message-loglevel-trace
${CMAKE_COMMAND} --loglevel=trace -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake
)
# Produce a message for everything except FATAL_ERROR and SEND_ERROR
message(DEPRECATION "Deprecation warning")
message(AUTHOR_WARNING "Author warning message")
message(WARNING "Warning message")
message("Default NOTICE message")
message(NOTICE "NOTICE message")
message(STATUS "STATUS message")
message(VERBOSE "VERBOSE message")
message(DEBUG "DEBUG message")
message(TRACE "TRACE message")
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message
+
Default NOTICE message
NOTICE message$
-- STATUS message
-- VERBOSE message
-- DEBUG message
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message
+
Default NOTICE message
NOTICE message$
CMake Error: Invalid level specified for --loglevel
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message
+
Default NOTICE message
NOTICE message$
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message
+
Default NOTICE message
NOTICE message$
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message
+
Default NOTICE message
NOTICE message$
-- STATUS message
-- VERBOSE message
-- DEBUG message
-- TRACE message
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message
+
Default NOTICE message
NOTICE message$
^CMake Deprecation Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:2 \(message\):
Deprecation warning
+
CMake Warning \(dev\) at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:3 \(message\):
Author warning message
This warning is for project developers\. Use -Wno-dev to suppress it\.
+
CMake Warning at.*/Tests/RunCMake/message/message-all-loglevels\.cmake:4 \(message\):
Warning message$
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment