diff --git a/build-support/custom-modules/ns3-compiler-workarounds.cmake b/build-support/custom-modules/ns3-compiler-workarounds.cmake index 73cb77a2f..f91fc389a 100644 --- a/build-support/custom-modules/ns3-compiler-workarounds.cmake +++ b/build-support/custom-modules/ns3-compiler-workarounds.cmake @@ -3,3 +3,58 @@ # SPDX-License-Identifier: GPL-2.0-only # # Author: Gabriel Ferreira + +include(CheckCXXSourceCompiles) + +# Some compilers (e.g. GCC <= 15) do not link std::stacktrace by default. If the +# sample program can be linked, it means it is indeed linked by default. +# Otherwise, we link it manually. +# https://en.cppreference.com/w/cpp/header/stacktrace +set(CMAKE_REQUIRED_FLAGS -std=c++23) +check_cxx_source_compiles( + " + #if __has_include() + int main() + { + return 0; + } + #endif + " + STACKTRACE_LIBRARY_ENABLED +) +if(STACKTRACE_LIBRARY_ENABLED) + set(stacktrace_flags) + if(GCC) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0.0") + # GCC does not support stacktracing + elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0.0") + set(stacktrace_flags -lstdc++_libbacktrace) + else() + set(stacktrace_flags -lstdc++exp) + endif() + elseif(CLANG) + set(stacktrace_flags -lstdc++_libbacktrace) + else() + # Most likely MSVC, which does not need custom flags for this + endif() + set(CMAKE_REQUIRED_LIBRARIES ${stacktrace_flags}) + string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + check_cxx_source_compiles( + " + #include + #include + + int main() + { + std::cout << std::stacktrace::current() << std::endl; + return 0; + } + " + STACKTRACE_LIBRARY_IS_LINKED + ) + + if(STACKTRACE_LIBRARY_IS_LINKED) + add_definitions(-DSTACKTRACE_LIBRARY_IS_LINKED=1) + link_libraries(${stacktrace_flags}) + endif() +endif() diff --git a/src/core/model/fatal-error.h b/src/core/model/fatal-error.h index 626898b06..c8fe41e66 100644 --- a/src/core/model/fatal-error.h +++ b/src/core/model/fatal-error.h @@ -17,6 +17,23 @@ #include #include +// If stacktrace is available, print it on fatal errors +#ifdef STACKTRACE_LIBRARY_IS_LINKED +#include +/** + * @brief Macro prints the current stack trace to standard error. + * + * This macro is defined only if the stacktrace library is linked. + */ + +#define PRINT_STACKTRACE std::cerr << std::stacktrace::current() << std::endl +#else +/** + * @brief Macro does nothing if stacktrace library is not available. + */ +#define PRINT_STACKTRACE +#endif + /** * @file * @ingroup fatal @@ -84,6 +101,7 @@ constexpr std::string_view NS_FATAL_MSG{"NS_FATAL, terminating"}; if (fatal) \ { \ std::cerr << ns3::NS_FATAL_MSG << std::endl; \ + PRINT_STACKTRACE; \ std::terminate(); \ } \ } while (false)