mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-03 12:49:50 -05:00
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.
This commit is contained in:
+10
-3
@@ -298,7 +298,8 @@ Options
|
|||||||
"cmd": "add_executable",
|
"cmd": "add_executable",
|
||||||
"args": ["foo", "bar"],
|
"args": ["foo", "bar"],
|
||||||
"time": 1579512535.9687231,
|
"time": 1579512535.9687231,
|
||||||
"frame": 2
|
"frame": 2,
|
||||||
|
"global_frame": 4
|
||||||
}
|
}
|
||||||
|
|
||||||
The members are:
|
The members are:
|
||||||
@@ -325,7 +326,13 @@ Options
|
|||||||
Timestamp (seconds since epoch) of the function call.
|
Timestamp (seconds since epoch) of the function call.
|
||||||
|
|
||||||
``frame``
|
``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
|
Additionally, the first JSON document outputted contains the
|
||||||
``version`` key for the current major and minor version of the
|
``version`` key for the current major and minor version of the
|
||||||
@@ -337,7 +344,7 @@ Options
|
|||||||
{
|
{
|
||||||
"version": {
|
"version": {
|
||||||
"major": 1,
|
"major": 1,
|
||||||
"minor": 1
|
"minor": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -302,6 +302,8 @@ void cmMakefile::PrintCommandTrace(
|
|||||||
val["time"] = cmSystemTools::GetTime();
|
val["time"] = cmSystemTools::GetTime();
|
||||||
val["frame"] =
|
val["frame"] =
|
||||||
static_cast<Json::Value::UInt64>(this->ExecutionStatusStack.size());
|
static_cast<Json::Value::UInt64>(this->ExecutionStatusStack.size());
|
||||||
|
val["global_frame"] =
|
||||||
|
static_cast<Json::Value::UInt64>(this->RecursionDepth);
|
||||||
msg << Json::writeString(builder, val);
|
msg << Json::writeString(builder, val);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-1
@@ -1434,7 +1434,7 @@ void cmake::PrintTraceFormatVersion()
|
|||||||
Json::StreamWriterBuilder builder;
|
Json::StreamWriterBuilder builder;
|
||||||
builder["indentation"] = "";
|
builder["indentation"] = "";
|
||||||
version["major"] = 1;
|
version["major"] = 1;
|
||||||
version["minor"] = 1;
|
version["minor"] = 2;
|
||||||
val["version"] = version;
|
val["version"] = version;
|
||||||
msg = Json::writeString(builder, val);
|
msg = Json::writeString(builder, val);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,8 +46,15 @@ required_traces = [
|
|||||||
{
|
{
|
||||||
'args': msg_args,
|
'args': msg_args,
|
||||||
'cmd': 'message',
|
'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:
|
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.keys()) == ['version']
|
||||||
assert sorted(vers['version'].keys()) == ['major', 'minor']
|
assert sorted(vers['version'].keys()) == ['major', 'minor']
|
||||||
assert vers['version']['major'] == 1
|
assert vers['version']['major'] == 1
|
||||||
assert vers['version']['minor'] == 1
|
assert vers['version']['minor'] == 2
|
||||||
|
|
||||||
for i in fp.readlines():
|
for i in fp.readlines():
|
||||||
line = json.loads(i)
|
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['args'], list)
|
||||||
assert isinstance(line['cmd'], unicode)
|
assert isinstance(line['cmd'], unicode)
|
||||||
assert isinstance(line['file'], unicode)
|
assert isinstance(line['file'], unicode)
|
||||||
assert isinstance(line['frame'], int)
|
assert isinstance(line['frame'], int)
|
||||||
|
assert isinstance(line['global_frame'], int)
|
||||||
assert isinstance(line['line'], int)
|
assert isinstance(line['line'], int)
|
||||||
assert isinstance(line['time'], float)
|
assert isinstance(line['time'], float)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
function(f)
|
||||||
|
message(STATUS "nested global_frame")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(g)
|
||||||
|
f()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
g()
|
||||||
@@ -3,3 +3,4 @@ set(ASDF fff sss " SPACES !!! ")
|
|||||||
set(FOO 42)
|
set(FOO 42)
|
||||||
set(BAR " space in string!")
|
set(BAR " space in string!")
|
||||||
message(STATUS fff ${ASDF} " ${FOO} ${BAR}" " SPACES !!! ")
|
message(STATUS fff ${ASDF} " ${FOO} ${BAR}" " SPACES !!! ")
|
||||||
|
add_subdirectory(trace-json-v1-nested)
|
||||||
|
|||||||
@@ -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":\["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,"line":3,"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
|
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$
|
Deferred Message$
|
||||||
|
|||||||
Reference in New Issue
Block a user