Browse Source

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.
pull/348/head
Braulio Valdivielso Martinez 4 years ago
parent
commit
a41d6e4d7a
  1. 13
      Help/manual/cmake.1.rst
  2. 8
      Help/release/dev/trace-global-frame.rst
  3. 2
      Source/cmMakefile.cxx
  4. 2
      Source/cmake.cxx
  5. 14
      Tests/RunCMake/CommandLine/trace-json-v1-check.py
  6. 9
      Tests/RunCMake/CommandLine/trace-json-v1-nested/CMakeLists.txt
  7. 1
      Tests/RunCMake/CommandLine/trace-json-v1.cmake
  8. 6
      Tests/RunCMake/cmake_language/defer_call_trace_json-stderr.txt

13
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
}
}

8
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.

2
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;

2
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

14
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)

9
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()

1
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)

6
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$
Loading…
Cancel
Save