1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

cmake_language: add TRACE subcommand

Closes 27235.
This commit is contained in:
Alex Turbov
2025-09-22 19:59:21 +04:00
parent c9dccc6d15
commit cb07358256
33 changed files with 207 additions and 2 deletions

View File

@@ -16,6 +16,7 @@ Synopsis
cmake_language(`SET_DEPENDENCY_PROVIDER`_ <command> SUPPORTED_METHODS <methods>...)
cmake_language(`GET_MESSAGE_LOG_LEVEL`_ <out-var>)
cmake_language(`EXIT`_ <exit-code>)
cmake_language(`TRACE`_ <boolean> ...)
Introduction
^^^^^^^^^^^^
@@ -534,3 +535,27 @@ Terminating Scripts
shell or platform, and some shells may interpret values
above 125 specially. Therefore, it is advisable to only
specify an ``<exit-code>`` in the range 0 to 125.
.. _trace:
Trace Control
^^^^^^^^^^^^^
.. versionadded:: 4.2
.. signature::
cmake_language(TRACE ON [EXPAND])
cmake_language(TRACE OFF)
The TRACE subcommand controls runtime tracing of executed CMake commands and
macros within the current process. When enabled, trace output is written
in the same format as if CMake had been started with the
:option:`cmake --trace` or :option:`cmake --trace-expand` command line options.
Tracing scopes are nestable. Multiple ``TRACE ON`` calls may be active at the
same time, and each ``TRACE OFF`` deactivates one nesting level.
If CMake is run with :option:`cmake --trace` or :option:`cmake --trace-expand`,
those options override and force tracing globally, regardless of
``cmake_language(TRACE OFF)`` calls. In such cases, the command may still
be invoked but has no effect on the trace state.

View File

@@ -0,0 +1,5 @@
cmake_language_TRACE
--------------------
* The :command:`cmake_language` command gained a new ``TRACE`` subcommand
to enable or disable tracing during script execution.

View File

@@ -25,6 +25,7 @@
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -542,5 +543,40 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
status);
}
if (expArgs[expArg] == "TRACE") {
++expArg; // Consume "TRACE".
if (!moreArgs()) {
return FatalError(status, "TRACE missing a boolean value");
}
bool const value = cmValue::IsOn(expArgs[expArg++]);
bool expand = false;
if (value && moreArgs()) {
expand = (expArgs[expArg] == "EXPAND");
if (!expand) {
return FatalError(
status,
cmStrCat("TRACE ON given an invalid argument ", expArgs[expArg]));
}
++expArg;
}
if (moreArgs()) {
return FatalError(
status,
cmStrCat("TRACE O", value ? "N" : "FF", " given too many arguments"));
}
cmMakefile& makefile = status.GetMakefile();
if (value) {
makefile.GetCMakeInstance()->PushTraceCmd(expand);
return true;
}
return makefile.GetCMakeInstance()->PopTraceCmd() ||
FatalError(status, "TRACE OFF request without a corresponding TRACE ON");
}
return FatalError(status, "called with unknown meta-operation");
}

View File

@@ -1764,6 +1764,16 @@ cmake::TraceFormat cmake::StringToTraceFormat(std::string const& traceStr)
return (it != levels.cend()) ? it->second : TraceFormat::Undefined;
}
bool cmake::PopTraceCmd()
{
if (this->cmakeLangTraceCmdStack.empty()) {
// Nothing to pop! A caller should report an error.
return false;
}
this->cmakeLangTraceCmdStack.pop();
return true;
}
void cmake::SetTraceFile(std::string const& file)
{
this->TraceFile.close();

View File

@@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <set>
#include <stack>
#include <string>
#include <unordered_set>
#include <utility>
@@ -527,9 +528,22 @@ public:
void SetDebugFindOutputVars(std::string const& args);
//! Do we want trace output during the cmake run.
bool GetTrace() const { return this->Trace; }
bool GetTrace() const
{
return this->Trace || !this->cmakeLangTraceCmdStack.empty();
}
void SetTrace(bool b) { this->Trace = b; }
bool GetTraceExpand() const { return this->TraceExpand; }
void PushTraceCmd(bool expandFlag)
{
this->cmakeLangTraceCmdStack.emplace(expandFlag);
}
bool PopTraceCmd();
bool GetTraceExpand() const
{
return this->TraceExpand ||
(!this->cmakeLangTraceCmdStack.empty() &&
this->cmakeLangTraceCmdStack.top());
}
void SetTraceExpand(bool b) { this->TraceExpand = b; }
TraceFormat GetTraceFormat() const { return this->TraceFormatVar; }
void SetTraceFormat(TraceFormat f) { this->TraceFormatVar = f; }
@@ -806,6 +820,10 @@ private:
CommandFailureAction::FATAL_ERROR;
bool DebugOutput = false;
bool DebugFindOutput = false;
// Elements of `cmakeLangTraceCmdStack` are "trace requests" pushed
// by `cmake_language(TRACE ON [EXPAND])` and a boolean value is
// a state of a given `EXPAND` option.
std::stack<bool> cmakeLangTraceCmdStack;
bool Trace = false;
bool TraceExpand = false;
TraceFormat TraceFormatVar = TraceFormat::Human;

View File

@@ -164,3 +164,19 @@ run_cmake(Experimental/ExportPackageDependencies-set)
run_cmake(Experimental/ExportPackageDependencies-unset)
run_cmake(Experimental/ExportPackageDependencies-wrong)
run_cmake(Experimental/Unknown)
run_cmake(trace)
run_cmake(trace_seq)
run_cmake(trace_expand)
run_cmake(trace_nested)
run_cmake(trace_unballanced)
run_cmake(trace_invalid_arg)
run_cmake(trace_too_few_args)
run_cmake(trace_ON_too_many_args)
run_cmake(trace_OFF_too_many_args)
block()
set(RunCMake_TEST_OPTIONS --trace --trace-source=trace_cli_wins.cmake)
run_cmake(trace_cli_wins)
set(RunCMake_TEST_OPTIONS --trace-expand --trace-source=trace_expand_cli_wins.cmake)
run_cmake(trace_expand_cli_wins)
endblock()

View File

@@ -0,0 +1,2 @@
.*/trace\.cmake\(3\): set\(foo \${bar} \)
.*/trace\.cmake\(4\): cmake_language\(TRACE OFF \)

View File

@@ -0,0 +1,4 @@
set(bar "bar")
cmake_language(TRACE ON)
set(foo "${bar}")
cmake_language(TRACE OFF)

View File

@@ -0,0 +1,4 @@
CMake Error at trace_OFF_too_many_args\.cmake:1 \(cmake_language\):
cmake_language TRACE OFF given too many arguments
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1 @@
cmake_language(TRACE OFF EXTRA)

View File

@@ -0,0 +1,4 @@
CMake Error at trace_ON_too_many_args\.cmake:1 \(cmake_language\):
cmake_language TRACE ON given too many arguments
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1 @@
cmake_language(TRACE ON EXPAND EXTRA)

View File

@@ -0,0 +1,5 @@
.*/trace_cli_wins\.cmake\(1\): set\(bar bar \)
.*/trace_cli_wins\.cmake\(2\): cmake_language\(TRACE ON EXPAND \)
.*/trace_cli_wins\.cmake\(3\): set\(foo bar \)
.*/trace_cli_wins\.cmake\(4\): cmake_language\(TRACE OFF \)
.*/trace_cli_wins\.cmake\(5\): set\(foo \${bar} \)

View File

@@ -0,0 +1,5 @@
set(bar "bar")
cmake_language(TRACE ON EXPAND)
set(foo "${bar}") # NOTE Will be expanded
cmake_language(TRACE OFF)
set(foo "${bar}")

View File

@@ -0,0 +1,2 @@
.*/trace_expand\.cmake\(3\): set\(foo bar \)
.*/trace_expand\.cmake\(4\): cmake_language\(TRACE OFF \)

View File

@@ -0,0 +1,4 @@
set(bar "bar")
cmake_language(TRACE ON EXPAND)
set(foo "${bar}")
cmake_language(TRACE OFF)

View File

@@ -0,0 +1,5 @@
.*/trace_expand_cli_wins\.cmake\(1\): set\(bar bar \)
.*/trace_expand_cli_wins\.cmake\(2\): cmake_language\(TRACE ON \)
.*/trace_expand_cli_wins\.cmake\(3\): set\(foo bar \)
.*/trace_expand_cli_wins\.cmake\(4\): cmake_language\(TRACE OFF \)
.*/trace_expand_cli_wins\.cmake\(5\): set\(foo bar \)

View File

@@ -0,0 +1,5 @@
set(bar "bar")
cmake_language(TRACE ON)
set(foo "${bar}") # NOTE Will be expanded
cmake_language(TRACE OFF)
set(foo "${bar}")

View File

@@ -0,0 +1,4 @@
CMake Error at trace_invalid_arg\.cmake:1 \(cmake_language\):
cmake_language TRACE ON given an invalid argument XPAND
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1 @@
cmake_language(TRACE TRUE XPAND)

View File

@@ -0,0 +1,8 @@
.*/trace_nested\.cmake\(3\): set\(foo \${bar} \)
.*/trace_nested\.cmake\(4\): cmake_language\(TRACE ON EXPAND \)
.*/trace_nested\.cmake\(5\): set\(foo bar \)
.*/trace_nested\.cmake\(6\): cmake_language\(TRACE ON \)
.*/trace_nested\.cmake\(7\): set\(foo \${bar} \)
.*/trace_nested\.cmake\(8\): cmake_language\(TRACE OFF \)
.*/trace_nested\.cmake\(9\): cmake_language\(TRACE OFF \)
.*/trace_nested\.cmake\(10\): cmake_language\(TRACE OFF \)

View File

@@ -0,0 +1,10 @@
set(bar "bar")
cmake_language(TRACE ON)
set(foo "${bar}")
cmake_language(TRACE ON EXPAND)
set(foo "${bar}")
cmake_language(TRACE ON)
set(foo "${bar}")
cmake_language(TRACE OFF)
cmake_language(TRACE OFF)
cmake_language(TRACE OFF)

View File

@@ -0,0 +1,4 @@
.*/trace_seq\.cmake\(3\): set\(foo \${bar} \)
.*/trace_seq\.cmake\(4\): cmake_language\(TRACE OFF \)
.*/trace_seq\.cmake\(7\): set\(foo \${bar} \)
.*/trace_seq\.cmake\(8\): cmake_language\(TRACE OFF \)

View File

@@ -0,0 +1,9 @@
set(bar "bar")
cmake_language(TRACE ON)
set(foo "${bar}")
cmake_language(TRACE OFF)
set(foo "${bar}")
cmake_language(TRACE ON)
set(foo "${bar}")
cmake_language(TRACE OFF)
set(foo "${bar}")

View File

@@ -0,0 +1,4 @@
CMake Error at trace_too_few_args\.cmake:1 \(cmake_language\):
cmake_language TRACE missing a boolean value
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1 @@
cmake_language(TRACE)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,6 @@
.*/trace_unballanced\.cmake\(3\): set\(foo \${bar} \)
.*/trace_unballanced\.cmake\(4\): cmake_language\(TRACE OFF \)
CMake Error at trace_unballanced\.cmake:5 \(cmake_language\):
cmake_language TRACE OFF request without a corresponding TRACE ON
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1,5 @@
set(bar "bar")
cmake_language(TRACE ON)
set(foo "${bar}")
cmake_language(TRACE OFF)
cmake_language(TRACE OFF)