CMake improvements (#57)
This commit is contained in:
parent
e14eac364f
commit
98368fb417
335
CMakeLists.txt
335
CMakeLists.txt
@ -1,15 +1,24 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
endif()
|
||||
include(cmake/PreventInSourceBuilds.cmake)
|
||||
|
||||
# ---- Initialize Project ----
|
||||
|
||||
# Used to support find_package
|
||||
set(package_name "cpptrace")
|
||||
|
||||
project(
|
||||
cpptrace
|
||||
VERSION 0.2.1
|
||||
DESCRIPTION "Simple, portable, and self-contained stacktrace library for C++11 and newer "
|
||||
HOMEPAGE_URL "https://github.com/jeremy-rifkin/cpptrace"
|
||||
LANGUAGES C CXX
|
||||
)
|
||||
|
||||
# Don't change include order, OptionVariables checks if project is top level
|
||||
include(cmake/ProjectIsTopLevel.cmake)
|
||||
include(cmake/OptionVariables.cmake)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckCXXCompilerFlag)
|
||||
@ -22,47 +31,6 @@ if(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CPPTRACE_STATIC "" OFF)
|
||||
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_LIBDL "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_NOTHING "" OFF)
|
||||
|
||||
option(CPPTRACE_UNWIND_WITH_UNWIND "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_EXECINFO "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_WINAPI "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_DBGHELP "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_NOTHING "" OFF)
|
||||
|
||||
option(CPPTRACE_DEMANGLE_WITH_CXXABI "" OFF)
|
||||
option(CPPTRACE_DEMANGLE_WITH_WINAPI "" OFF)
|
||||
option(CPPTRACE_DEMANGLE_WITH_NOTHING "" OFF)
|
||||
|
||||
set(CPPTRACE_BACKTRACE_PATH "" CACHE STRING "Path to backtrace.h, if the compiler doesn't already know it. Check /usr/lib/gcc/x86_64-linux-gnu/*/include.")
|
||||
set(CPPTRACE_HARD_MAX_FRAMES "" CACHE STRING "Hard limit on unwinding depth. Default is 100.")
|
||||
set(CPPTRACE_ADDR2LINE_PATH "" CACHE STRING "Absolute path to the addr2line executable you want to use.")
|
||||
option(CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH "" OFF)
|
||||
|
||||
option(CPPTRACE_BUILD_TEST "" OFF)
|
||||
option(CPPTRACE_BUILD_DEMO "" OFF)
|
||||
option(CPPTRACE_BUILD_TEST_RDYNAMIC "" OFF)
|
||||
|
||||
option(CPPTRACE_USE_SYSTEM_LIBDWARF "" OFF)
|
||||
option(CPPTRACE_SANITIZER_BUILD "" OFF)
|
||||
|
||||
mark_as_advanced(
|
||||
CPPTRACE_BACKTRACE_PATH
|
||||
CPPTRACE_ADDR2LINE_PATH
|
||||
CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH
|
||||
CPPTRACE_BUILD_TEST
|
||||
CPPTRACE_BUILD_DEMO
|
||||
CPPTRACE_BUILD_TEST_RDYNAMIC
|
||||
CPPTRACE_SANITIZER_BUILD
|
||||
)
|
||||
|
||||
if(CPPTRACE_SANITIZER_BUILD)
|
||||
add_compile_options(-fsanitize=address)
|
||||
add_link_options(-fsanitize=address)
|
||||
@ -82,6 +50,7 @@ else()
|
||||
set(CPPTRACE_BACKTRACE_PATH_DEFINITION "")
|
||||
endif()
|
||||
|
||||
# =============================================== Platform Support ===============================================
|
||||
function(check_support var source includes libraries definitions)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${includes}")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
@ -195,93 +164,126 @@ endif()
|
||||
|
||||
# =============================================== Now define the library ===============================================
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
# Target that we can modify (can't modify ALIAS targets)
|
||||
# Target name should not be the same as ${PROJECT_NAME}, causes add_subdirectory issues
|
||||
set(target_name "cpptrace-lib")
|
||||
add_library(${target_name} ${build_type})
|
||||
|
||||
set(
|
||||
sources
|
||||
src/cpptrace.cpp
|
||||
src/demangle/demangle_with_cxxabi.cpp
|
||||
src/demangle/demangle_with_winapi.cpp
|
||||
src/demangle/demangle_with_nothing.cpp
|
||||
src/symbols/symbols_with_addr2line.cpp
|
||||
src/symbols/symbols_with_dbghelp.cpp
|
||||
src/symbols/symbols_with_dl.cpp
|
||||
src/symbols/symbols_with_libbacktrace.cpp
|
||||
src/symbols/symbols_with_libdwarf.cpp
|
||||
src/symbols/symbols_with_nothing.cpp
|
||||
src/symbols/symbols_core.cpp
|
||||
src/unwind/unwind_with_execinfo.cpp
|
||||
src/unwind/unwind_with_nothing.cpp
|
||||
src/unwind/unwind_with_unwind.cpp
|
||||
src/unwind/unwind_with_winapi.cpp
|
||||
src/unwind/unwind_with_dbghelp.cpp
|
||||
# Alias to cause error at configuration time instead of link time if target is missing
|
||||
add_library(cpptrace::cpptrace ALIAS ${target_name})
|
||||
|
||||
# Add /include files to target
|
||||
# This is solely for IDE benefit, doesn't affect building
|
||||
target_sources(
|
||||
${target_name} PRIVATE
|
||||
include/cpptrace/cpptrace.hpp
|
||||
)
|
||||
|
||||
if(CPPTRACE_STATIC)
|
||||
add_library(cpptrace STATIC ${sources} include/cpptrace/cpptrace.hpp)
|
||||
else()
|
||||
add_library(cpptrace SHARED ${sources} include/cpptrace/cpptrace.hpp)
|
||||
set_property(TARGET cpptrace PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
# add /src files to target
|
||||
target_sources(
|
||||
${target_name} PRIVATE
|
||||
# src
|
||||
src/cpptrace.cpp
|
||||
src/demangle/demangle_with_cxxabi.cpp
|
||||
src/demangle/demangle_with_winapi.cpp
|
||||
src/demangle/demangle_with_nothing.cpp
|
||||
src/symbols/symbols_with_addr2line.cpp
|
||||
src/symbols/symbols_with_dbghelp.cpp
|
||||
src/symbols/symbols_with_dl.cpp
|
||||
src/symbols/symbols_with_libbacktrace.cpp
|
||||
src/symbols/symbols_with_libdwarf.cpp
|
||||
src/symbols/symbols_with_nothing.cpp
|
||||
src/symbols/symbols_core.cpp
|
||||
src/unwind/unwind_with_execinfo.cpp
|
||||
src/unwind/unwind_with_nothing.cpp
|
||||
src/unwind/unwind_with_unwind.cpp
|
||||
src/unwind/unwind_with_winapi.cpp
|
||||
src/unwind/unwind_with_dbghelp.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
cpptrace
|
||||
${target_name}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpptrace/>
|
||||
)
|
||||
|
||||
# TODO
|
||||
target_compile_features(cpptrace PRIVATE cxx_range_for cxx_constexpr cxx_nullptr cxx_static_assert)
|
||||
# ---- Generate Build Info Headers ----
|
||||
|
||||
set_target_properties(
|
||||
cpptrace
|
||||
PROPERTIES
|
||||
CXX_STANDARD_REQUIRED TRUE
|
||||
CXX_EXTENSIONS OFF
|
||||
# used in export header generated below
|
||||
if(NOT CPPTRACE_BUILD_SHARED)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_STATIC_DEFINE)
|
||||
endif()
|
||||
|
||||
# generate header file with export macros prefixed with BASE_NAME
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(
|
||||
${target_name}
|
||||
BASE_NAME cpptrace
|
||||
EXPORT_FILE_NAME include/cpptrace/cpptrace_export.hpp
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
cpptrace
|
||||
PRIVATE
|
||||
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Werror=return-type -Wundef>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wuseless-cast>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX /permissive->
|
||||
# ---- Library Properties ----
|
||||
|
||||
# Hide all symbols by default
|
||||
# Use SameMajorVersion versioning for shared library runtime linker lookup
|
||||
set_target_properties(
|
||||
${target_name} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
VISIBILITY_INLINES_HIDDEN YES
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}"
|
||||
EXPORT_NAME "cpptrace"
|
||||
OUTPUT_NAME "cpptrace"
|
||||
)
|
||||
|
||||
# Header files generated by CMake
|
||||
target_include_directories(
|
||||
${target_name} SYSTEM PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
|
||||
)
|
||||
|
||||
# Header files from /include
|
||||
target_include_directories(
|
||||
${target_name} ${warning_guard} PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
)
|
||||
|
||||
# Require C++11 support
|
||||
target_compile_features(
|
||||
${target_name}
|
||||
PRIVATE cxx_std_11
|
||||
)
|
||||
|
||||
# =============================================== Apply options to build ===============================================
|
||||
|
||||
if(HAS_CXX_EXCEPTION_TYPE)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_HAS_CXX_EXCEPTION_TYPE)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_HAS_CXX_EXCEPTION_TYPE)
|
||||
endif()
|
||||
|
||||
function(check_backtrace_error)
|
||||
if(NOT HAS_BACKTRACE)
|
||||
if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "")
|
||||
message(WARNING "Cpptrace: CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE specified but libbacktrace doesn't appear installed or configured properly.")
|
||||
else()
|
||||
message(WARNING "Cpptrace: CPPTRACE_FULL_TRACE_WITH_LIBBACKTRACE specified but libbacktrace doesn't appear installed or configured properly. You may need to specify CPPTRACE_BACKTRACE_PATH.")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Symbols
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
|
||||
check_backtrace_error()
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
|
||||
target_link_libraries(cpptrace PRIVATE backtrace)
|
||||
if(NOT HAS_BACKTRACE)
|
||||
if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "")
|
||||
message(WARNING "Cpptrace: Using libbacktrace for symbols but libbacktrace doesn't appear installed or configured properly.")
|
||||
else()
|
||||
message(WARNING "Cpptrace: Using libbacktrace for symbols but libbacktrace doesn't appear installed or configured properly. You may need to specify CPPTRACE_BACKTRACE_PATH.")
|
||||
endif()
|
||||
endif()
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE)
|
||||
target_link_libraries(${target_name} PRIVATE backtrace dl)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_LIBDL)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBDL)
|
||||
target_link_libraries(cpptrace PRIVATE dl)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBDL)
|
||||
target_link_libraries(${target_name} PRIVATE dl)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
||||
# set(CPPTRACE_ADDR2LINE_PATH "" CACHE STRING "Absolute path to the addr2line executable you want to use.")
|
||||
# option(CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH "" OFF)
|
||||
if(CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH)
|
||||
else()
|
||||
if("${CPPTRACE_ADDR2LINE_PATH}" STREQUAL "")
|
||||
if(APPLE)
|
||||
@ -293,35 +295,46 @@ if(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
||||
set(CPPTRACE_ADDR2LINE_PATH_FINAL "${CPPTRACE_ADDR2LINE_PATH}")
|
||||
endif()
|
||||
message(STATUS "Cpptrace: Using ${CPPTRACE_ADDR2LINE_PATH_FINAL} for addr2line path")
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_ADDR2LINE_PATH="${CPPTRACE_ADDR2LINE_PATH_FINAL}")
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_ADDR2LINE_PATH="${CPPTRACE_ADDR2LINE_PATH_FINAL}")
|
||||
endif()
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
||||
if(UNIX)
|
||||
target_link_libraries(cpptrace PRIVATE dl)
|
||||
target_link_libraries(${target_name} PRIVATE dl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF)
|
||||
if(CPPTRACE_USE_SYSTEM_LIBDWARF)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF)
|
||||
if(CPPTRACE_USE_EXTERNAL_LIBDWARF)
|
||||
find_package(libdwarf REQUIRED)
|
||||
target_link_libraries(cpptrace PRIVATE libdwarf)
|
||||
target_link_libraries(${target_name} PRIVATE libdwarf::dwarf-static)
|
||||
else()
|
||||
add_subdirectory(bundled/libdwarf)
|
||||
target_link_libraries(cpptrace PRIVATE dwarf)
|
||||
target_link_libraries(${target_name} PRIVATE dwarf)
|
||||
# set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
# set(PIC_ALWAYS TRUE)
|
||||
# set(BUILD_DWARFDUMP FALSE)
|
||||
# include(FetchContent)
|
||||
# FetchContent_Declare(
|
||||
# libdwarf
|
||||
# GIT_REPOSITORY https://github.com/jeremy-rifkin/libdwarf-code.git
|
||||
# GIT_TAG 4ca6a7bc86b27d56741923f03c15b5aa274efc28 # v0.8.0
|
||||
# )
|
||||
# FetchContent_MakeAvailable(libdwarf)
|
||||
# target_link_libraries(${target_name} PRIVATE dwarf-static)
|
||||
endif()
|
||||
if(UNIX)
|
||||
target_link_libraries(cpptrace PRIVATE dl)
|
||||
target_link_libraries(${target_name} PRIVATE dl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
|
||||
target_link_libraries(cpptrace PRIVATE dbghelp)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
|
||||
target_link_libraries(${target_name} PRIVATE dbghelp)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_NOTHING)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_GET_SYMBOLS_WITH_NOTHING)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_GET_SYMBOLS_WITH_NOTHING)
|
||||
endif()
|
||||
|
||||
# Unwinding
|
||||
@ -329,30 +342,30 @@ if(CPPTRACE_UNWIND_WITH_UNWIND)
|
||||
if(NOT HAS_UNWIND)
|
||||
message(WARNING "Cpptrace: CPPTRACE_UNWIND_WITH_UNWIND specified but libgcc unwind doesn't seem to be available.")
|
||||
endif()
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_UNWIND_WITH_UNWIND)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_UNWIND_WITH_UNWIND)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_UNWIND_WITH_EXECINFO)
|
||||
if(NOT HAS_EXECINFO)
|
||||
message(WARNING "Cpptrace: CPPTRACE_UNWIND_WITH_EXECINFO specified but execinfo.h doesn't seem to be available.")
|
||||
endif()
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_UNWIND_WITH_EXECINFO)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_UNWIND_WITH_EXECINFO)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_UNWIND_WITH_WINAPI)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_UNWIND_WITH_WINAPI)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_UNWIND_WITH_WINAPI)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_UNWIND_WITH_DBGHELP)
|
||||
if(NOT HAS_STACKWALK)
|
||||
message(WARNING "Cpptrace: CPPTRACE_UNWIND_WITH_DBGHELP specified but dbghelp stackwalk64 doesn't seem to be available.")
|
||||
endif()
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_UNWIND_WITH_DBGHELP)
|
||||
target_link_libraries(cpptrace PRIVATE dbghelp)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_UNWIND_WITH_DBGHELP)
|
||||
target_link_libraries(${target_name} PRIVATE dbghelp)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_UNWIND_WITH_NOTHING)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_UNWIND_WITH_NOTHING)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_UNWIND_WITH_NOTHING)
|
||||
endif()
|
||||
|
||||
# Demangling
|
||||
@ -360,100 +373,38 @@ if(CPPTRACE_DEMANGLE_WITH_CXXABI)
|
||||
if(NOT HAS_CXXABI)
|
||||
message(WARNING "Cpptrace: CPPTRACE_DEMANGLE_WITH_CXXABI specified but cxxabi.h doesn't seem to be available.")
|
||||
endif()
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_DEMANGLE_WITH_CXXABI)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_DEMANGLE_WITH_CXXABI)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_DEMANGLE_WITH_WINAPI)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_DEMANGLE_WITH_WINAPI)
|
||||
target_link_libraries(cpptrace PRIVATE dbghelp)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_DEMANGLE_WITH_WINAPI)
|
||||
target_link_libraries(${target_name} PRIVATE dbghelp)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_DEMANGLE_WITH_NOTHING)
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_DEMANGLE_WITH_NOTHING)
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_DEMANGLE_WITH_NOTHING)
|
||||
endif()
|
||||
|
||||
if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "")
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_BACKTRACE_PATH=${CPPTRACE_BACKTRACE_PATH})
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_BACKTRACE_PATH=${CPPTRACE_BACKTRACE_PATH})
|
||||
endif()
|
||||
|
||||
if(NOT "${CPPTRACE_HARD_MAX_FRAMES}" STREQUAL "")
|
||||
target_compile_definitions(cpptrace PUBLIC CPPTRACE_HARD_MAX_FRAMES=${CPPTRACE_HARD_MAX_FRAMES})
|
||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_HARD_MAX_FRAMES=${CPPTRACE_HARD_MAX_FRAMES})
|
||||
endif()
|
||||
|
||||
# ======================================================================================================================
|
||||
# =============================================== Install ===============================================
|
||||
|
||||
if(NOT CMAKE_SKIP_INSTALL_RULES)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
if(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF)
|
||||
set(CPPTRACE_STATIC_EXPORT_TARGETS cpptrace dwarf)
|
||||
else()
|
||||
set(CPPTRACE_STATIC_EXPORT_TARGETS cpptrace)
|
||||
endif()
|
||||
|
||||
if(CPPTRACE_STATIC)
|
||||
install(
|
||||
TARGETS ${CPPTRACE_STATIC_EXPORT_TARGETS}
|
||||
EXPORT cpptrace_targets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
else()
|
||||
install(
|
||||
TARGETS cpptrace
|
||||
EXPORT cpptrace_targets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
install(
|
||||
FILES
|
||||
include/cpptrace/cpptrace.hpp
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpptrace
|
||||
)
|
||||
|
||||
export(
|
||||
EXPORT cpptrace_targets
|
||||
FILE ${CMAKE_CURRENT_BINARY_DIR}/cpptrace/cpptrace_targets.cmake
|
||||
NAMESPACE cpptrace::
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
cmake/cpptrace-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cpptrace/cpptrace-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpptrace
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cpptrace/cpptrace-config-version.cmake
|
||||
VERSION ${PACKAGE_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT cpptrace_targets
|
||||
FILE cpptrace_targets.cmake
|
||||
NAMESPACE cpptrace::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpptrace
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cpptrace/cpptrace-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cpptrace/cpptrace-config-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpptrace
|
||||
)
|
||||
include(cmake/InstallRules.cmake)
|
||||
endif()
|
||||
|
||||
# =============================================== Demo/test ===============================================
|
||||
|
||||
if(CPPTRACE_BUILD_TEST)
|
||||
add_executable(test test/test.cpp)
|
||||
target_compile_features(test PRIVATE cxx_range_for cxx_constexpr cxx_nullptr cxx_static_assert)
|
||||
target_link_libraries(test PRIVATE cpptrace)
|
||||
target_link_libraries(test PRIVATE ${target_name})
|
||||
# Clang has been fast to adopt dwarf 5, other tools (e.g. addr2line from binutils) have not
|
||||
check_cxx_compiler_flag("-gdwarf-4" HAS_DWARF4)
|
||||
if(HAS_DWARF4)
|
||||
@ -474,7 +425,7 @@ endif()
|
||||
if(CPPTRACE_BUILD_DEMO)
|
||||
add_executable(demo test/demo.cpp)
|
||||
target_compile_features(demo PRIVATE cxx_range_for cxx_constexpr cxx_nullptr cxx_static_assert)
|
||||
target_link_libraries(demo PRIVATE cpptrace)
|
||||
target_link_libraries(demo PRIVATE ${target_name})
|
||||
# Clang has been fast to adopt dwarf 5, other tools (e.g. addr2line from binutils) have not
|
||||
check_cxx_compiler_flag("-gdwarf-4" HAS_DWARF4)
|
||||
if(HAS_DWARF4)
|
||||
|
||||
11
README.md
11
README.md
@ -585,7 +585,7 @@ configurable with `CPPTRACE_HARD_MAX_FRAMES`.
|
||||
|
||||
| Library | CMake config | Platforms | Info |
|
||||
| ------------ | ---------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| libdwarf | `CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF` | linux, macos, mingw | Libdwarf is the preferred method for symbol resolution for cpptrace, and it's bundled in this repository for ease of use. |
|
||||
| libdwarf | `CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF` | linux, macos, mingw | Libdwarf is the preferred method for symbol resolution for cpptrace. Cpptrace will get it via FetchContent or find_package depending on `CPPTRACE_USE_EXTERNAL_LIBDWARF`. |
|
||||
| dbghelp | `CPPTRACE_GET_SYMBOLS_WITH_DBGHELP` | windows | Dbghelp.h is the preferred method for symbol resolution on windows under msvc/clang and is supported on all windows machines. |
|
||||
| libbacktrace | `CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE` | linux, macos*, mingw* | Libbacktrace is already installed on most systems or available through the compiler directly. For clang you must specify the absolute path to `backtrace.h` using `CPPTRACE_BACKTRACE_PATH`. |
|
||||
| addr2line | `CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE` | linux, macos, mingw | Symbols are resolved by invoking `addr2line` (or `atos` on mac) via `fork()` (on linux/unix, and `popen` under mingw). |
|
||||
@ -634,7 +634,6 @@ Back-ends:
|
||||
- `CPPTRACE_DEMANGLE_WITH_NOTHING=On/Off`
|
||||
|
||||
Back-end configuration:
|
||||
- `CPPTRACE_STATIC=On/Off`: Create cpptrace as a static library.
|
||||
- `CPPTRACE_BACKTRACE_PATH=<string>`: Path to libbacktrace backtrace.h, needed when compiling with clang/
|
||||
- `CPPTRACE_HARD_MAX_FRAMES=<number>`: Some back-ends write to a fixed-size buffer. This is the size of that buffer.
|
||||
Default is `100`.
|
||||
@ -643,7 +642,13 @@ Back-end configuration:
|
||||
injection).
|
||||
- `CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH=On/Off`: Specifies whether cpptrace should let the system search the PATH
|
||||
environment variable directories for the binary.
|
||||
- `CPPTRACE_USE_SYSTEM_LIBDWARF=On/Off`: Use libdwarf resolved via `find_package` rather than the bundled libdwarf.
|
||||
|
||||
Other userufl configurations:
|
||||
- `CPPTRACE_BUILD_SHARED=On/Off`: Override for `BUILD_SHARED_LIBS`.
|
||||
- `CPPTRACE_INCLUDES_WITH_SYSTEM=On/Off`: Marks cpptrace headers as `SYSTEM` which will hide any warnings that aren't
|
||||
the fault of your project. Defaults to On.
|
||||
- `CPPTRACE_INSTALL_CMAKEDIR`: Override for the installation path for the cmake configs.
|
||||
- `CPPTRACE_USE_EXTERNAL_LIBDWARF=On/Off`: Get libdwarf from `find_package` rather than `FetchContent`.
|
||||
|
||||
Testing:
|
||||
- `CPPTRACE_BUILD_TEST` Build a small test program
|
||||
|
||||
94
bundled/libdwarf/CMakeLists.txt
vendored
94
bundled/libdwarf/CMakeLists.txt
vendored
@ -430,11 +430,17 @@ set(
|
||||
libdwarf_private.h
|
||||
)
|
||||
|
||||
set(
|
||||
libdwarf_export_headers
|
||||
dwarf.h
|
||||
libdwarf.h
|
||||
)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_library(dwarf OBJECT ${libdwarf_sources} ${libdwarf_headers})
|
||||
add_library(dwarf STATIC ${libdwarf_sources} ${libdwarf_headers})
|
||||
set_property(TARGET dwarf PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_compile_definitions(dwarf PUBLIC LIBDWARF_BUILD)
|
||||
@ -452,53 +458,53 @@ else()
|
||||
endif()
|
||||
|
||||
# TODO: Something will have to be figured out for dynamic linking, but for now there's nothing to install
|
||||
# if(NOT CMAKE_SKIP_INSTALL_RULES)
|
||||
# include(CMakePackageConfigHelpers)
|
||||
if(NOT CMAKE_SKIP_INSTALL_RULES)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# install(
|
||||
# TARGETS dwarf
|
||||
# EXPORT libdwarf_targets
|
||||
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# )
|
||||
install(
|
||||
TARGETS dwarf
|
||||
EXPORT libdwarf_targets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
# install(
|
||||
# FILES
|
||||
# ${libdwarf_headers}
|
||||
# DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libdwarf
|
||||
# )
|
||||
install(
|
||||
FILES
|
||||
${libdwarf_export_headers}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libdwarf
|
||||
)
|
||||
|
||||
# export(
|
||||
# EXPORT libdwarf_targets
|
||||
# FILE ${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf_targets.cmake
|
||||
# NAMESPACE libdwarf::
|
||||
# )
|
||||
export(
|
||||
EXPORT libdwarf_targets
|
||||
FILE ${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf_targets.cmake
|
||||
NAMESPACE libdwarf::
|
||||
)
|
||||
|
||||
# configure_package_config_file(
|
||||
# cmake/libdwarf-config.cmake.in
|
||||
# ${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config.cmake
|
||||
# INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf
|
||||
# )
|
||||
configure_package_config_file(
|
||||
cmake/libdwarf-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf
|
||||
)
|
||||
|
||||
# write_basic_package_version_file(
|
||||
# ${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config-version.cmake
|
||||
# VERSION "${VERSION}"
|
||||
# COMPATIBILITY SameMajorVersion
|
||||
# )
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config-version.cmake
|
||||
VERSION "${VERSION}"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
# install(
|
||||
# EXPORT libdwarf_targets
|
||||
# FILE libdwarf_targets.cmake
|
||||
# NAMESPACE libdwarf::
|
||||
# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf
|
||||
# )
|
||||
install(
|
||||
EXPORT libdwarf_targets
|
||||
FILE libdwarf_targets.cmake
|
||||
NAMESPACE libdwarf::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf
|
||||
)
|
||||
|
||||
# install(
|
||||
# FILES
|
||||
# ${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config.cmake
|
||||
# ${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config-version.cmake
|
||||
# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf
|
||||
# )
|
||||
# endif()
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libdwarf/libdwarf-config-version.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -15,6 +15,9 @@ failed = False
|
||||
|
||||
expected_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../test/expected/")
|
||||
|
||||
def get_c_compiler_counterpart(compiler: str) -> str:
|
||||
return compiler.replace("clang++", "clang").replace("g++", "gcc")
|
||||
|
||||
MAX_LINE_DIFF = 2
|
||||
|
||||
def similarity(name: str, target: List[str]) -> int:
|
||||
@ -149,6 +152,7 @@ def build(matrix):
|
||||
"..",
|
||||
f"-DCMAKE_BUILD_TYPE={matrix['target']}",
|
||||
f"-DCMAKE_CXX_COMPILER={matrix['compiler']}",
|
||||
f"-DCMAKE_C_COMPILER={get_c_compiler_counterpart(matrix['compiler'])}",
|
||||
f"-DCMAKE_CXX_STANDARD={matrix['std']}",
|
||||
f"-D{matrix['unwind']}=On",
|
||||
f"-D{matrix['symbols']}=On",
|
||||
@ -167,6 +171,7 @@ def build(matrix):
|
||||
"..",
|
||||
f"-DCMAKE_BUILD_TYPE={matrix['target']}",
|
||||
f"-DCMAKE_CXX_COMPILER={matrix['compiler']}",
|
||||
f"-DCMAKE_C_COMPILER={get_c_compiler_counterpart(matrix['compiler'])}",
|
||||
f"-DCMAKE_CXX_STANDARD={matrix['std']}",
|
||||
f"-D{matrix['unwind']}=On",
|
||||
f"-D{matrix['symbols']}=On",
|
||||
@ -190,6 +195,7 @@ def build_full_or_auto(matrix):
|
||||
"..",
|
||||
f"-DCMAKE_BUILD_TYPE={matrix['target']}",
|
||||
f"-DCMAKE_CXX_COMPILER={matrix['compiler']}",
|
||||
f"-DCMAKE_C_COMPILER={get_c_compiler_counterpart(matrix['compiler'])}",
|
||||
f"-DCMAKE_CXX_STANDARD={matrix['std']}",
|
||||
f"-DCPPTRACE_BACKTRACE_PATH=/usr/lib/gcc/x86_64-linux-gnu/10/include/backtrace.h",
|
||||
"-DCPPTRACE_BUILD_TEST=On"
|
||||
@ -205,6 +211,7 @@ def build_full_or_auto(matrix):
|
||||
"..",
|
||||
f"-DCMAKE_BUILD_TYPE={matrix['target']}",
|
||||
f"-DCMAKE_CXX_COMPILER={matrix['compiler']}",
|
||||
f"-DCMAKE_C_COMPILER={get_c_compiler_counterpart(matrix['compiler'])}",
|
||||
f"-DCMAKE_CXX_STANDARD={matrix['std']}",
|
||||
"-DCPPTRACE_BUILD_TEST=On"
|
||||
]
|
||||
@ -309,7 +316,8 @@ def main():
|
||||
#"CPPTRACE_UNWIND_WITH_NOTHING",
|
||||
],
|
||||
"symbols": [
|
||||
"CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE",
|
||||
# Disabled due to libbacktrace bug
|
||||
# "CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE",
|
||||
"CPPTRACE_GET_SYMBOLS_WITH_LIBDL",
|
||||
"CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE",
|
||||
"CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF",
|
||||
|
||||
69
cmake/InstallRules.cmake
Normal file
69
cmake/InstallRules.cmake
Normal file
@ -0,0 +1,69 @@
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
# copy header files to CMAKE_INSTALL_INCLUDEDIR
|
||||
# don't include third party header files
|
||||
install(
|
||||
DIRECTORY
|
||||
"${PROJECT_SOURCE_DIR}/include/" # our header files
|
||||
"${PROJECT_BINARY_DIR}/include/" # generated header files
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT ${package_name}-development
|
||||
# PATTERN "**/third_party" EXCLUDE # skip third party directory
|
||||
# PATTERN "**/third_party/**" EXCLUDE # skip third party files
|
||||
)
|
||||
|
||||
# copy target build output artifacts to OS dependent locations
|
||||
# (Except includes, that just sets a compiler flag with the path)
|
||||
install(
|
||||
TARGETS ${target_name}
|
||||
EXPORT ${package_name}-targets
|
||||
RUNTIME #
|
||||
COMPONENT ${package_name}-runtime
|
||||
LIBRARY #
|
||||
COMPONENT ${package_name}-runtime
|
||||
NAMELINK_COMPONENT ${package_name}-development
|
||||
ARCHIVE #
|
||||
COMPONENT ${package_name}-development
|
||||
INCLUDES #
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
# create config file that points to targets file
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/cmake/in/cpptrace-config-cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/cmake/${package_name}-config.cmake"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# copy config file for find_package to find
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/cmake/${package_name}-config.cmake"
|
||||
DESTINATION "${CPPTRACE_INSTALL_CMAKEDIR}"
|
||||
COMPONENT ${package_name}-development
|
||||
)
|
||||
|
||||
# create version file for consumer to check version in CMake
|
||||
write_basic_package_version_file(
|
||||
"${package_name}-config-version.cmake"
|
||||
COMPATIBILITY SameMajorVersion # a.k.a SemVer
|
||||
)
|
||||
|
||||
# copy version file for find_package to find for version check
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/${package_name}-config-version.cmake"
|
||||
DESTINATION "${CPPTRACE_INSTALL_CMAKEDIR}"
|
||||
COMPONENT ${package_name}-development
|
||||
)
|
||||
|
||||
# create targets file included by config file with targets for consumers
|
||||
install(
|
||||
EXPORT ${package_name}-targets
|
||||
NAMESPACE cpptrace::
|
||||
DESTINATION "${CPPTRACE_INSTALL_CMAKEDIR}"
|
||||
COMPONENT ${package_name}-development
|
||||
)
|
||||
|
||||
# support packaging library
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
include(CPack)
|
||||
endif()
|
||||
170
cmake/OptionVariables.cmake
Normal file
170
cmake/OptionVariables.cmake
Normal file
@ -0,0 +1,170 @@
|
||||
# Included further down to avoid interfering with our cache variables
|
||||
# include(GNUInstallDirs)
|
||||
|
||||
# ---- Options Summary ----
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
# | Option | Availability | Default |
|
||||
# |=================================|===============|===============================================|
|
||||
# | BUILD_SHARED_LIBS | Top-Level | OFF |
|
||||
# | BUILD_TESTING | Top-Level | OFF |
|
||||
# | CMAKE_INSTALL_INCLUDEDIR | Top-Level | include/${package_name}-${PROJECT_VERSION} |
|
||||
# |---------------------------------|---------------|-----------------------------------------------|
|
||||
# | ASSERT_BUILD_SHARED | Always | ${BUILD_SHARED_LIBS} |
|
||||
# | ASSERT_BUILD_TESTING | Always | ${BUILD_TESTING} AND ${PROJECT_IS_TOP_LEVEL} |
|
||||
# | ASSERT_INCLUDES_WITH_SYSTEM | Not Top-Level | ON |
|
||||
# | ASSERT_INSTALL_CMAKEDIR | Always | ${CMAKE_INSTALL_LIBDIR}/cmake/${package_name} |
|
||||
# | CPPTRACE_USE_EXTERNAL_LIBDWARF | Always | OFF |
|
||||
# | ... | | |
|
||||
# ---------------------------------------------------------------------------------------------------
|
||||
|
||||
# ---- Build Shared ----
|
||||
|
||||
# Sometimes it's useful to be able to single out a dependency to be built as
|
||||
# static or shared, even if obtained from source
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
option(BUILD_SHARED_LIBS "Build shared libs" OFF)
|
||||
endif()
|
||||
option(
|
||||
CPPTRACE_BUILD_SHARED
|
||||
"Override BUILD_SHARED_LIBS for ${package_name} library"
|
||||
${BUILD_SHARED_LIBS}
|
||||
)
|
||||
mark_as_advanced(CPPTRACE_BUILD_SHARED)
|
||||
set(build_type STATIC)
|
||||
if(CPPTRACE_BUILD_SHARED)
|
||||
set(build_type SHARED)
|
||||
endif()
|
||||
|
||||
# ---- Warning Guard ----
|
||||
|
||||
# target_include_directories with SYSTEM modifier will request the compiler to
|
||||
# omit warnings from the provided paths, if the compiler supports that.
|
||||
# This is to provide a user experience similar to find_package when
|
||||
# add_subdirectory or FetchContent is used to consume this project.
|
||||
set(warning_guard )
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
option(
|
||||
CPPTRACE_INCLUDES_WITH_SYSTEM
|
||||
"Use SYSTEM modifier for ${package_name}'s includes, disabling warnings"
|
||||
ON
|
||||
)
|
||||
mark_as_advanced(CPPTRACE_INCLUDES_WITH_SYSTEM)
|
||||
if(CPPTRACE_INCLUDES_WITH_SYSTEM)
|
||||
set(warning_guard SYSTEM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ---- Enable Testing ----
|
||||
|
||||
# By default tests aren't enabled even with BUILD_TESTING=ON unless the library
|
||||
# is built as a top level project.
|
||||
# This is in order to cut down on unnecessary compile times, since it's unlikely
|
||||
# for users to want to run the tests of their dependencies.
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
option(BUILD_TESTING "Build tests" OFF)
|
||||
endif()
|
||||
if(PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
|
||||
set(build_testing ON)
|
||||
endif()
|
||||
option(
|
||||
CPPTRACE_BUILD_TESTING
|
||||
"Override BUILD_TESTING for ${package_name} library"
|
||||
${build_testing}
|
||||
)
|
||||
set(build_testing )
|
||||
mark_as_advanced(CPPTRACE_BUILD_TESTING)
|
||||
|
||||
# ---- Install Include Directory ----
|
||||
|
||||
# Adds an extra directory to the include path by default, so that when you link
|
||||
# against the target, you get `<prefix>/include/<package-X.Y.Z>` added to your
|
||||
# include paths rather than `<prefix>/include`.
|
||||
# This doesn't affect include paths used by consumers of this project, but helps
|
||||
# prevent consumers having access to other projects in the same include
|
||||
# directory (e.g. usr/include).
|
||||
# The variable type is STRING rather than PATH, because otherwise passing
|
||||
# -DCMAKE_INSTALL_INCLUDEDIR=include on the command line would expand to an
|
||||
# absolute path with the base being the current CMake directory, leading to
|
||||
# unexpected errors.
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
set(
|
||||
CMAKE_INSTALL_INCLUDEDIR "include/${package_name}-${PROJECT_VERSION}"
|
||||
CACHE STRING ""
|
||||
)
|
||||
# marked as advanced in GNUInstallDirs version, so we follow their lead
|
||||
mark_as_advanced(CMAKE_INSTALL_INCLUDEDIR)
|
||||
endif()
|
||||
|
||||
# do not include earlier or we can't set CMAKE_INSTALL_INCLUDEDIR above
|
||||
# include required for CMAKE_INSTALL_LIBDIR below
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# ---- Install CMake Directory ----
|
||||
|
||||
# This allows package maintainers to freely override the installation path for
|
||||
# the CMake configs.
|
||||
# This doesn't affects include paths used by consumers of this project.
|
||||
# The variable type is STRING rather than PATH, because otherwise passing
|
||||
# -DCPPTRACE_INSTALL_CMAKEDIR=lib/cmake on the command line would expand to an
|
||||
# absolute path with the base being the current CMake directory, leading to
|
||||
# unexpected errors.
|
||||
set(
|
||||
CPPTRACE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${package_name}"
|
||||
CACHE STRING "CMake package config location relative to the install prefix"
|
||||
)
|
||||
# depends on CMAKE_INSTALL_LIBDIR which is marked as advanced in GNUInstallDirs
|
||||
mark_as_advanced(CPPTRACE_INSTALL_CMAKEDIR)
|
||||
|
||||
# ---- Symbol Options ----
|
||||
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_LIBDL "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP "" OFF)
|
||||
option(CPPTRACE_GET_SYMBOLS_WITH_NOTHING "" OFF)
|
||||
|
||||
# ---- Unwinding Options ----
|
||||
|
||||
option(CPPTRACE_UNWIND_WITH_UNWIND "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_EXECINFO "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_WINAPI "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_DBGHELP "" OFF)
|
||||
option(CPPTRACE_UNWIND_WITH_NOTHING "" OFF)
|
||||
|
||||
# ---- Demangling Options ----
|
||||
|
||||
option(CPPTRACE_DEMANGLE_WITH_CXXABI "" OFF)
|
||||
option(CPPTRACE_DEMANGLE_WITH_WINAPI "" OFF)
|
||||
option(CPPTRACE_DEMANGLE_WITH_NOTHING "" OFF)
|
||||
|
||||
# ---- Back-end configurations ----
|
||||
|
||||
set(CPPTRACE_BACKTRACE_PATH "" CACHE STRING "Path to backtrace.h, if the compiler doesn't already know it. Check /usr/lib/gcc/x86_64-linux-gnu/*/include.")
|
||||
set(CPPTRACE_HARD_MAX_FRAMES "" CACHE STRING "Hard limit on unwinding depth. Default is 100.")
|
||||
set(CPPTRACE_ADDR2LINE_PATH "" CACHE STRING "Absolute path to the addr2line executable you want to use.")
|
||||
option(CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH "" OFF)
|
||||
|
||||
# ---- Other configurations ----
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
option(CPPTRACE_BUILD_TEST "" OFF)
|
||||
option(CPPTRACE_BUILD_DEMO "" OFF)
|
||||
option(CPPTRACE_BUILD_TEST_RDYNAMIC "" OFF)
|
||||
mark_as_advanced(
|
||||
CPPTRACE_BUILD_TEST
|
||||
CPPTRACE_BUILD_DEMO
|
||||
CPPTRACE_BUILD_TEST_RDYNAMIC
|
||||
)
|
||||
endif()
|
||||
|
||||
option(CPPTRACE_USE_EXTERNAL_LIBDWARF "" OFF)
|
||||
option(CPPTRACE_SANITIZER_BUILD "" OFF)
|
||||
|
||||
mark_as_advanced(
|
||||
CPPTRACE_BACKTRACE_PATH
|
||||
CPPTRACE_ADDR2LINE_PATH
|
||||
CPPTRACE_ADDR2LINE_SEARCH_SYSTEM_PATH
|
||||
CPPTRACE_SANITIZER_BUILD
|
||||
)
|
||||
8
cmake/PreventInSourceBuilds.cmake
Normal file
8
cmake/PreventInSourceBuilds.cmake
Normal file
@ -0,0 +1,8 @@
|
||||
# In-source build guard
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"In-source builds are not supported. "
|
||||
"You may need to delete 'CMakeCache.txt' and 'CMakeFiles/' before rebuilding this project."
|
||||
)
|
||||
endif()
|
||||
6
cmake/ProjectIsTopLevel.cmake
Normal file
6
cmake/ProjectIsTopLevel.cmake
Normal file
@ -0,0 +1,6 @@
|
||||
# This variable is set by project() in CMake 3.21+
|
||||
string(
|
||||
COMPARE EQUAL
|
||||
"${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}"
|
||||
PROJECT_IS_TOP_LEVEL
|
||||
)
|
||||
@ -1,3 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cpptrace_targets.cmake)
|
||||
9
cmake/has_backtrace.cpp
Normal file
9
cmake/has_backtrace.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#ifdef CPPTRACE_BACKTRACE_PATH
|
||||
#include CPPTRACE_BACKTRACE_PATH
|
||||
#else
|
||||
#include <backtrace.h>
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
backtrace_state* state = backtrace_create_state(nullptr, true, nullptr, nullptr);
|
||||
}
|
||||
14
cmake/in/cpptrace-config-cmake.in
Normal file
14
cmake/in/cpptrace-config-cmake.in
Normal file
@ -0,0 +1,14 @@
|
||||
# Init @ variables before doing anything else
|
||||
@PACKAGE_INIT@
|
||||
|
||||
# Dependencies
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(libdwarf REQUIRED)
|
||||
|
||||
# We cannot modify an existing IMPORT target
|
||||
if(NOT TARGET assert::assert)
|
||||
|
||||
# import targets
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@package_name@-targets.cmake")
|
||||
|
||||
endif()
|
||||
@ -7,6 +7,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cpptrace/cpptrace_export.hpp"
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#ifdef __has_include
|
||||
#if __has_include(<format>)
|
||||
@ -16,24 +18,18 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define CPPTRACE_API __declspec(dllexport)
|
||||
#else
|
||||
#define CPPTRACE_API
|
||||
#endif
|
||||
|
||||
namespace cpptrace {
|
||||
struct object_trace;
|
||||
struct stacktrace;
|
||||
|
||||
struct raw_trace {
|
||||
struct CPPTRACE_EXPORT raw_trace {
|
||||
std::vector<std::uintptr_t> frames;
|
||||
CPPTRACE_API static raw_trace current(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_API static raw_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_API object_trace resolve_object_trace() const;
|
||||
CPPTRACE_API stacktrace resolve() const;
|
||||
CPPTRACE_API void clear();
|
||||
CPPTRACE_API bool empty() const noexcept;
|
||||
static raw_trace current(std::uint_least32_t skip = 0);
|
||||
static raw_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
object_trace resolve_object_trace() const;
|
||||
stacktrace resolve() const;
|
||||
void clear();
|
||||
bool empty() const noexcept;
|
||||
|
||||
using iterator = std::vector<std::uintptr_t>::iterator;
|
||||
using const_iterator = std::vector<std::uintptr_t>::const_iterator;
|
||||
@ -45,20 +41,20 @@ namespace cpptrace {
|
||||
inline const_iterator cend() const noexcept { return frames.cend(); }
|
||||
};
|
||||
|
||||
struct object_frame {
|
||||
struct CPPTRACE_EXPORT object_frame {
|
||||
std::string obj_path;
|
||||
std::string symbol;
|
||||
std::uintptr_t raw_address = 0;
|
||||
std::uintptr_t obj_address = 0;
|
||||
};
|
||||
|
||||
struct object_trace {
|
||||
struct CPPTRACE_EXPORT object_trace {
|
||||
std::vector<object_frame> frames;
|
||||
CPPTRACE_API static object_trace current(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_API static object_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_API stacktrace resolve() const;
|
||||
CPPTRACE_API void clear();
|
||||
CPPTRACE_API bool empty() const noexcept;
|
||||
static object_trace current(std::uint_least32_t skip = 0);
|
||||
static object_trace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
stacktrace resolve() const;
|
||||
void clear();
|
||||
bool empty() const noexcept;
|
||||
|
||||
using iterator = std::vector<object_frame>::iterator;
|
||||
using const_iterator = std::vector<object_frame>::const_iterator;
|
||||
@ -70,7 +66,7 @@ namespace cpptrace {
|
||||
inline const_iterator cend() const noexcept { return frames.cend(); }
|
||||
};
|
||||
|
||||
struct stacktrace_frame {
|
||||
struct CPPTRACE_EXPORT stacktrace_frame {
|
||||
std::uintptr_t address;
|
||||
std::uint_least32_t line; // TODO: This should use UINT_LEAST32_MAX as a sentinel
|
||||
std::uint_least32_t column; // UINT_LEAST32_MAX if not present
|
||||
@ -89,21 +85,21 @@ namespace cpptrace {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
CPPTRACE_API std::string to_string() const;
|
||||
CPPTRACE_API friend std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame);
|
||||
std::string to_string() const;
|
||||
friend std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame);
|
||||
};
|
||||
|
||||
struct stacktrace {
|
||||
struct CPPTRACE_EXPORT stacktrace {
|
||||
std::vector<stacktrace_frame> frames;
|
||||
CPPTRACE_API static stacktrace current(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_API static stacktrace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_API void print() const;
|
||||
CPPTRACE_API void print(std::ostream& stream) const;
|
||||
CPPTRACE_API void print(std::ostream& stream, bool color) const;
|
||||
CPPTRACE_API void clear();
|
||||
CPPTRACE_API bool empty() const noexcept;
|
||||
CPPTRACE_API std::string to_string(bool color = false) const;
|
||||
CPPTRACE_API friend std::ostream& operator<<(std::ostream& stream, const stacktrace& trace);
|
||||
static stacktrace current(std::uint_least32_t skip = 0);
|
||||
static stacktrace current(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
void print() const;
|
||||
void print(std::ostream& stream) const;
|
||||
void print(std::ostream& stream, bool color) const;
|
||||
void clear();
|
||||
bool empty() const noexcept;
|
||||
std::string to_string(bool color = false) const;
|
||||
friend std::ostream& operator<<(std::ostream& stream, const stacktrace& trace);
|
||||
|
||||
using iterator = std::vector<stacktrace_frame>::iterator;
|
||||
using const_iterator = std::vector<stacktrace_frame>::const_iterator;
|
||||
@ -114,27 +110,27 @@ namespace cpptrace {
|
||||
inline const_iterator cbegin() const noexcept { return frames.cbegin(); }
|
||||
inline const_iterator cend() const noexcept { return frames.cend(); }
|
||||
private:
|
||||
CPPTRACE_API void print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const;
|
||||
void print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const;
|
||||
friend void print_terminate_trace();
|
||||
};
|
||||
|
||||
CPPTRACE_API raw_trace generate_raw_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_API raw_trace generate_raw_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_API object_trace generate_object_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_API object_trace generate_object_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_API stacktrace generate_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_API stacktrace generate_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_EXPORT raw_trace generate_raw_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_EXPORT raw_trace generate_raw_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_EXPORT object_trace generate_object_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_EXPORT object_trace generate_object_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
CPPTRACE_EXPORT stacktrace generate_trace(std::uint_least32_t skip = 0);
|
||||
CPPTRACE_EXPORT stacktrace generate_trace(std::uint_least32_t skip, std::uint_least32_t max_depth);
|
||||
|
||||
// utilities:
|
||||
CPPTRACE_API std::string demangle(const std::string& name);
|
||||
CPPTRACE_API void absorb_trace_exceptions(bool absorb);
|
||||
CPPTRACE_API bool isatty(int fd);
|
||||
CPPTRACE_EXPORT std::string demangle(const std::string& name);
|
||||
CPPTRACE_EXPORT void absorb_trace_exceptions(bool absorb);
|
||||
CPPTRACE_EXPORT bool isatty(int fd);
|
||||
|
||||
CPPTRACE_API extern const int stdin_fileno;
|
||||
CPPTRACE_API extern const int stderr_fileno;
|
||||
CPPTRACE_API extern const int stdout_fileno;
|
||||
CPPTRACE_EXPORT extern const int stdin_fileno;
|
||||
CPPTRACE_EXPORT extern const int stderr_fileno;
|
||||
CPPTRACE_EXPORT extern const int stdout_fileno;
|
||||
|
||||
CPPTRACE_API void register_terminate_handler();
|
||||
CPPTRACE_EXPORT void register_terminate_handler();
|
||||
|
||||
enum class cache_mode {
|
||||
// Only minimal lookup tables
|
||||
@ -146,15 +142,15 @@ namespace cpptrace {
|
||||
};
|
||||
|
||||
namespace experimental {
|
||||
CPPTRACE_API void set_cache_mode(cache_mode mode);
|
||||
CPPTRACE_EXPORT void set_cache_mode(cache_mode mode);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
CPPTRACE_API bool should_absorb_trace_exceptions();
|
||||
CPPTRACE_API enum cache_mode get_cache_mode();
|
||||
CPPTRACE_EXPORT bool should_absorb_trace_exceptions();
|
||||
CPPTRACE_EXPORT enum cache_mode get_cache_mode();
|
||||
}
|
||||
|
||||
class exception : public std::exception {
|
||||
class CPPTRACE_EXPORT exception : public std::exception {
|
||||
mutable raw_trace trace;
|
||||
mutable stacktrace resolved_trace;
|
||||
mutable std::string what_string;
|
||||
@ -177,7 +173,7 @@ namespace cpptrace {
|
||||
const stacktrace& get_trace() const noexcept;
|
||||
};
|
||||
|
||||
class exception_with_message : public exception {
|
||||
class CPPTRACE_EXPORT exception_with_message : public exception {
|
||||
mutable std::string message;
|
||||
|
||||
protected:
|
||||
|
||||
@ -28,17 +28,16 @@
|
||||
#define CYAN ESC "36m"
|
||||
|
||||
namespace cpptrace {
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace raw_trace::current(std::uint_least32_t skip) {
|
||||
return generate_raw_trace(skip + 1);
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace raw_trace::current(std::uint_least32_t skip, std::uint_least32_t max_depth) {
|
||||
return generate_raw_trace(skip + 1, max_depth);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
object_trace raw_trace::resolve_object_trace() const {
|
||||
try {
|
||||
return object_trace{detail::get_frames_object_info(frames)};
|
||||
@ -50,7 +49,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
stacktrace raw_trace::resolve() const {
|
||||
try {
|
||||
std::vector<stacktrace_frame> trace = detail::resolve_frames(frames);
|
||||
@ -66,27 +64,24 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void raw_trace::clear() {
|
||||
frames.clear();
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
bool raw_trace::empty() const noexcept {
|
||||
return frames.empty();
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
object_trace object_trace::current(std::uint_least32_t skip) {
|
||||
return generate_object_trace(skip + 1);
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
object_trace object_trace::current(std::uint_least32_t skip, std::uint_least32_t max_depth) {
|
||||
return generate_object_trace(skip + 1, max_depth);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
stacktrace object_trace::resolve() const {
|
||||
try {
|
||||
return stacktrace{detail::resolve_frames(frames)};
|
||||
@ -98,23 +93,21 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void object_trace::clear() {
|
||||
frames.clear();
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
bool object_trace::empty() const noexcept {
|
||||
return frames.empty();
|
||||
}
|
||||
|
||||
CPPTRACE_API std::string stacktrace_frame::to_string() const {
|
||||
std::string stacktrace_frame::to_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << *this;
|
||||
return std::move(oss).str();
|
||||
}
|
||||
|
||||
CPPTRACE_API std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame) {
|
||||
std::ostream& operator<<(std::ostream& stream, const stacktrace_frame& frame) {
|
||||
stream
|
||||
<< std::hex
|
||||
<< "0x"
|
||||
@ -138,32 +131,28 @@ namespace cpptrace {
|
||||
return stream;
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
stacktrace stacktrace::current(std::uint32_t skip) {
|
||||
return generate_trace(skip + 1);
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
stacktrace stacktrace::current(std::uint_least32_t skip, std::uint_least32_t max_depth) {
|
||||
return generate_trace(skip + 1, max_depth);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void stacktrace::print() const {
|
||||
print(std::cerr, true);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void stacktrace::print(std::ostream& stream) const {
|
||||
print(stream, true);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void stacktrace::print(std::ostream& stream, bool color) const {
|
||||
print(stream, color, true, nullptr);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void stacktrace::print(std::ostream& stream, bool color, bool newline_at_end, const char* header) const {
|
||||
if(color) {
|
||||
detail::enable_virtual_terminal_processing_if_needed();
|
||||
@ -224,28 +213,25 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
void stacktrace::clear() {
|
||||
frames.clear();
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
bool stacktrace::empty() const noexcept {
|
||||
return frames.empty();
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
std::string stacktrace::to_string(bool color) const {
|
||||
std::ostringstream oss;
|
||||
print(oss, color, false, nullptr);
|
||||
return std::move(oss).str();
|
||||
}
|
||||
|
||||
CPPTRACE_API std::ostream& operator<<(std::ostream& stream, const stacktrace& trace) {
|
||||
std::ostream& operator<<(std::ostream& stream, const stacktrace& trace) {
|
||||
return stream << trace.to_string();
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace generate_raw_trace(std::uint_least32_t skip) {
|
||||
try {
|
||||
return raw_trace{detail::capture_frames(skip + 1, UINT_LEAST32_MAX)};
|
||||
@ -257,7 +243,7 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
raw_trace generate_raw_trace(std::uint_least32_t skip, std::uint_least32_t max_depth) {
|
||||
try {
|
||||
return raw_trace{detail::capture_frames(skip + 1, max_depth)};
|
||||
@ -269,7 +255,7 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
object_trace generate_object_trace(std::uint_least32_t skip) {
|
||||
try {
|
||||
return object_trace{detail::get_frames_object_info(detail::capture_frames(skip + 1, UINT_LEAST32_MAX))};
|
||||
@ -281,7 +267,7 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
object_trace generate_object_trace(std::uint_least32_t skip, std::uint_least32_t max_depth) {
|
||||
try {
|
||||
return object_trace{detail::get_frames_object_info(detail::capture_frames(skip + 1, max_depth))};
|
||||
@ -293,12 +279,12 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
stacktrace generate_trace(std::uint_least32_t skip) {
|
||||
return generate_trace(skip + 1, UINT_LEAST32_MAX);
|
||||
}
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE CPPTRACE_API
|
||||
CPPTRACE_FORCE_NO_INLINE
|
||||
stacktrace generate_trace(std::uint32_t skip, std::uint_least32_t max_depth) {
|
||||
try {
|
||||
std::vector<std::uintptr_t> frames = detail::capture_frames(skip + 1, max_depth);
|
||||
@ -315,19 +301,17 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
std::string demangle(const std::string& name) {
|
||||
return detail::demangle(name);
|
||||
}
|
||||
|
||||
CPPTRACE_API
|
||||
bool isatty(int fd) {
|
||||
return detail::isatty(fd);
|
||||
}
|
||||
|
||||
CPPTRACE_API extern const int stdin_fileno = detail::fileno(stdin);
|
||||
CPPTRACE_API extern const int stdout_fileno = detail::fileno(stdout);
|
||||
CPPTRACE_API extern const int stderr_fileno = detail::fileno(stderr);
|
||||
extern const int stdin_fileno = detail::fileno(stdin);
|
||||
extern const int stdout_fileno = detail::fileno(stdout);
|
||||
extern const int stderr_fileno = detail::fileno(stderr);
|
||||
|
||||
CPPTRACE_FORCE_NO_INLINE void print_terminate_trace() {
|
||||
generate_trace(1).print(
|
||||
@ -338,7 +322,7 @@ namespace cpptrace {
|
||||
);
|
||||
}
|
||||
|
||||
[[noreturn]] CPPTRACE_API void terminate_handler() {
|
||||
[[noreturn]] void terminate_handler() {
|
||||
try {
|
||||
auto ptr = std::current_exception();
|
||||
if(ptr == nullptr) {
|
||||
@ -371,7 +355,7 @@ namespace cpptrace {
|
||||
abort();
|
||||
}
|
||||
|
||||
CPPTRACE_API void register_terminate_handler() {
|
||||
void register_terminate_handler() {
|
||||
std::set_terminate(terminate_handler);
|
||||
}
|
||||
|
||||
@ -380,22 +364,22 @@ namespace cpptrace {
|
||||
std::atomic<enum cache_mode> cache_mode(cache_mode::prioritize_speed); // NOSONAR
|
||||
}
|
||||
|
||||
CPPTRACE_API void absorb_trace_exceptions(bool absorb) {
|
||||
void absorb_trace_exceptions(bool absorb) {
|
||||
detail::absorb_trace_exceptions = absorb;
|
||||
}
|
||||
|
||||
namespace experimental {
|
||||
CPPTRACE_API void set_cache_mode(cache_mode mode) {
|
||||
void set_cache_mode(cache_mode mode) {
|
||||
detail::cache_mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
CPPTRACE_API bool should_absorb_trace_exceptions() {
|
||||
bool should_absorb_trace_exceptions() {
|
||||
return absorb_trace_exceptions;
|
||||
}
|
||||
|
||||
CPPTRACE_API enum cache_mode get_cache_mode() {
|
||||
enum cache_mode get_cache_mode() {
|
||||
return cache_mode;
|
||||
}
|
||||
|
||||
|
||||
@ -5,14 +5,14 @@ project(demo_project VERSION 0.0.1 LANGUAGES CXX)
|
||||
add_executable(main main.cpp)
|
||||
|
||||
add_subdirectory(cpptrace)
|
||||
target_link_libraries(main cpptrace)
|
||||
target_link_libraries(main cpptrace::cpptrace)
|
||||
target_compile_features(main PRIVATE cxx_std_11)
|
||||
|
||||
if(WIN32)
|
||||
add_custom_command(
|
||||
TARGET main POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:cpptrace>
|
||||
$<TARGET_FILE:cpptrace::cpptrace>
|
||||
$<TARGET_FILE_DIR:main>
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -20,7 +20,7 @@ if(WIN32)
|
||||
add_custom_command(
|
||||
TARGET main POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:cpptrace>
|
||||
$<TARGET_FILE:cpptrace::cpptrace>
|
||||
$<TARGET_FILE_DIR:main>
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -35,6 +35,7 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
set(cpptrace_DIR "../../build/foo/lib/cmake/cpptrace")
|
||||
set(libdwarf_DIR "../../build/foo/lib/cmake/libdwarf")
|
||||
find_package(cpptrace REQUIRED)
|
||||
|
||||
add_executable(speedtest speedtest.cpp)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user