Backward-cpp [![Conan Center](https://img.shields.io/conan/v/backward-cpp)](https://conan.io/center/recipes/backward-cpp)
============
Backward is a beautiful stack trace pretty printer for C++.
If you are bored to see this:
![default trace](doc/rude.png)
Backward will spice it up for you:
![pretty stackstrace](doc/pretty.png)
There is not much to say. Of course it will be able to display the code
snippets only if the source files are accessible (else see trace #4 in the
example).
All "Source" lines and code snippet prefixed by a pipe "|" are frames inline
the next frame.
You can see that for the trace #1 in the example, the function
`you_shall_not_pass()` was inlined in the function `...read2::do_test()` by the
compiler.
## Installation
#### Install backward.hpp
Backward is a header only library. So installing Backward is easy, simply drop
a copy of `backward.hpp` along with your other source files in your C++ project.
You can also use a git submodule or really any other way that best fits your
environment, as long as you can include `backward.hpp`.
#### Install backward.cpp
If you want Backward to automatically print a stack trace on most common fatal
errors (segfault, abort, un-handled exception...), simply add a copy of
`backward.cpp` to your project, and don't forget to tell your build system.
The code in `backward.cpp` is trivial anyway, you can simply copy what it's
doing at your convenience.
Note for [folly](https://github.com/facebook/folly) library users: must define `backward::SignalHandling sh;` after `folly::init(&argc, &argv);`.
## Configuration & Dependencies
### Integration with CMake
If you are using CMake and want to use its configuration abilities to save you
the trouble, you can easily integrate Backward, depending on how you obtained
the library.
Notice that all approaches are equivalent in the way Backward is added to a
CMake target, the difference is in how CMake is pointed to the Backward
sources. Backward defines three targets:
- `Backward::Interface` is an interface target that brings compiler definition
flags, include directory, and external libraries. This is all you need to use
the `backward.hpp` header library.
- `Backward::Object` brings `Backward::Interface` and `backward.cpp` as an
`OBJECT` CMake library. This target cannot be exported, so it is not
available when Backward is used via `find_package`.
- `Backward::Backward` brings `Backward::Interface` and `backward.cpp` as
either `STATIC` or `SHARED` library (depending on the `BACKWARD_SHARED`
option). This target is exported and always available, however note that the
linker will not include unused objects from a static library, unless the
`-Wl,--whole-archive` option (or similar) is used.
#### With `FetchContent()`:
If you are using a recent version of CMake, you can integrate `backward` via `FetchContent` like below:
```cmake
include(FetchContent)
# Also requires one of: libbfd (gnu binutils), libdwarf, libdw (elfutils)
FetchContent_Declare(backward
GIT_REPOSITORY https://github.com/bombela/backward-cpp
GIT_TAG master # or a version tag, such as v1.6
SYSTEM # optional, the Backward include directory will be treated as system directory
)
FetchContent_MakeAvailable(backward)
# Add Backward to your target (either Backward::Interface, Backward::Object, or Backward::Backward)
target_link_libraries(mytarget PUBLIC Backward::Interface)
```
#### As a subdirectory:
In this case you have a subdirectory containing the whole repository of Backward
(e.g. using [git-submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules)),
in this case you can do:
```cmake
add_subdirectory(/path/to/backward-cpp)
# Add Backward to your target (either Backward::Interface, Backward::Object, or Backward::Backward)
target_link_libraries(mytarget PUBLIC Backward::Interface)
```
#### Modifying `CMAKE_MODULE_PATH`:
In this case you can have Backward installed as a subdirectory:
```
list(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp)
find_package(Backward)
# Add Backward to your target (either Backward::Interface or Backward::Backward)
target_link_libraries(mytarget PUBLIC Backward::Interface)
```
#### Installation through a regular package manager
In this case you have obtained Backward through a package manager.
Packages currently available:
- [conda-forge](https://anaconda.org/conda-forge/backward-cpp)
```
find_package(Backward)
# Add Backward to your target (either Backward::Interface or Backward::Backward)
target_link_libraries(mytarget PUBLIC Backward::Interface)
```
### Libraries to unwind the stack
On Linux and macOS, backtrace can back-trace or "walk" the stack using the
following libraries:
#### unwind
Unwind comes from libgcc, but there is an equivalent inside clang itself. With
unwind, the stacktrace is as accurate as it can possibly be, since this is
used by the C++ runtine in gcc/clang for stack unwinding on exception.
Normally libgcc is already linked to your program by default.
#### libunwind from the [libunwind project](https://github.com/libunwind/libunwind)
apt-get install binutils-dev (or equivalent)
Libunwind provides, in some cases, a more accurate stacktrace as it knows
to decode signal handler frames and lets us edit the context registers when
unwinding, allowing stack traces over bad function references.
For best results make sure you are using libunwind 1.3 or later, which added
`unw_init_local2` and support for handling signal frames.
CMake will warn you when configuring if your libunwind version doesn't support
signal frames.
On macOS clang provides a libunwind API compatible library as part of its
environment, so no third party libraries are necessary.
### Compile with debug info
You need to compile your project with generation of debug symbols enabled,
usually `-g` with clang++ and g++.
Note that you can use `-g` with any level of optimization, with modern debug
information encoding like DWARF, it only takes space in the binary (it's not
loaded in memory until your debugger or Backward makes use of it, don't worry),
and it doesn't impact the code generation (at least on GNU/Linux x86\_64 for
what I know).
If you are missing debug information, the stack trace will lack details about
your sources.
### Libraries to read the debug info
Backward supports pretty printed stack traces on GNU/Linux, macOS and Windows,
it will compile fine under other platforms but will not do anything. **Pull
requests are welcome :)**
Also, by default you will get a really basic stack trace, based on the
`backtrace_symbols` API:
![default trace](doc/nice.png)
You will need to install some dependencies to get the ultimate stack trace.
Three libraries are currently supported, the only difference is which one is the
easiest for you to install, so pick your poison:
#### libbfd from the [GNU/binutils](http://www.gnu.org/software/binutils/)
apt-get install binutils-dev (or equivalent)
And do not forget to link with the lib: `g++/clang++ -lbfd -ldl ...`
This library requires dynamic loading. Which is provided by the library `dl`.
Hence why we also link with `-ldl`.
Then define the following before every inclusion of `backward.hpp` (don't
forget to update `backward.cpp` as well):
#define BACKWARD_HAS_BFD 1
#### libdw from the [elfutils](https://fedorahosted.org/elfutils/)
apt-get install libdw-dev (or equivalent)
And do not forget to link with the lib and inform Backward to use it:
#define BACKWARD_HAS_DW 1
Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the
linkage details in your build system and even auto-detect which library is
installed, it's up to you.
#### [libdwarf](https://sourceforge.net/projects/libdwarf/) and [libelf](http://www.mr511.de/software/english.html)
apt-get install libdwarf-dev (or equivalent)
And do not forget to link with the lib and inform Backward to use it:
#define BACKWARD_HAS_DWARF 1
There are several alternative implementations of