Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sintef/fortran-stacktrace

Generate stacktraces from Fortran
https://github.com/sintef/fortran-stacktrace

error-handling fortran stacktrace

Last synced: about 2 months ago
JSON representation

Generate stacktraces from Fortran

Awesome Lists containing this project

README

        

= Fortran Stacktrace
:imagesdir: doc/

:repo: SINTEF/fortran-stacktrace
**Generate stacktraces in Fortran**

image:https://github.com/{repo}/actions/workflows/built-test.yml/badge.svg[link="https://github.com/{repo}/actions/workflows/built-test.yml"]
image:https://img.shields.io/github/v/release/{repo}?label=version&sort=semver[link="https://github.com/{repo}/releases"]

This library enables generation of stacktraces for Fortran.
It does so by providing a Fortran wrapper around the C++ library
https://github.com/bombela/backward-cpp[backward-cpp].

It also integrates with the Fortran
https://github.com/SINTEF/fortran-error-handling[error-handling] library in order
to generate errors that includes a stacktrace.
This means that you can easily make even old legacy code output errors messages like this:

image::stacktrace-example.png[]

The source code snippets are of course voluntary and only available on a machine
with access to the source code itself.

== Building

A fairly recent Fortran and C++ compiler is required to build this library.
The following compilers are known to work:

- gfortran version 9 or later
- Intel Fortran 2021 or later

NOTE: Stacktraces are currently not enabled for gcc/gfortran when using MinGW
on Windows.
It seems like backward-cpp should support this, but I haven't figured out how to get it
working. Pull requests are welcome if anyone wants to have a look at this!

In order to get proper stacktraces you also need to *compile your source code with
debug information*. To do this use the following compiler flags
|===
| Compiler Vendor | Operating System | Compiler flag | Link flag
| GCC | Linux | `-g` |
| Intel | Linux | `-g` |
| Intel | Windows | `-Z7` | `-debug`
|===

This will increase the binary size slightly, but contrary to popular belief it should
*not* impact performance of your code!

On Linux, you also need to install binutils-dev which contains libbfd:
[source,bash]
----
apt-get install binutils-dev # or the equivalent for your distro
----

For more information see also the https://github.com/bombela/backward-cpp[backward-cpp]
documentation.

=== CMake

First, enable both Fortran and CXX as languages in your project:

[source,cmake]
----
project( LANGUAGES Fortran CXX)
----

Or:

[source,cmake]
----
enable_language("Fortran")
enable_language("CXX")
----

To use the recommended compiler and link flags you can for example do the following:

[source,cmake]
----
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
set(CMAKE_Fortran_FLAGS "-g")
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "-debug")
endif(WIN32)
elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
if(WIN32)
set(CMAKE_Fortran_FLAGS "-Z7")
set(CMAKE_EXE_LINKER_FLAGS "-debug")
else(WIN32)
set(CMAKE_Fortran_FLAGS "-g")
endif(WIN32)
endif()
----

This example is not complete, but can be used as a starting point.
Add other compiler flags depending on your project needs.

The recommended way of getting the source code for this library when using CMake
is to add it as a dependency using
https://github.com/cpm-cmake/CPM.cmake/[CMake Package Manager (CPM)]:

[source,cmake]
----
CPMAddPackage("https://github.com/SINTEF/[email protected]")
target_link_libraries( stacktrace)
----

=== CMake Without CPM

If you don't want to use CPM you can either use
https://cmake.org/cmake/help/latest/module/FetchContent.html[FetchContent]
manually or add this repo as a git submodule to your project. Then in your
`CMakeLists.txt` add it as a subdirectory and use `target_link_libraries` to
link against `stacktrace`.

Do however note that this library will still use CPM to add
https://github.com/SINTEF/fortran-error-handling[fortran-error-handling]
as its dependency.

=== Fortran Package Manager (FPM)

FPM is currently not supported as it is not yet able to compile C++ sources.

== Usage

WARNING: The procedures for loading and displaying a stacktrace is declared as pure
however they do invoke C++ code which by definition cannot be pure.
This is possible because the c-bindings are declared pure which is done by
hand.
The procedures does not have any side effects, which is the intent for
of pure procedures in Fortran.
If you are not comfortable with this way of stretching the definition of
`pure`, don't use `stacktrace_t` in pure procedures!

WARNING: As of this writing, the latest gfortran versions has bugs related to
user defined finalization of derived types. In order to avoid crashes
like segmentation faults due to this, finalization is currently disabled
when gfortran is used. As a result there will be a memory leak if a
loaded `stacktrace_t` is deallocated or goes out of scope.

=== Error Handling Integration

It is possible to make errors created with the
https://github.com/SINTEF/fortran-error-handling[fortran-error-handling]
library contain a stacktrace.
To do this, add the following code near the top of your program,
preferably before any errors may occur:

[source, Fortran]
----
program main
use error_handling, only: set_error_hook
use stacktrace_mod, only: stacktrace_error_hook_t
implicit none

call set_error_hook(stacktrace_error_hook_t())

! (...)
end program
----

For a complete example, see link:example/error-handling-integration.f90[`error-handling-integration.f90`].

=== Generating Stacktraces

To generate a stacktrace from an arbitrary code location, do the following:

[source,fortran]
----
use stacktrace_mod, only: stacktrace_t

type(stacktrace_t) :: st
character(len=:), allocatable :: chars

! Load a stacktrace from this point
call st%load_here()

! Convert the stacktrace into character, e.g. for writing to a log file.
! `snippet=.false.` disables snippet generation even when sources are available
chars = st%to_chars(snippet=.false.)
write(*,'(a)') chars
----

== Contributions

Feel free to submit Feedback, suggestions or any problems in the issue tracker.

== License and Copyright

Copyright 2022 SINTEF Ocean AS. All Rights Reserved. MIT License.

https://github.com/bombela/backward-cpp[backward-cpp] is redistributed by this project.
Copyright 2013-2017 Google Inc. All Rights Reserved. MIT License.