summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBraulio Valdivielso Martinez <bvaldivielso@bloomberg.net>2022-02-04 12:19:32 -0500
committerBraulio Valdivielso Martinez <bvaldivielso@bloomberg.net>2022-02-07 16:03:22 -0500
commita41d6e4d7a264954bebd6c1c45475647da60e14c (patch)
treec080acd8e9a85ae4b43387ae2ec9f380bf6af382
parentca4bb89f276e244b5b56d1988cd659d30df1ca5a (diff)
downloadcmake-a41d6e4d7a264954bebd6c1c45475647da60e14c.tar.gz
Trace: add global_frame field to json-v1 format
Tools using the json-v1 format might want to trace stack frames across different `CMakeLists.txt` files, in order to, for example, provide stacktraces that span from the top-level `CMakeLists.txt` in a project. One would think that `frame` lets you do that, but it doesn't, because it tells you the depth of the stack within the current `CMakeLists.txt`, so it gets reset across calls to `add_subdirectory`. The solution involves adding a field with a "global frame". This value gets incremented on calls to `add_subdirectory`, which makes it easier for tools to reconstruct "global stacktraces". I considered changing the current "frame" value, but I didn't because it would be a breaking change. I cannot think of any use-case where "frame" is more useful to "global-frame", but maybe I'm missing something.
-rw-r--r--Help/manual/cmake.1.rst13
-rw-r--r--Help/release/dev/trace-global-frame.rst8
-rw-r--r--Source/cmMakefile.cxx2
-rw-r--r--Source/cmake.cxx2
-rwxr-xr-xTests/RunCMake/CommandLine/trace-json-v1-check.py14
-rw-r--r--Tests/RunCMake/CommandLine/trace-json-v1-nested/CMakeLists.txt9
-rw-r--r--Tests/RunCMake/CommandLine/trace-json-v1.cmake1
-rw-r--r--Tests/RunCMake/cmake_language/defer_call_trace_json-stderr.txt6
8 files changed, 45 insertions, 10 deletions
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index c2b4d68e7b..2102b36209 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -298,7 +298,8 @@ Options
"cmd": "add_executable",
"args": ["foo", "bar"],
"time": 1579512535.9687231,
- "frame": 2
+ "frame": 2,
+ "global_frame": 4
}
The members are:
@@ -325,7 +326,13 @@ Options
Timestamp (seconds since epoch) of the function call.
``frame``
- Stack frame depth of the function that was called.
+ Stack frame depth of the function that was called, within the
+ context of the ``CMakeLists.txt`` being processed currently.
+
+ ``global_frame``
+ Stack frame depth of the function that was called, tracked globally
+ across all ``CMakeLists.txt`` files involved in the trace. This field
+ was added in minor version 2 of the ``json-v1`` format.
Additionally, the first JSON document outputted contains the
``version`` key for the current major and minor version of the
@@ -337,7 +344,7 @@ Options
{
"version": {
"major": 1,
- "minor": 1
+ "minor": 2
}
}
diff --git a/Help/release/dev/trace-global-frame.rst b/Help/release/dev/trace-global-frame.rst
new file mode 100644
index 0000000000..fdc4b5cb26
--- /dev/null
+++ b/Help/release/dev/trace-global-frame.rst
@@ -0,0 +1,8 @@
+trace-global-frame
+------------------
+
+* Add the field ``global_frame`` to the json-v1 trace format. This
+ frame tracks the depth of the call stack globally across all
+ ``CMakeLists.txt`` files involved in the trace, and will let tools
+ reconstruct stack traces that span from the top-level ``CMakeLists.txt``
+ file of the project.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 4b1635b6ae..34d3efa2d8 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -302,6 +302,8 @@ void cmMakefile::PrintCommandTrace(
val["time"] = cmSystemTools::GetTime();
val["frame"] =
static_cast<Json::Value::UInt64>(this->ExecutionStatusStack.size());
+ val["global_frame"] =
+ static_cast<Json::Value::UInt64>(this->RecursionDepth);
msg << Json::writeString(builder, val);
#endif
break;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index ef4e37beef..85ac9ca10e 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1434,7 +1434,7 @@ void cmake::PrintTraceFormatVersion()
Json::StreamWriterBuilder builder;
builder["indentation"] = "";
version["major"] = 1;
- version["minor"] = 1;
+ version["minor"] = 2;
val["version"] = version;
msg = Json::writeString(builder, val);
#endif
diff --git a/Tests/RunCMake/CommandLine/trace-json-v1-check.py b/Tests/RunCMake/CommandLine/trace-json-v1-check.py
index 1ee005ede2..995cfad32f 100755
--- a/Tests/RunCMake/CommandLine/trace-json-v1-check.py
+++ b/Tests/RunCMake/CommandLine/trace-json-v1-check.py
@@ -46,8 +46,15 @@ required_traces = [
{
'args': msg_args,
'cmd': 'message',
- 'frame': 3 if expand else 2
+ 'frame': 3 if expand else 2,
+ 'global_frame': 3 if expand else 2
},
+ {
+ 'args': ['STATUS', 'nested global_frame'],
+ 'cmd': 'message',
+ 'frame': 3,
+ 'global_frame': 6 if expand else 5
+ }
]
with open(trace_file, 'r') as fp:
@@ -56,15 +63,16 @@ with open(trace_file, 'r') as fp:
assert sorted(vers.keys()) == ['version']
assert sorted(vers['version'].keys()) == ['major', 'minor']
assert vers['version']['major'] == 1
- assert vers['version']['minor'] == 1
+ assert vers['version']['minor'] == 2
for i in fp.readlines():
line = json.loads(i)
- assert sorted(line.keys()) == ['args', 'cmd', 'file', 'frame', 'line', 'time']
+ assert sorted(line.keys()) == ['args', 'cmd', 'file', 'frame', 'global_frame','line', 'time']
assert isinstance(line['args'], list)
assert isinstance(line['cmd'], unicode)
assert isinstance(line['file'], unicode)
assert isinstance(line['frame'], int)
+ assert isinstance(line['global_frame'], int)
assert isinstance(line['line'], int)
assert isinstance(line['time'], float)
diff --git a/Tests/RunCMake/CommandLine/trace-json-v1-nested/CMakeLists.txt b/Tests/RunCMake/CommandLine/trace-json-v1-nested/CMakeLists.txt
new file mode 100644
index 0000000000..089a960c2e
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/trace-json-v1-nested/CMakeLists.txt
@@ -0,0 +1,9 @@
+function(f)
+ message(STATUS "nested global_frame")
+endfunction()
+
+function(g)
+ f()
+endfunction()
+
+g()
diff --git a/Tests/RunCMake/CommandLine/trace-json-v1.cmake b/Tests/RunCMake/CommandLine/trace-json-v1.cmake
index ed0a0f9a3e..871746da23 100644
--- a/Tests/RunCMake/CommandLine/trace-json-v1.cmake
+++ b/Tests/RunCMake/CommandLine/trace-json-v1.cmake
@@ -3,3 +3,4 @@ set(ASDF fff sss " SPACES !!! ")
set(FOO 42)
set(BAR " space in string!")
message(STATUS fff ${ASDF} " ${FOO} ${BAR}" " SPACES !!! ")
+add_subdirectory(trace-json-v1-nested)
diff --git a/Tests/RunCMake/cmake_language/defer_call_trace_json-stderr.txt b/Tests/RunCMake/cmake_language/defer_call_trace_json-stderr.txt
index 647beb05ca..3bde16d454 100644
--- a/Tests/RunCMake/cmake_language/defer_call_trace_json-stderr.txt
+++ b/Tests/RunCMake/cmake_language/defer_call_trace_json-stderr.txt
@@ -1,5 +1,5 @@
-{"args":\["DEFER","CALL","message","Deferred Message"\],"cmd":"cmake_language","file":"[^"]*/Tests/RunCMake/cmake_language/defer_call_trace_json.cmake","frame":2,"line":2,"time":[0-9.]+}
-{"args":\["Immediate Message"\],"cmd":"message","file":"[^"]*/Tests/RunCMake/cmake_language/defer_call_trace_json.cmake","frame":2,"line":3,"time":[0-9.]+}
+{"args":\["DEFER","CALL","message","Deferred Message"\],"cmd":"cmake_language","file":"[^"]*/Tests/RunCMake/cmake_language/defer_call_trace_json.cmake","frame":2,"global_frame":2,"line":2,"time":[0-9.]+}
+{"args":\["Immediate Message"\],"cmd":"message","file":"[^"]*/Tests/RunCMake/cmake_language/defer_call_trace_json.cmake","frame":2,"global_frame":2,"line":3,"time":[0-9.]+}
Immediate Message
-{"args":\["Deferred Message"],"cmd":"message","defer":"__0","file":"[^"]*/Tests/RunCMake/cmake_language/defer_call_trace_json.cmake","frame":1,"line":2,"time":[0-9.]+}
+{"args":\["Deferred Message"],"cmd":"message","defer":"__0","file":"[^"]*/Tests/RunCMake/cmake_language/defer_call_trace_json.cmake","frame":1,"global_frame":1,"line":2,"time":[0-9.]+}
Deferred Message$