Support building without Boost.Stacktrace

This commit is contained in:
Nikita Lisitsa 2025-01-26 14:45:43 +03:00
parent 4890761b0a
commit 6fc476f1f0
25 changed files with 95 additions and 69 deletions

View file

@ -2,6 +2,7 @@ file(GLOB_RECURSE RAPIDJSON_SOURCES "${CMAKE_CURRENT_LIST_DIR}/rapidjson/include
add_library(rapidjson INTERFACE EXCLUDE_FROM_ALL "${RAPIDJSON_SOURCES}")
target_include_directories(rapidjson INTERFACE "${CMAKE_CURRENT_LIST_DIR}/rapidjson/include")
if(PSEMEK_STACKTRACE)
set(LIBBACKTRACE_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/libbacktrace")
set(LIBBACKTRACE_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/libbacktrace")
set(LIBBACKTRACE_INCLUDE_DIR "${LIBBACKTRACE_BUILD_DIR}/include")
@ -27,3 +28,5 @@ endif()
add_library(libbacktrace INTERFACE)
target_include_directories(libbacktrace INTERFACE "${LIBBACKTRACE_INCLUDE_DIR}")
target_link_libraries(libbacktrace INTERFACE "${LIBBACKTRACE_LIBRARY}")
endif()

View file

@ -72,6 +72,12 @@ endif()
message(STATUS "Using graphics API ${PSEMEK_GRAPHICS_API}")
list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_GRAPHICS_API_${PSEMEK_GRAPHICS_API}=1")
option(PSEMEK_STACKTRACE "Use Boost.Stacktrace for stacktraces in exceptions" ON)
if(PSEMEK_STACKTRACE)
list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_STACKTRACE=1")
endif()
add_subdirectory(3rdparty)
get_directory_property(PSEMEK_PARENT_DIRECTORY PARENT_DIRECTORY)

View file

@ -63,7 +63,7 @@ namespace psemek::async
struct empty_future_error
: util::exception
{
empty_future_error(boost::stacktrace::stacktrace stacktrace = {})
empty_future_error(util::stacktrace stacktrace = {})
: util::exception("Future is empty", std::move(stacktrace))
{}
};
@ -71,7 +71,7 @@ namespace psemek::async
struct canceled_task_error
: util::exception
{
canceled_task_error(boost::stacktrace::stacktrace stacktrace = {})
canceled_task_error(util::stacktrace stacktrace = {})
: util::exception("Task canceled", std::move(stacktrace))
{}
};
@ -184,7 +184,7 @@ namespace psemek::async
struct empty_promise_error
: util::exception
{
empty_promise_error(boost::stacktrace::stacktrace stacktrace = {})
empty_promise_error(util::stacktrace stacktrace = {})
: util::exception("Promise is empty", std::move(stacktrace))
{}
};
@ -192,7 +192,7 @@ namespace psemek::async
struct satisfied_promise_error
: util::exception
{
satisfied_promise_error(boost::stacktrace::stacktrace stacktrace = {})
satisfied_promise_error(util::stacktrace stacktrace = {})
: util::exception("Promise already contains a value or exception", std::move(stacktrace))
{}
};

View file

@ -11,7 +11,7 @@ namespace psemek::bt
struct assertion_failed_exception
: util::exception
{
assertion_failed_exception(std::string message, boost::stacktrace::stacktrace stacktrace = {})
assertion_failed_exception(std::string message, util::stacktrace stacktrace = {})
: util::exception(std::move(message), std::move(stacktrace))
{}
};

View file

@ -13,7 +13,7 @@ namespace psemek::ecs::detail
struct duplicate_uuid_exception
: util::exception
{
duplicate_uuid_exception(util::uuid const & uuid, std::type_info const & type1, std::type_info const & type2, boost::stacktrace::stacktrace stacktrace = {})
duplicate_uuid_exception(util::uuid const & uuid, std::type_info const & type1, std::type_info const & type2, util::stacktrace stacktrace = {})
: util::exception(util::to_string("Found duplicate UUID ", uuid, " for components ", util::type_name(type1), " and ", util::type_name(type2)), std::move(stacktrace))
, uuid_(uuid)
, type1_(type1)

View file

@ -13,7 +13,7 @@ namespace psemek::ecs
struct component_not_found_exception
: util::exception
{
component_not_found_exception(std::type_info const & type, handle const & handle, std::string const & description, boost::stacktrace::stacktrace stacktrace = {})
component_not_found_exception(std::type_info const & type, handle const & handle, std::string const & description, util::stacktrace stacktrace = {})
: util::exception(util::to_string("Component ", util::type_name(type), " not found for entity ", handle, " <", description, ">"), std::move(stacktrace))
, type_(type)
, handle_(handle)
@ -37,7 +37,7 @@ namespace psemek::ecs
struct entity_not_cloneable
: util::exception
{
entity_not_cloneable(handle const & entity, std::vector<std::type_index> non_copyable_components, boost::stacktrace::stacktrace stacktrace = {})
entity_not_cloneable(handle const & entity, std::vector<std::type_index> non_copyable_components, util::stacktrace stacktrace = {})
: util::exception(make_message(entity, non_copyable_components), std::move(stacktrace))
, entity_(entity)
, non_copyable_components_(std::move(non_copyable_components))

View file

@ -14,13 +14,13 @@ namespace psemek::io
struct null_istream
: null_stream
{
null_istream(boost::stacktrace::stacktrace stacktrace = {});
null_istream(util::stacktrace stacktrace = {});
};
struct null_ostream
: null_stream
{
null_ostream(boost::stacktrace::stacktrace stacktrace = {});
null_ostream(util::stacktrace stacktrace = {});
};
struct stream_end
@ -32,13 +32,13 @@ namespace psemek::io
struct istream_end
: stream_end
{
istream_end(boost::stacktrace::stacktrace stacktrace = {});
istream_end(util::stacktrace stacktrace = {});
};
struct ostream_end
: stream_end
{
ostream_end(boost::stacktrace::stacktrace stacktrace = {});
ostream_end(util::stacktrace stacktrace = {});
};
}

View file

@ -3,19 +3,19 @@
namespace psemek::io
{
null_istream::null_istream(boost::stacktrace::stacktrace stacktrace)
null_istream::null_istream(util::stacktrace stacktrace)
: null_stream("Attempt to read from null input stream", std::move(stacktrace))
{}
null_ostream::null_ostream(boost::stacktrace::stacktrace stacktrace)
null_ostream::null_ostream(util::stacktrace stacktrace)
: null_stream("Attempt to write to null output stream", std::move(stacktrace))
{}
istream_end::istream_end(boost::stacktrace::stacktrace stacktrace)
istream_end::istream_end(util::stacktrace stacktrace)
: stream_end("Unexpected input stream end", std::move(stacktrace))
{}
ostream_end::ostream_end(boost::stacktrace::stacktrace stacktrace)
ostream_end::ostream_end(util::stacktrace stacktrace)
: stream_end("Unexpected output stream end", std::move(stacktrace))
{}

View file

@ -61,7 +61,7 @@ namespace psemek::log
if (p.signal == signal)
{
log::error() << p.message;
log::error() << boost::stacktrace::stacktrace();
log::error() << util::stacktrace();
break;
}
}

View file

@ -8,7 +8,7 @@ namespace psemek::math::detail
struct empty_array_exception
: util::exception
{
empty_array_exception(boost::stacktrace::stacktrace stacktrace = {})
empty_array_exception(util::stacktrace stacktrace = {})
: util::exception("Indexing an empty array", std::move(stacktrace))
{}
};

View file

@ -14,25 +14,25 @@ namespace psemek::ml
struct empty_neural_net_error
: neural_net_error
{
empty_neural_net_error(boost::stacktrace::stacktrace stacktrace = {});
empty_neural_net_error(util::stacktrace stacktrace = {});
};
struct wrong_activation_types_count_error
: neural_net_error
{
wrong_activation_types_count_error(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace = {});
wrong_activation_types_count_error(std::size_t expected, std::size_t actual, util::stacktrace stacktrace = {});
};
struct wrong_neural_net_input_size
: neural_net_error
{
wrong_neural_net_input_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace = {});
wrong_neural_net_input_size(std::size_t expected, std::size_t actual, util::stacktrace stacktrace = {});
};
struct wrong_neural_net_output_size
: neural_net_error
{
wrong_neural_net_output_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace = {});
wrong_neural_net_output_size(std::size_t expected, std::size_t actual, util::stacktrace stacktrace = {});
};
}

View file

@ -5,19 +5,19 @@
namespace psemek::ml
{
empty_neural_net_error::empty_neural_net_error(boost::stacktrace::stacktrace stacktrace)
empty_neural_net_error::empty_neural_net_error(util::stacktrace stacktrace)
: neural_net_error("Neural net must have at least a single layer", std::move(stacktrace))
{}
wrong_activation_types_count_error::wrong_activation_types_count_error(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace)
wrong_activation_types_count_error::wrong_activation_types_count_error(std::size_t expected, std::size_t actual, util::stacktrace stacktrace)
: neural_net_error(util::to_string("Wrong number of activation types: expected ", expected, ", got ", actual), std::move(stacktrace))
{}
wrong_neural_net_input_size::wrong_neural_net_input_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace)
wrong_neural_net_input_size::wrong_neural_net_input_size(std::size_t expected, std::size_t actual, util::stacktrace stacktrace)
: neural_net_error(util::to_string("Wrong neural net input size: expected ", expected, ", got ", actual), std::move(stacktrace))
{}
wrong_neural_net_output_size::wrong_neural_net_output_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace)
wrong_neural_net_output_size::wrong_neural_net_output_size(std::size_t expected, std::size_t actual, util::stacktrace stacktrace)
: neural_net_error(util::to_string("Wrong neural net output size: expected ", expected, ", got ", actual), std::move(stacktrace))
{}

View file

@ -16,7 +16,7 @@ namespace psemek::parser
struct parse_error
: util::exception
{
parse_error(std::string message, std::size_t line, std::size_t character, boost::stacktrace::stacktrace stacktrace = {})
parse_error(std::string message, std::size_t line, std::size_t character, util::stacktrace stacktrace = {})
: util::exception(util::to_string(message, " at ", line, "#", character), std::move(stacktrace))
, message_{std::move(message)}
, line_{line}

View file

@ -11,7 +11,7 @@ namespace psemek::rs
struct unknown_id_error
: util::exception
{
unknown_id_error(rs::id id, boost::stacktrace::stacktrace stacktrace = {});
unknown_id_error(rs::id id, util::stacktrace stacktrace = {});
rs::id id() const { return id_; }
@ -22,7 +22,7 @@ namespace psemek::rs
struct unknown_name_error
: util::exception
{
unknown_name_error(std::string_view name, boost::stacktrace::stacktrace stacktrace = {});
unknown_name_error(std::string_view name, util::stacktrace stacktrace = {});
std::string_view name() const { return name_; }

View file

@ -41,12 +41,12 @@ namespace psemek::rs
}
unknown_id_error::unknown_id_error(rs::id id, boost::stacktrace::stacktrace stacktrace)
unknown_id_error::unknown_id_error(rs::id id, util::stacktrace stacktrace)
: util::exception(util::to_string("unknown resource id: ", id), std::move(stacktrace))
, id_(id)
{}
unknown_name_error::unknown_name_error(std::string_view name, boost::stacktrace::stacktrace stacktrace)
unknown_name_error::unknown_name_error(std::string_view name, util::stacktrace stacktrace)
: util::exception(util::to_string("unknown resource name: ", name), std::move(stacktrace))
{}

View file

@ -5,8 +5,12 @@ file(GLOB_RECURSE PSEMEK_UTIL_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "so
psemek_add_library(psemek-util ${PSEMEK_UTIL_HEADERS} ${PSEMEK_UTIL_SOURCES})
target_include_directories(psemek-util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(psemek-util PUBLIC ${CMAKE_THREAD_LIBS_INIT} Boost::boost libbacktrace)
target_link_libraries(psemek-util PUBLIC ${CMAKE_THREAD_LIBS_INIT} Boost::boost)
if(PSEMEK_STACKTRACE)
target_link_libraries(psemek-util PUBLIC libbacktrace)
target_compile_definitions(psemek-util PUBLIC "-DBOOST_STACKTRACE_USE_BACKTRACE")
endif()
psemek_glob_tests(psemek-util tests)

View file

@ -12,7 +12,7 @@
namespace psemek::util
{
[[noreturn]] inline bool assertion_handler(char const * assertion, boost::stacktrace::stacktrace stacktrace = {})
[[noreturn]] inline bool assertion_handler(char const * assertion, stacktrace stacktrace = {})
{
throw ::psemek::util::exception(assertion, std::move(stacktrace));
}

View file

@ -36,7 +36,7 @@ namespace psemek::util
struct key_error
: key_error_base
{
key_error(Key const & key, boost::stacktrace::stacktrace stacktrace = {})
key_error(Key const & key, util::stacktrace stacktrace = {})
: key_error_base(detail::key_error_to_string(key), std::move(stacktrace))
, key_(key)
{}

View file

@ -26,7 +26,7 @@ namespace psemek::util
struct unknown_enum_value_exception
: unknown_enum_value_exception_base
{
unknown_enum_value_exception(Enum value, boost::stacktrace::stacktrace stacktrace = {})
unknown_enum_value_exception(Enum value, util::stacktrace stacktrace = {})
: unknown_enum_value_exception_base(to_string("unknown ", type_name<Enum>(), " value: ", static_cast<std::underlying_type_t<Enum>>(value)), std::move(stacktrace))
, value_(value)
{}

View file

@ -1,6 +1,8 @@
#pragma once
#ifdef PSEMEK_STACKTRACE
#include <boost/stacktrace.hpp>
#endif
#include <exception>
#include <string>
@ -9,10 +11,24 @@
namespace psemek::util
{
#ifdef PSEMEK_STACKTRACE
using stacktrace = boost::stacktrace::stacktrace;
#else
struct stacktrace
{
template <typename Stream>
friend Stream & operator << (Stream & stream, stacktrace)
{
stream << "(stacktrace disabled)\n";
return stream;
}
};
#endif
struct exception
: std::exception
{
exception(std::string message, boost::stacktrace::stacktrace stacktrace = {})
exception(std::string message, stacktrace stacktrace = {})
: message_(std::move(message))
, stacktrace_(std::move(stacktrace))
{}
@ -27,14 +43,14 @@ namespace psemek::util
return message_;
}
boost::stacktrace::stacktrace const & stacktrace() const noexcept
auto const & stacktrace() const noexcept
{
return stacktrace_;
}
private:
std::string message_;
boost::stacktrace::stacktrace stacktrace_;
util::stacktrace stacktrace_;
};
inline std::ostream & operator << (std::ostream & os, exception const & e)

View file

@ -3,7 +3,6 @@
#include <psemek/util/exception.hpp>
#include <type_traits>
#include <memory>
#include <functional>
namespace psemek::util
@ -12,7 +11,7 @@ namespace psemek::util
struct empty_function_error
: exception
{
empty_function_error(boost::stacktrace::stacktrace stacktrace = {})
empty_function_error(util::stacktrace stacktrace = {})
: exception("Trying to call an empty function", std::move(stacktrace))
{}
};

View file

@ -8,7 +8,7 @@ namespace psemek::util
struct not_implemented_error
: exception
{
not_implemented_error(boost::stacktrace::stacktrace stacktrace = {});
not_implemented_error(util::stacktrace stacktrace = {});
};
[[noreturn]] void not_implemented();

View file

@ -8,7 +8,7 @@ namespace psemek::util
struct system_error
: exception
{
system_error(std::error_code error_code, std::string message, boost::stacktrace::stacktrace stacktrace = {})
system_error(std::error_code error_code, std::string message, util::stacktrace stacktrace = {})
: exception(message + ": " + error_code.message(), std::move(stacktrace))
, error_code_(error_code)
{}

View file

@ -73,7 +73,7 @@ namespace psemek::util
struct invalid_utf8
: exception
{
invalid_utf8(char const * data, boost::stacktrace::stacktrace stacktrace = {})
invalid_utf8(char const * data, util::stacktrace stacktrace = {})
: exception("Invalid UTF-8 string", std::move(stacktrace))
, data_{data}
{}

View file

@ -1,11 +1,9 @@
#include <psemek/util/not_implemented.hpp>
#include <stdexcept>
namespace psemek::util
{
not_implemented_error::not_implemented_error(boost::stacktrace::stacktrace stacktrace)
not_implemented_error::not_implemented_error(util::stacktrace stacktrace)
: exception("Not implemented", std::move(stacktrace))
{}