Branch | Drone CI |
---|---|
A collection of helpers for convenient use of GDB pretty printers with accompanying build system modules.
Warning
|
Not an official Boost tool yet! |
The core of this project is a couple of utility Python scripts.
-
embed-gdb-extension.py takes a Python GDB extension module (the most common such extesnsion is a set of pretty printers) and produces C code that pushes the contents of that module into a special binary section, so that GDB could automatically load those pretty printers during debugging.
-
generate-gdb-test-runner.py takes C or C++ source files that have special comment lines and creates a Python program that sets breakpoints on those lines to check if printed expressions produce the desired output.
For convenience of using the provided tools the project also provides a CMake module and a b2 module. For direct usage consult the Direct usage subsection in the API section.
Note, you don’t have to add your build directory to GDB’s autoload safe paths if you are using build system functions. The functions invoke GDB with the necessary flag to enable autoloading of extensions.
# CMakeLists.txt
find_package(BoostPrettyPrinters)
if(BoostPrettyPrinters_FOUND)
boost_pretty_printers_embed_gdb_extension(
TARGET regenerate_printers
INPUT gdb_printers.py
OUTPUT include/myproject/gdb_printers.hpp
EXCLUDE_FROM_ALL)
endif()
# test/CMakeLists.txt
if(BoostPrettyPrinters_GDB_FOUND)
boost_pretty_printers_test_gdb_printers(
TEST test_gdb_printers
SOURCES printers.cpp
EXCLUDE_FROM_ALL)
target_link_libraries(test_gdb_printers PRIVATE myproject)
endif()
Note: In order for find_package
to find the provided CMake module you
need to append the installation directory of PrettyPrinters to
CMAKE_MODULE_PATH
variable. This is normally done either from the command
line or via presets. For example:
cmake -S.. -B. -DCMAKE_MODULE_PATH=path/to/pretty_printers
# build.jam
using boost-pretty-printers ;
import boost-pretty-printers ;
boost-pretty-printers.gdb-python-header gdb_printers.hpp
: gdb_printers.py
: <location>include/mymproject
;
always gdb_printers.hpp ;
alias regenerate-printers : gdb_printers.hpp ;
explicit regenerate-printers gdb_printers.hpp ;
# test/build.jam
import boost-pretty-printers ;
boost-pretty-printers.test-gdb-printers gdb-printers
: printers.cpp
..//myproject
;
explicit gdb-printers ;
find_package(BoostPrettyPrinters [QUIET])
The package has only one component: GDB
.
- BoostPrettyPrinters::GDB
-
The GDB executable to use. This target is defined only if the
GDB
component is found.
This module will set the following variables in your project:.
- BoostPrettyPrinters_FOUND
-
True if both the module and a Python 3 Interpreter were found.
- BoostPrettyPrinters_GDB_FOUND
-
True if GDB executable was found.
- BoostPrettyPrinters_GDB_EXECUTABLE
-
The GDB executable to use.
boost_pretty_printers_embed_gdb_extension(
TARGET target
INPUT input
OUTPUT output
[EXCLUDE_FROM_ALL]
[FLAGS flags...])
Defines a custom target target
that creates a C file output
from a Python
script input
by running embed-gdb-extension.py.
If EXCLUDE_FROM_ALL
is set the target will not be added to the default build
target.
FLAGS
are addtional flags passed to embed-gdb-extension.py, e.g.
--header-guard=
or --disable-macro=
.
boost_pretty_printers_test_gdb_printers(
TEST test
[PROGRAM program]
SOURCES [srcs...]
[EXCLUDE_FROM_ALL])
-
Defines a custom target that creates a Python program from
srcs
by running generate-gdb-test-runner.py. -
Defines executable target
program
with the providedsrcs
. -
Defines a test
test
that uses GDB as a Python interpreter for script from step 1 to debug the program from step 2.
If PROGRAM
is not set then the executable target’s name is assumed to be the
same as test
.
If EXCLUDE_FROM_ALL
is set then both the executable target and the custom
target will not be added to the default build target.
using boost-pretty-printers : [path/to/gdb] ;
rule embed-gdb-extension ( target : sources + : requirements * : usage-requirements * )
Main target rule that creates a C file from a Python script by running embed-gdb-extension.py.
Usually, you would use <location>
feature to create the file in the headers
directory. Use the <flags>
feature to pass additional flags to
embed-gdb-extension.py
, for example
<flags>--header-guard=MYPROJECT_GDB_PRINTERS_HPP
.
rule test-gdb-printers ( target : sources + : requirements * : default-build * : usage-requirements * )
Main target rule that
-
creates a Python program sources by running generate-gdb-test-runner.py;
-
compiles and links the sources into a program;
-
runs GDB as a Python interpreter for script from step 1 to debug the program from step 2.
embed-gdb-extension.py input [output] [--header-guard HEADER_GUARD] [--disable-macro DISABLE_MACRO]
Creates a C file that pushes contents of a GDB Python extension file into .debug_gdb_scripts ELF section.
Positional arguments:
- input
-
Input file; must be written in Python.
- output
-
Output file; if not provided, the result is printed to standard output.
Options:
- --header-guard
-
Header guard macro to use; if not provided, the value is deduced from the output file name; to remove the header guard macro use empty value (
--header-guard=
). - --disable-macro
-
Macro to disable pretty printer embedding; by default
BOOST_ALL_NO_EMBEDDED_GDB_SCRIPTS
; to remove the disable macro use empty value (--disable-macro=
).
generate-gdb-test-runner.py input [output]
Creates a Python script from C++ source files to control a GDB test of those source files.
int n = 1;
// TEST_EXPR( 'n', '1' )
The resulting script commands GDB to set a breakpoint on each line with a
special comment. Then the script will test that printing the expression in the
first argument of TEST_EXPR
(e.g. print n
) produces the output equal to the
second argument of TEST_EXPR
(e.g. 1
). Note that the breakpoint is set
effectively on the next statement. Also note that multiline comments are not
supported.
In some cases you need to know some run-time values to know the expected
output. In that case you can provide extra arguments to TEST_EXPR
. Those will
be in turn printed by GDB, and their output will be substituted into the second
argument of TEST_EXPR
using Python’s str.format
:
unsigned char buf[1024];
monotonic_resource mr(buf);
// TEST_EXPR( 'mr', 'monotonic_resource[buffer={0}]', '/a &buf' )
(The option /a
tells print
to output just the address, without type
information).
Positional arguments:
- input
-
Input files.
- output
-
Output file; if not provided, the result is printed to the standard output.