浏览代码

message: Support logging a context with each message

Alex Turbov 6 年之前
父节点
当前提交
7cf79f4419

+ 12 - 1
Help/command/message.rst

@@ -63,11 +63,22 @@ To make a log level persist between CMake runs, the
 :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can be set instead.
 Note that the command line option takes precedence over the cache variable.
 
-Messages of log levels ``NOTICE`` and below will also have each line preceded
+Messages of log levels ``NOTICE`` and below will have each line preceded
 by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to
 a single string by concatenating its list items).  For ``STATUS`` to ``TRACE``
 messages, this indenting content will be inserted after the hyphens.
 
+Messages of log levels ``NOTICE`` and below can also have each line preceded
+with context of the form ``[some.context.example]``.  The content between the
+square brackets is obtained by converting the :variable:`CMAKE_MESSAGE_CONTEXT`
+list variable to a dot-separated string.  The message context will always
+appear before any indenting content but after any automatically added leading
+hyphens. By default, message context is not shown, it has to be explicitly
+enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context``
+command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW`
+variable to true.  See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for
+usage examples.
+
 CMake Warning and Error message text displays using a simple markup
 language.  Non-indented text is formatted in line-wrapped paragraphs
 delimited by newlines.  Indented text is considered pre-formatted.

+ 2 - 0
Help/manual/cmake-variables.7.rst

@@ -204,6 +204,8 @@ Variables that Change Behavior
    /variable/CMAKE_LINK_DIRECTORIES_BEFORE
    /variable/CMAKE_MFC_FLAG
    /variable/CMAKE_MAXIMUM_RECURSION_DEPTH
+   /variable/CMAKE_MESSAGE_CONTEXT
+   /variable/CMAKE_MESSAGE_CONTEXT_SHOW
    /variable/CMAKE_MESSAGE_INDENT
    /variable/CMAKE_MESSAGE_LOG_LEVEL
    /variable/CMAKE_MODULE_PATH

+ 10 - 0
Help/manual/cmake.1.rst

@@ -214,6 +214,16 @@ Options
  For backward compatibility reasons, ``--loglevel`` is also accepted as a
  synonym for this option.
 
+``--log-context``
+ Enable the :command:`message` command outputting context attached to each
+ message.
+
+ This option turns on showing context for the current CMake run only.
+ To make showing the context persistent for all subsequent CMake runs, set
+ :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` as a cache variable instead.
+ When this command line option is given, :variable:`CMAKE_MESSAGE_CONTEXT_SHOW`
+ is ignored.
+
 ``--debug-trycompile``
  Do not delete the :command:`try_compile` build tree.
  Only useful on one :command:`try_compile` at a time.

+ 5 - 0
Help/release/dev/feature-CMAKE_MESSAGE_CONTEXT

@@ -4,3 +4,8 @@ feature-CMAKE_MESSAGE_CONTEXT
 * The :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable can now be used
   to persist a log level between CMake runs, unlike the ``--log-level``
   command line option which only applies to that particular run.
+
+* The :command:`message` command learned to output context provided in
+  the :variable:`CMAKE_MESSAGE_CONTEXT` variable for log levels
+  ``NOTICE`` and below.  Enable this output with the new ``--log-context``
+  command-line option or :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable.

+ 62 - 0
Help/variable/CMAKE_MESSAGE_CONTEXT.rst

@@ -0,0 +1,62 @@
+CMAKE_MESSAGE_CONTEXT
+---------------------
+
+When enabled by the :manual:`cmake <cmake(1)>` ``--log-context`` command line
+option or the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable, the
+:command:`message` command converts the ``CMAKE_MESSAGE_CONTEXT`` list into a
+dot-separated string surrounded by square brackets and prepends it to each line
+for messages of log levels ``NOTICE`` and below.
+
+For logging contexts to work effectively, projects should generally
+``APPEND`` and ``POP_BACK`` an item to the current value of
+``CMAKE_MESSAGE_CONTEXT`` rather than replace it.
+Projects should not assume the message context at the top of the source tree
+is empty, as there are scenarios where the context might have already been set
+(e.g. hierarchical projects).
+
+.. warning::
+
+  Valid context names are restricted to anything that could be used
+  as a CMake variable name.  All names that begin with an underscore
+  or the string ``cmake_`` are also reserved for use by CMake and
+  should not be used by projects.
+
+Example:
+
+.. code-block:: cmake
+
+  function(bar)
+    list(APPEND CMAKE_MESSAGE_CONTEXT "bar")
+    message(VERBOSE "bar VERBOSE message")
+  endfunction()
+
+  function(baz)
+    list(APPEND CMAKE_MESSAGE_CONTEXT "baz")
+    message(DEBUG "baz DEBUG message")
+  endfunction()
+
+  function(foo)
+    list(APPEND CMAKE_MESSAGE_CONTEXT "foo")
+    bar()
+    message(TRACE "foo TRACE message")
+    baz()
+  endfunction()
+
+  list(APPEND CMAKE_MESSAGE_CONTEXT "top")
+
+  message(VERBOSE "Before `foo`")
+  foo()
+  message(VERBOSE "After `foo`")
+
+  list(POP_BACK CMAKE_MESSAGE_CONTEXT)
+
+
+Which results in the following output:
+
+.. code-block:: none
+
+  -- [top] Before `foo`
+  -- [top.foo.bar] bar VERBOSE message
+  -- [top.foo] foo TRACE message
+  -- [top.foo.baz] baz DEBUG message
+  -- [top] After `foo`

+ 15 - 0
Help/variable/CMAKE_MESSAGE_CONTEXT_SHOW.rst

@@ -0,0 +1,15 @@
+CMAKE_MESSAGE_CONTEXT_SHOW
+--------------------------
+
+Setting this variable to true enables showing a context with each line
+logged by the :command:`message` command (see :variable:`CMAKE_MESSAGE_CONTEXT`
+for how the context itself is specified).
+
+This variable is an alternative to providing the ``--log-context`` option
+on the :manual:`cmake <cmake(1)>` command line.  Whereas the command line
+option will apply only to that one CMake run, setting
+``CMAKE_MESSAGE_CONTEXT_SHOW`` to true as a cache variable will ensure that
+subsequent CMake runs will continue to show the message context.
+
+Projects should not set ``CMAKE_MESSAGE_CONTEXT_SHOW``.  It is intended for
+users so that they may control whether or not to include context with messages.

+ 17 - 8
Source/cmMessageCommand.cxx

@@ -112,16 +112,25 @@ bool cmMessageCommand(std::vector<std::string> const& args,
   auto message = cmJoin(cmMakeRange(i, args.cend()), "");
 
   if (cmake::LogLevel::LOG_NOTICE <= level) {
-    // Check if any indentation has requested:
-    // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces
-    // to be joined and prepended to the message lines.
     auto indent =
       cmJoin(cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_INDENT")), "");
-    // Make every line of the `message` indented
-    // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted`
-    // here cuz it appends `\n` to the EOM ;-(
-    cmSystemTools::ReplaceString(message, "\n", "\n" + indent);
-    message = indent + message;
+    if (!indent.empty()) {
+      cmSystemTools::ReplaceString(message, "\n", "\n" + indent);
+      message = indent + message;
+    }
+
+    const auto showContext = mf.GetCMakeInstance()->GetShowLogContext() ||
+      mf.IsOn("CMAKE_MESSAGE_CONTEXT_SHOW");
+    if (showContext) {
+      // Output the current context (if any)
+      auto context = cmJoin(
+        cmExpandedList(mf.GetSafeDefinition("CMAKE_MESSAGE_CONTEXT")), ".");
+      if (!context.empty()) {
+        context = "[" + context + "] ";
+        cmSystemTools::ReplaceString(message, "\n", "\n" + context);
+        message = context + message;
+      }
+    }
   }
 
   switch (level) {

+ 2 - 0
Source/cmake.cxx

@@ -746,6 +746,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
       }
       this->SetLogLevel(logLevel);
       this->LogLevelWasSetViaCLI = true;
+    } else if (arg == "--log-context") {
+      this->SetShowLogContext(true);
     } else if (arg.find("--trace-expand", 0) == 0) {
       std::cout << "Running with expanded trace output on.\n";
       this->SetTrace(true);

+ 5 - 0
Source/cmake.h

@@ -391,6 +391,10 @@ public:
   bool GetDebugOutput() { return this->DebugOutput; }
   void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
 
+  //! Should `message` command display context.
+  bool GetShowLogContext() const { return this->LogContext; }
+  void SetShowLogContext(bool b) { this->LogContext = b; }
+
   //! Do we want trace output during the cmake run.
   bool GetTrace() { return this->Trace; }
   void SetTrace(bool b) { this->Trace = b; }
@@ -590,6 +594,7 @@ private:
 
   LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
   bool LogLevelWasSetViaCLI = false;
+  bool LogContext = false;
 
   void UpdateConversionPathTable();
 

+ 1 - 0
Source/cmakemain.cxx

@@ -73,6 +73,7 @@ const char* cmDocumentationOptions[][2] = {
   { "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>",
     "Set the verbosity of messages from CMake files. "
     "--loglevel is also accepted for backward compatibility reasons." },
+  { "--log-context", "Prepend log messages with context, if given" },
   { "--debug-trycompile",
     "Do not delete the try_compile build tree. Only "
     "useful on one try_compile at a time." },

+ 15 - 0
Tests/RunCMake/message/RunCMakeTest.cmake

@@ -68,3 +68,18 @@ run_cmake_command(
     message-indent-multiline
     ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent-multiline.cmake
   )
+
+run_cmake_command(
+    message-context-cli
+    ${CMAKE_COMMAND} --log-level=trace --log-context -P ${RunCMake_SOURCE_DIR}/message-context.cmake
+  )
+
+run_cmake_command(
+    message-context-cache
+    ${CMAKE_COMMAND} -DCMAKE_MESSAGE_LOG_LEVEL=TRACE -DCMAKE_MESSAGE_CONTEXT_SHOW=ON -P ${RunCMake_SOURCE_DIR}/message-context.cmake
+  )
+
+run_cmake_command(
+    message-context-cli-wins-cache
+    ${CMAKE_COMMAND} --log-level=verbose --log-context -DCMAKE_MESSAGE_CONTEXT_SHOW=OFF -P ${RunCMake_SOURCE_DIR}/message-context.cmake
+  )

+ 8 - 0
Tests/RunCMake/message/message-context-cache-stdout.txt

@@ -0,0 +1,8 @@
+-- Begin context output test
+-- \[top\] Top: before
+-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message
+-- \[top\.foo\] foo TRACE message
+-- \[top\.foo\.baz\] This is the multi-line
+\[top\.foo\.baz\] baz DEBUG message
+-- \[top\] Top: after
+-- End of context output test

+ 8 - 0
Tests/RunCMake/message/message-context-cli-stdout.txt

@@ -0,0 +1,8 @@
+-- Begin context output test
+-- \[top\] Top: before
+-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message
+-- \[top\.foo\] foo TRACE message
+-- \[top\.foo\.baz\] This is the multi-line
+\[top\.foo\.baz\] baz DEBUG message
+-- \[top\] Top: after
+-- End of context output test

+ 5 - 0
Tests/RunCMake/message/message-context-cli-wins-cache-stdout.txt

@@ -0,0 +1,5 @@
+-- Begin context output test
+-- \[top\] Top: before
+-- \[top\.foo\.bar\] <-- indent -->bar VERBOSE message
+-- \[top\] Top: after
+-- End of context output test

+ 27 - 0
Tests/RunCMake/message/message-context.cmake

@@ -0,0 +1,27 @@
+function(bar)
+    list(APPEND CMAKE_MESSAGE_CONTEXT "bar")
+    list(APPEND CMAKE_MESSAGE_INDENT "<-- indent -->")
+    message(VERBOSE "bar VERBOSE message")
+endfunction()
+
+function(baz)
+    list(APPEND CMAKE_MESSAGE_CONTEXT "baz")
+    message(DEBUG "This is the multi-line\nbaz DEBUG message")
+endfunction()
+
+function(foo)
+    list(APPEND CMAKE_MESSAGE_CONTEXT "foo")
+    bar()
+    message(TRACE "foo TRACE message")
+    baz()
+endfunction()
+
+message(STATUS "Begin context output test")
+list(APPEND CMAKE_MESSAGE_CONTEXT "top")
+
+message(STATUS "Top: before")
+foo()
+message(STATUS "Top: after")
+
+list(POP_BACK CMAKE_MESSAGE_CONTEXT)
+message(STATUS "End of context output test")