mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 10:50:16 -06:00
Add cmake_language(GET_MESSAGE_LOG_LEVEL) sub command
The new sub-command writes a string representation of the current log level to the output variable given to the sub-command. Given that the log-level might be set either via the --log-level command line option or via the CMAKE_MESSAGE_LOG_LEVEL cache / regular variables, the priority for each of the log level sources is as follows, with the first one being the highest: 1) --log-level 2) CMAKE_MESSAGE_LOG_LEVEL regular variable 3) CMAKE_MESSAGE_LOG_LEVEL cache variable 4) default log level (STATUS) Fixes: #23572
This commit is contained in:
@@ -14,6 +14,7 @@ Synopsis
|
||||
cmake_language(`EVAL`_ CODE <code>...)
|
||||
cmake_language(`DEFER`_ <options>... CALL <command> [<arg>...])
|
||||
cmake_language(`SET_DEPENDENCY_PROVIDER`_ <command> SUPPORTED_METHODS <methods>...)
|
||||
cmake_language(`GET_MESSAGE_LOG_LEVEL`_ <out-var>)
|
||||
|
||||
Introduction
|
||||
^^^^^^^^^^^^
|
||||
@@ -491,3 +492,28 @@ calling the provider command recursively for the same dependency.
|
||||
SET_DEPENDENCY_PROVIDER mycomp_provide_dependency
|
||||
SUPPORTED_METHODS FIND_PACKAGE
|
||||
)
|
||||
|
||||
Getting current message log level
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.25
|
||||
|
||||
.. _GET_MESSAGE_LOG_LEVEL:
|
||||
.. _query_message_log_level:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_language(GET_MESSAGE_LOG_LEVEL <output_variable>)
|
||||
|
||||
Writes the current :command:`message` logging level
|
||||
into the given ``<output_variable>``.
|
||||
|
||||
See :command:`message` for the possible logging levels.
|
||||
|
||||
The current message logging level can be set either using the ``--log-level``
|
||||
command line option of the :manual:`cmake(1)` program or using
|
||||
the :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable.
|
||||
|
||||
If both the command line option and the variable are set, the command line
|
||||
option takes precedence. If neither are set, the default logging level
|
||||
is returned.
|
||||
|
||||
@@ -249,6 +249,11 @@ Options
|
||||
For backward compatibility reasons, ``--loglevel`` is also accepted as a
|
||||
synonym for this option.
|
||||
|
||||
.. versionadded:: 3.25
|
||||
See the :command:`cmake_language`
|
||||
:ref:`cmake_language <query_message_log_level>` command for a way to query
|
||||
the current message logging level.
|
||||
|
||||
``--log-context``
|
||||
Enable the :command:`message` command outputting context attached to each
|
||||
message.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
cmake-language_GET_MESSAGE_LOG_LEVEL
|
||||
------------------------------------
|
||||
|
||||
* The :command:`cmake_language` command gained a new
|
||||
``GET_MESSAGE_LOG_LEVEL`` sub-command. It can be used to
|
||||
query the current message logging level.
|
||||
@@ -15,3 +15,8 @@ subsequent CMake runs will continue to use the chosen log level.
|
||||
|
||||
Projects should not set this variable, it is intended for users so that
|
||||
they may control the log level according to their own needs.
|
||||
|
||||
.. versionadded:: 3.25
|
||||
See the :command:`cmake_language`
|
||||
:ref:`cmake_language <query_message_log_level>` command for a way to query
|
||||
the current message logging level.
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmState.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmake.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -303,6 +305,27 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(
|
||||
std::vector<cmListFileArgument> const& args, cmExecutionStatus& status)
|
||||
{
|
||||
cmMakefile& makefile = status.GetMakefile();
|
||||
std::vector<std::string> expandedArgs;
|
||||
makefile.ExpandArguments(args, expandedArgs);
|
||||
|
||||
if (args.size() < 2 || expandedArgs.size() > 2) {
|
||||
return FatalError(
|
||||
status,
|
||||
"sub-command GET_MESSAGE_LOG_LEVEL expects exactly one argument");
|
||||
}
|
||||
|
||||
Message::LogLevel logLevel = makefile.GetCurrentLogLevel();
|
||||
std::string outputValue = cmake::LogLevelToString(logLevel);
|
||||
|
||||
const std::string& outputVariable = expandedArgs[1];
|
||||
makefile.AddDefinition(outputVariable, outputValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
|
||||
@@ -451,5 +474,9 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
|
||||
return cmCMakeLanguageCommandEVAL(args, status);
|
||||
}
|
||||
|
||||
if (expArgs[expArg] == "GET_MESSAGE_LOG_LEVEL") {
|
||||
return cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(args, status);
|
||||
}
|
||||
|
||||
return FatalError(status, "called with unknown meta-operation");
|
||||
}
|
||||
|
||||
@@ -149,6 +149,29 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const
|
||||
this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace);
|
||||
}
|
||||
|
||||
Message::LogLevel cmMakefile::GetCurrentLogLevel() const
|
||||
{
|
||||
const cmake* cmakeInstance = this->GetCMakeInstance();
|
||||
|
||||
const Message::LogLevel logLevelCliOrDefault = cmakeInstance->GetLogLevel();
|
||||
assert("Expected a valid log level here" &&
|
||||
logLevelCliOrDefault != Message::LogLevel::LOG_UNDEFINED);
|
||||
|
||||
Message::LogLevel result = logLevelCliOrDefault;
|
||||
|
||||
// If the log-level was set via the command line option, it takes precedence
|
||||
// over the CMAKE_MESSAGE_LOG_LEVEL variable.
|
||||
if (!cmakeInstance->WasLogLevelSetViaCLI()) {
|
||||
const Message::LogLevel logLevelFromVar = cmake::StringToLogLevel(
|
||||
this->GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
|
||||
if (logLevelFromVar != Message::LogLevel::LOG_UNDEFINED) {
|
||||
result = logLevelFromVar;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cmMakefile::CheckCMP0037(std::string const& targetName,
|
||||
cmStateEnums::TargetType targetType) const
|
||||
{
|
||||
|
||||
@@ -925,6 +925,7 @@ public:
|
||||
};
|
||||
|
||||
void IssueMessage(MessageType t, std::string const& text) const;
|
||||
Message::LogLevel GetCurrentLogLevel() const;
|
||||
|
||||
/** Set whether or not to report a CMP0000 violation. */
|
||||
void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
|
||||
|
||||
@@ -157,18 +157,7 @@ bool cmMessageCommand(std::vector<std::string> const& args,
|
||||
assert("Message log level expected to be set" &&
|
||||
level != Message::LogLevel::LOG_UNDEFINED);
|
||||
|
||||
auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel();
|
||||
assert("Expected a valid log level here" &&
|
||||
desiredLevel != Message::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 != Message::LogLevel::LOG_UNDEFINED) {
|
||||
desiredLevel = desiredLevelFromCache;
|
||||
}
|
||||
}
|
||||
Message::LogLevel desiredLevel = mf.GetCurrentLogLevel();
|
||||
|
||||
if (desiredLevel < level) {
|
||||
// Suppress the message
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "cmake.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -1402,21 +1403,32 @@ void cmake::SetArgs(const std::vector<std::string>& args)
|
||||
#endif
|
||||
}
|
||||
|
||||
Message::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
|
||||
namespace {
|
||||
using LevelsPair = std::pair<cm::string_view, Message::LogLevel>;
|
||||
using LevelsPairArray = std::array<LevelsPair, 7>;
|
||||
const LevelsPairArray& getStringToLogLevelPairs()
|
||||
{
|
||||
using LevelsPair = std::pair<std::string, Message::LogLevel>;
|
||||
static const std::vector<LevelsPair> levels = {
|
||||
{ "error", Message::LogLevel::LOG_ERROR },
|
||||
{ "warning", Message::LogLevel::LOG_WARNING },
|
||||
{ "notice", Message::LogLevel::LOG_NOTICE },
|
||||
{ "status", Message::LogLevel::LOG_STATUS },
|
||||
{ "verbose", Message::LogLevel::LOG_VERBOSE },
|
||||
{ "debug", Message::LogLevel::LOG_DEBUG },
|
||||
{ "trace", Message::LogLevel::LOG_TRACE }
|
||||
static const LevelsPairArray levels = {
|
||||
{ { "error", Message::LogLevel::LOG_ERROR },
|
||||
{ "warning", Message::LogLevel::LOG_WARNING },
|
||||
{ "notice", Message::LogLevel::LOG_NOTICE },
|
||||
{ "status", Message::LogLevel::LOG_STATUS },
|
||||
{ "verbose", Message::LogLevel::LOG_VERBOSE },
|
||||
{ "debug", Message::LogLevel::LOG_DEBUG },
|
||||
{ "trace", Message::LogLevel::LOG_TRACE } }
|
||||
};
|
||||
return levels;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const auto levelStrLowCase = cmSystemTools::LowerCase(levelStr);
|
||||
Message::LogLevel cmake::StringToLogLevel(cm::string_view levelStr)
|
||||
{
|
||||
const LevelsPairArray& levels = getStringToLogLevelPairs();
|
||||
|
||||
const auto levelStrLowCase =
|
||||
cmSystemTools::LowerCase(std::string{ levelStr });
|
||||
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
const auto it = std::find_if(levels.cbegin(), levels.cend(),
|
||||
[&levelStrLowCase](const LevelsPair& p) {
|
||||
return p.first == levelStrLowCase;
|
||||
@@ -1424,6 +1436,21 @@ Message::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
|
||||
return (it != levels.cend()) ? it->second : Message::LogLevel::LOG_UNDEFINED;
|
||||
}
|
||||
|
||||
std::string cmake::LogLevelToString(Message::LogLevel level)
|
||||
{
|
||||
const LevelsPairArray& levels = getStringToLogLevelPairs();
|
||||
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
const auto it =
|
||||
std::find_if(levels.cbegin(), levels.cend(),
|
||||
[&level](const LevelsPair& p) { return p.second == level; });
|
||||
const cm::string_view levelStrLowerCase =
|
||||
(it != levels.cend()) ? it->first : "undefined";
|
||||
std::string levelStrUpperCase =
|
||||
cmSystemTools::UpperCase(std::string{ levelStrLowerCase });
|
||||
return levelStrUpperCase;
|
||||
}
|
||||
|
||||
cmake::TraceFormat cmake::StringToTraceFormat(const std::string& traceStr)
|
||||
{
|
||||
using TracePair = std::pair<std::string, TraceFormat>;
|
||||
|
||||
@@ -458,7 +458,8 @@ public:
|
||||
//! Get the selected log level for `message()` commands during the cmake run.
|
||||
Message::LogLevel GetLogLevel() const { return this->MessageLogLevel; }
|
||||
void SetLogLevel(Message::LogLevel level) { this->MessageLogLevel = level; }
|
||||
static Message::LogLevel StringToLogLevel(const std::string& levelStr);
|
||||
static Message::LogLevel StringToLogLevel(cm::string_view levelStr);
|
||||
static std::string LogLevelToString(Message::LogLevel level);
|
||||
static TraceFormat StringToTraceFormat(const std::string& levelStr);
|
||||
|
||||
bool HasCheckInProgress() const
|
||||
|
||||
@@ -82,3 +82,61 @@ run_cmake(defer_get_call_id_var)
|
||||
run_cmake(defer_missing_arg)
|
||||
run_cmake(defer_missing_call)
|
||||
run_cmake(defer_unknown_option)
|
||||
|
||||
# Default log level
|
||||
run_cmake_command(
|
||||
get_message_log_level_none
|
||||
${CMAKE_COMMAND}
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
# Log level from cache
|
||||
run_cmake_command(
|
||||
get_message_log_level_cache
|
||||
${CMAKE_COMMAND}
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=TRACE
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
# Log level from regular variable
|
||||
run_cmake_command(
|
||||
get_message_log_level_var
|
||||
${CMAKE_COMMAND}
|
||||
-DNEW_LOG_LEVEL=TRACE
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
# Log level from command line
|
||||
run_cmake_command(
|
||||
get_message_log_level_cli
|
||||
${CMAKE_COMMAND}
|
||||
--log-level=DEBUG
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
# Log level from command line, it has higher priority over a cache variable
|
||||
run_cmake_command(
|
||||
get_message_log_level_cli_and_cache
|
||||
${CMAKE_COMMAND}
|
||||
--log-level=DEBUG
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=TRACE
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
# Log level from command line, it has higher priority over a regular variable
|
||||
run_cmake_command(
|
||||
get_message_log_level_cli_and_var
|
||||
${CMAKE_COMMAND}
|
||||
--log-level=DEBUG
|
||||
-DNEW_LOG_LEVEL=TRACE
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
# Log level from variable, it has higher priority over a cache variable
|
||||
run_cmake_command(
|
||||
get_message_log_level_var_and_cache
|
||||
${CMAKE_COMMAND}
|
||||
-DNEW_LOG_LEVEL=DEBUG
|
||||
-DCMAKE_MESSAGE_LOG_LEVEL=TRACE
|
||||
-P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
if(NEW_LOG_LEVEL)
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL "${NEW_LOG_LEVEL}")
|
||||
endif()
|
||||
cmake_language(GET_MESSAGE_LOG_LEVEL log_level)
|
||||
message(STATUS "log level is: ${log_level}")
|
||||
@@ -0,0 +1 @@
|
||||
log level is: TRACE
|
||||
@@ -0,0 +1 @@
|
||||
log level is: DEBUG
|
||||
@@ -0,0 +1 @@
|
||||
log level is: DEBUG
|
||||
@@ -0,0 +1 @@
|
||||
log level is: DEBUG
|
||||
@@ -0,0 +1 @@
|
||||
log level is: STATUS
|
||||
@@ -0,0 +1 @@
|
||||
log level is: TRACE
|
||||
@@ -0,0 +1 @@
|
||||
log level is: DEBUG
|
||||
Reference in New Issue
Block a user