Echo Writes Code

CHANGELOG.md

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

Added

Changed

Deprecated

Removed

Fixed

Security

0.8.0

Released on October 22, 2022.

Release notes

This release was tagged in order to transition off of GitLab and on to self-hosted storage. A large amount of changes were made, including the removal of all libraries besides core and test (which used to be called testing).

From this point on, the changelog will look different. Where there used to be a rigid rule in place of adding one or more changelog entries per merge, now only noteworthy changes will be recorded.

Another change from this point onwards is that the old GitLab links may no longer work. When possible, they will be replaced with links to afterlight.dev, where Crucible is now being hosted.

Added

  • A formatter for std::type_info
  • Formatters for C char and wchar_t strings with dynamic sizes
  • core::memory namespace for dealing with low-level memory management
    • Buffer type for managing object lifetimes inside of raw memory
    • HeapAllocator type for providing an interface to allocating heap memory
    • GenericStorage and HeapStorage types for managing memory from different sources
  • RecordFormatter now has two versions of a method called add_synthetic_field
    • These methods are used to add extra information that doesn't come from a physical member
  • core::vector::Vector (which used to be core::array::Array) can now be appended to using its push() method

Changed

  • Formatters for STL containers and C arrays are now multiline-capable
  • core::array became core::vector, and core::array::Array became core::vector::Vector
  • core::bit_array was merged into core::vector, and core::bit_array::BitArray became core::vector::BitVector
  • The backing for both vectors and bit vectors was changed from buffer::Buffer to memory::HeapStorage
  • All functionality from unix, windows, and process was consolidated and unified into core
  • Many, many other changes, too many to document here; see the release notes

Removed

  • core::buffer is gone since it no longer has any callers

Fixed

Security

0.7.0

Released on July 03, 2022.

Added

Build system

  • All executable and library targets now receive preprocessor definitions describing the target they're being compiled for
    • On Unix-like systems, the symbol CRUCIBLE_UNIX is defined in all header and source files
    • On Windows-like systems, the symbol CRUCIBLE_WINDOWS is defined in all header and source files
    • On all targets, the symbol CRUCIBLE_ROOT is defined to the path to the root of the repository

core library

  • A library-level core.hpp header that #includes all other core headers
  • A new namespace called fallible
    • Provides a very similar type to either::Either, but with better semantics and more specific names
    • Also provides analogues for either::Lhs and either::Rhs called fallible::Failure and fallible::Success
    • Also also provides a type called Error that serves as a variadic error type container
  • A new namespace called arrays
    • Provides two new types: Array, which owns a dynamically allocated buffer; and Slice, which views a subsection of an Array
    • Also provides two overloads of a function called make_array(), which constructs an Array from a C array of static or dynamic size
  • A new overload of format::format_carray() that accepts a size argument
  • A new API for formatting classes and structs: format_record() and build_fields()
    • A new type, format::Context, supplies formatting parameters and can be made with format::build_context()
    • format_record() is a utility function that is called from T::format() for any T
    • build_fields() is used to obtain a builder object that collects all of the fields in the object into a string
  • A new API for working with packed bit arrays called bitarray
    • A class called BitArray that owns its storage
    • Another class called BitSlice that borrows a range of storage from a BitArray
  • A new API for typed memory buffers called buffer, containing:
    • A template class called Buffer that holds a pointer and a size (and auto-frees the pointer on destruction)
    • Free functions make_buffer_by_copy() and make_buffer_by_move() for creating a Buffer from a pointer and size
  • array, bit_array, and buffer can now all be constructed using a std::initializer_list
  • array and bit_array can now be constructed using a C-style array (and buffer always could be)
  • make_buffer_by_move() changed to do an element-wise move rather than steal a pointer
  • buffer::Accumulator added to handle building up a Buffer procedurally rather than using a std::vector or raw array
  • A formatter for std::variant

grok library

  • A new library that will (eventually) replace the parsing library

meta library

  • A new library for communicating meta-level information (like libc capabilities) from the build system to the source code
  • Runtime capabilities (mainly of the C library) can be checked using the CRUCIBLE_META_CAPABILITY_* macros in the capability.hpp header

process library

  • This is a new library that deals with things related to the process that Crucible is running inside of
  • So far, there is one namespace called backtrace, which deals with getting backtraces in a cross-platform way:
    • The take_detailed_snapshot() function captures as much debug information as possible in DetailedStackFrame objects
    • The take_simple_snapshot() function captures only function names in SimpleStackFrame objects
    • The terminate_handler() function can be registered as a terminate handler using std::set_terminate() to print a nice crash report
  • There is also the usual result namespace, with two error types so far:
    • EmptyBacktrace indicates that the stack walking mechanism found 0 frames above the caller in the current thread's call stack
    • MissingDebugInformation indicates that a detailed snapshot couldn't be performed because there was no debug information found

testing library

  • A library-level testing.hpp header that #includes all other testing headers
  • Two new macros: EXPECT_FAILURE() and EXPECT_SUCCESS(), which test the state of a fallible::Result object
  • Test suites now have names that are printed by the reporters on output

unix library

  • A library-level unix.hpp header that #includes all other unix headers
  • A new namespace called backtrace
    • Provides a function called snapshot() which takes a snapshot of the current call stack
    • Also provides a simple type called Frame which holds the symbol associated with each frame of the call stack

windows library

  • A library-level windows.hpp header that #incudes all other windows headers
  • A new namespace called backtrace
    • Provides a function called snapshot() which takes a snapshot of the current call stack
    • Also provides a simple type called Frame which holds a semantic description of one frame of the call stack

Changed

General

  • Combined the boba library with the vm library, then renamed it to bolt
  • Changed the supported Linux variant from Arch on amd64 to Ubuntu on amd64 in the README
  • Clarified the supported versions of macOS and Windows in the README
  • Convert all uses of core::either to use core::fallible instead
    • Exception: parsing still uses core::either, because it needs more work to support the change
  • All macro names across all targets have been standardized to the same naming convention
  • All structs and classes now use the new format() API (with format::Context)
  • Big lambdas refactored into named functions

Build system

  • Unified naming of all CMake modules, functions, and variables to make it obvious when something is part of Crucible
    • Modules are named with the convention CrucibleXyz.cmake
    • Functions are named with the convention crucible_xyz()
    • Variables are named with the convention CRUCIBLE_XYZ
  • Hid some low-level cache variables behind new CMake functions
    • crucible_configure_language_standards() handles setting language flags
    • crucible_configure_output_directory() handles setting the output directory of final artifacts
    • crucible_configure_shared_library_exports() handles setting flags for how shared library exports are handled
  • Handle platform-specific libraries in the CMakeLists.txt for those libraries

core library

  • All format functions now take T const & instead of T &&, because formatters should never change the thing they're formatting
  • arrays::Array and arrays::Slice now use the new formatting API
  • core::assert has better formatting for its messages now
  • format::format_pointer() now requires a formatting context so it can render a pointed-to record properly
  • fallible::Failure, fallible::Success, and fallible::Result now behave more like a true sum type (and by extension, functor and monad)
  • Renamed core::fallible to core::result
  • Renamed core::bitarray to core::bit_array
  • array::Array and bit_array::BitArray are now backed by buffer::Buffer instead of raw memory
  • format::format_record() now has a simpler API

testing library

  • testing::cli::execute() now sets the terminate handler to process::backtrace::terminate_handler(), which prints a crash report
  • testing::expect has better formatting for its messages now
  • testing::console_reporter has totally redone reporting for better readability
    • Failures are now collected and displayed at the end, rather than printed inline with the tests
    • Instead of indenting to show hierarchy, section headers with underlining and colors are used to flatten the output and make it easier to read
  • The formatting for the test summary is slightly different

Removed

  • The bobadump executable is totally gone, because boba has been rolled into the bolt library
  • The os library is gone, because its only user was bobadump (which was also removed)
  • The core::resource_warden namespace is gone, because it's very easy to get the same functionality without it
  • The parsing library is removed and will be replaced with grok
  • The bolt library was emptied out and will be remade once grok is ready
  • The core::format::build_fields() function is gone (not needed any more)

Fixed

  • Check the target compatibility after setting the C++ standard (so that static_assert works properly)
  • Make sure to save the CMAKE_*_OUTPUT_DIRECTORY variables to the CMake cache
  • Fixed compilation errors and failing tests when building on Linux
  • core::fallible::Result::bind_failure() and core::fallible::Result::bind_success() now perform a real >>= operation
  • Bug in the macro expansion of ASSERT() which made it not compile (comparisons were unaffected)

0.6.0

Released on February 05, 2022.

Added

parsing library

  • A new combinator called Map and associated factory function make_map()
    • Accepts a parser and a function and transforms the result of the parser using the function
  • A new combinator called Bind and associated factory function make_bind()
    • Uses the result of one parser to build a new parser, then applies the new parser
  • A new combinator called Tee and associated factory function make_tee()
    • Similar to Bind, but keeps the output of both parsers and returns it in a std::pair
  • Several new factory functions and types in the bytes namespace (used to be the bits namespace):
    • Endianness, an enumeration used to distinguish big-endian and little-endian parsers from one another
    • U8Le, U16Le, U32Le, U64Be, U8Be, U16Be, U32Be, and U64Be: parsers for the appropriate type and endianness
    • make_exact() and make_take(): factory functions for creating Exact and Take parsers
    • make_u8_le(), make_u16_le(), make_u32_le(), make_u64_le(): factory functions for little-endian unsigned integer parsers
    • make_u8_be(), make_u16_be(), make_u32_be(), make_u64_be(): factory functions for big-endian unsigned integer parsers

Changed

Build system

  • Disabled the C4180 compiler warning on MSVC due to not being helpful and causing the build to fail

bobadump executable

  • Updated output to correspond with new Boba format

boba library

  • Total overhaul of the file format and internals
    • The schema block is gone; instead we have a special container metadata section
    • The from_bytes() API is exactly the same, but the Container type is now a simple record containing a vector of headers
  • New namespace: container
    • Contains simple record types for both individual block headers and the container as a whole
  • New namespace: read
    • The from_bytes() function was moved here

parsing library

  • The meaning of the Into parser combinator has changed
    • Into<T> now converts the result of its wrapped parser into a T using one of T's constructors
  • The bits namespace has been renamed to bytes, and also renamed the contents:
    • Renamed BitsState type to State
    • Renamed ByteSequence parser to Exact
    • Renamed SizedByteSequence parser to Take
    • Combined BigEndianUnsignedInteger and LittleEndianUnsignedInteger parsers into UnsignedInteger

Removed

boba library

  • The metadata namespace is gone; see the new container and read namespaces for equivalent functionality

parsing library

  • The >> operator is no longer overloaded to construct an instance of Into
    • Use make_into() instead

Fixed

bobadump executable

  • Tests were not passing on windows due to \r\n line endings not being handled correctly in the test script

parsing library

  • Compilation errors on macOS due to mis-ordered class fields and missing constructors

0.5.0

Released on January 01, 2022.

Added

bobadump executable

  • New executable for dumping Boba files
    • No options; just use crucible-bobadump BOBA_FILE
    • Prints the schema header (but not the schema entries) and each user header

core library

  • New formatter for primitive integer types called format_integral()
    • Will work on anything for which std::is_integral evaluates to true
  • New abstract method in AbstractError called describe()
    • In contrast to format(), which is intended for developers, describe() is intended for end users
  • either::Either got new methods bind_lhs() and bind_rhs()
    • Maps a value to a whole new Either instance
    • This is in contrast to map_lhs() and map_rhs(), which map a value to another value
    • Can be used to chain Either-returning functions together

os library

  • New library for abstracting over "operating-system-y" things
    • Automatically switches between unix and windows as a backend depending on the compilation target
    • The fs namespace has platform-agnostic wrapper functions for all of the utilities in unix::fs and windows::fs

Build system

  • Support for Python test drivers via add_crucible_python_test() (intended mainly for testing executables)

General

  • Added information about Python tests to the readme
  • Added information about supported compilation targets to the readme

Changed

bobadump executable

  • Renamed from boba-dump to just bobadump

core library

  • either::LHS and either::RHS renamed to either::Lhs and either::Rhs for readability

os library

  • The Windows implementation of the fs namespace now uses the bind_lhs() and bind_rhs() APIs of core::either::Either

Build system

  • Silenced the message from find_package, which could be really long and was basically just noise

General

  • All uses of Result have been changed to Either to remove duplicated code
  • Better end-user error messages across the board
  • Uses of "Boba" as a word standardized on camel-case, not uppercase (BOBA) or lowercase (boba)

Removed

  • The core::result namespace has been completely removed; use core::either instead

Fixed

parsing library

  • Compilation error on MSVC due to signed/unsigned comparison mismatch

unix library

  • Errors now have their details reported properly (we see the errno message)

windows library

  • Errors now have their details reported properly (we see the GetLastError() message)

0.4.0

Released on December 04, 2021.

Added

New libraries

  • boba, the reference implementation of the BOBA (Bunch Of Big Arrays) file format

boba library

  • The new errors namespace:
    • The main error class BobaError
    • The ParsingFailed error variant for when loading a BOBA container fails
    • A type alias BobaResult for core::result::Result
  • The new metadata namespace:
    • A POD type called Header for keeping the (almost) raw information about each block header
    • A type called Schema that wraps the very first Header of a container, providing information about the rest of the contents
    • A type called Container that holds all block headers and provides iterator access to them, as well as the schema
    • A function called from_bytes() which deserializes a byte stream into a Container

core library

  • The format namespace:
    • Lots of functions for formatting anything you can think of: STL containers, plain arrays, C strings, pointers...
    • A format_anything() function which intelligently selects a formatter based on a compile-time type check
  • Lots of new ASSERT macros, for parity with the EXPECT API
  • The errors namespace:
    • An abstract base class called AbstractError, intended to be used for the Failure alternative of Result instances
  • Support for std::tuple in format::format_anything()
  • constexpr comparison operators for none::None

parsing library

  • A new combinator called SequenceOf
    • Used to parse an exact number of repetitions of a single structure
    • Fails if there aren't enough occurrences (but it's fine to have more)
    • Has an associated error called SequenceOfError
  • The errors namespace:
    • Error variants AmbiguousMatch, UnexpectedInput, and UnexpectedEndOfInput
    • The main error class ParsingError and a Result alias named ParsingResult
  • A new combinator called Tuple
    • Used to parse a heterogeneous sequence of substructures
    • No combinator operator; use combinators::make_tuple()
  • New factory functions for each combinator: make_one_of(), make_pair(), make_into(), and make_sequence_of()

unix library

  • The errors namespace:
    • The HostError type, which is moved from the old errno_error::ErrnoError type
    • Error variants moved from the fs namespace
    • The main error class UnixError and a Result alias named UnixError

windows library

  • The errors namespace:
    • The HostError, which is moved from the old windows_error::WindowsError type
    • Error variants moved from the fs and transcoding namespaces
    • The main error class WindowsError and a Result alias named WindowsResult

testing library

  • Self tests (at least, for the parts that can be isolated and tested!)

Changed

  • ASSERT, EXPECT, and Result now use the format_anything() function to render objects
  • All error handling is now done using a combination of core::errors::AbstractError and core::result::Result
    • Each library now has an errors namespace in which it defines its own specializations of these types

core library

  • none::None now formats as "None" instead of "None {}"

parsing library

  • AndThen combinator renamed to Pair (as a special case of Tuple)

Removed

  • ASSERT_NOT_NULL is gone; use ASSERT_NE(thing, nullptr)
  • The parsing::result, unix::errno_error, and windows::windows_error namespaces are all gone
    • See the errors namespaces in each library for a standardized replacement

0.3.0

Released on November 06, 2021.

Added

core library

  • A new namespace called assert, containing functions for implementing the ASSERT macro family
  • In the assert namespace:
    • A pair of new macros called ASSERT and ASSERT_NOT_NULL, which terminate the program with a message if the assertion does not pass
    • A template function called fail, which implements the assertion failure mechanism
  • A new namespace called either, containing the Either type for holding one of two types of value
  • In the either namespace:
    • A tag type called PreventSelectionForCopyAndMove used internally
    • A pair of templates called LHS and RHS which distinguish the alternatives of an Either
    • A template called Either which can hold one of two values, which can have different types
    • A pair of functions called make_lhs() and make_rhs(), which can be used to create LHS and RHS instances to pass to an Either

parsing library

  • In the bits namespace:
    • A new parser called SizedByteSequence which extracts a specific number of bytes from the input
  • In the combinators namespace:
    • A new combinator called Into, which functions like AndThen but dynamically constructs the second parser based on the result of the first parser
    • Two new errors called AndThenError and IntoError, which serve as error types for the AndThen and Into combinators
  • In the combinators::operators namespace:
    • An overloaded >> operator, which builds Into instances from a parser and a function

testing library

  • In the expect namespace:
    • A pair of new macros called EXPECT_CONTAINER_EQ and EXPECT_CONTAINER_NE, which check for (in)equality between two iterables
  • In the abstract_reporter namespace:
    • The AbstractReporter class now has default do-nothing implementations for all of its virtual methods
    • Two new hook methods for AbstractReporter: handle_group_start() and handle_group_end(), which get the name of the group
  • In the reporter namespace:
    • Forwarding methods for the handle_group_start() and handle_group_end() hooks
  • In the console_reporter namespace:
    • An implementation of handle_group_start that prints the group name

Changed

testing library

  • Scenarios and fixtures now both accept a tag argument before the name, which groups the fixtures and scenarios together
    • Tags can be filtered on the command line with the -t or --tag option
    • Fixtures will only be run for the scenarios that have the same tag
    • BeforeAll and AfterAll fixtures will only run if their tag isn't being filtered out
  • Output rendering is much clearer
    • A count of total scenarios run is now printed
    • Fixtures are now printed at the same level as scenarios instead of inside them
    • Fixtures receive a pass/fail note (when they would be printed anyways)
    • Added icons for each keyword to make distinguishing them a little clearer
    • Removed all white and bright white to make reading output on a white background easier
  • "Tags" renamed to "Groups"
    • The option in the CLI runner has been changed from -t/--tag to -g/--group
  • Groups are now used as "containers" for scenarios
    • There are now two loops: one over each group, and another over each scenario within the group
    • BeforeAll and AfterAll fixtures now run only within their group, not at the start or end of the whole suite
    • The console reporter will show groups as the main heading now, with scenarios and fixtures underneath

unix library

  • test_fs now uses the fixture mechanism to create and delete its file structure

General

  • Turned all instances of std::u8string, std::u8string_view, char8_t, and u8"" literals back into their legacy versions due to bad support
  • Standardized constructor syntax ({} unless () is semantically required)

parsing library

  • The bits::ByteSequence and text::CharacterSequence parsers now make a deep copy of their sequences
  • The bits::ByteSequence parser has been renamed to bits::ExactByteSequence

Fixed

  • Compilation error on AppleClang: no viable constructor or deduction guide in core::assert::fail()

0.2.0

Released on October 02, 2021.

Added

New libraries

  • vm library for the virtual machine implementation
  • parsing library for parser combinators

parsing library features

  • bits namespace containing primitives for parsing binary data
    • FixedWidthUnsignedIntegerType concept, which constrains to one of the std::uintN_t types
    • ByteSequenceMismatch basic error type
    • UnexpectedEndOfInput basic error type
    • BitsError composite error type
    • BitsState type specialized for binary data
    • ByteSequence parser which matches an exact sequence of bytes
    • LittleEndianUnsignedInteger parser template
    • BigEndianUnsignedInteger parser template
  • combinators namespace containing types for combining simple parsers into more complex parsers
    • BothMatch error template
    • NeitherMatch error template
    • OneOfError composite error type
    • OneOf parser combinator, which matches exclusively one or the other of the child parsers
    • AndThen parser combinator, which matches one parser followed by another parser and returns both results
    • operators namespace containing tools for building combinator trees
      • operator^, which combines two parsers using the OneOf combinator
      • operator&, which combines two parsers using the AndThen combinator
  • result namespace containing utility types for the outcomes of individual parsers
    • Reject template for holding information about a rejected parse
    • Accept template for holding information about an accepted parse
    • reject function for building a Reject wrapped in a core::result::Failure
    • accept function for building an Accept wrapped in a core::result::Success
  • text namespace containing primitives for parsing UTF-8 data
    • CharacterSequenceMismatch basic error type
    • TextError composite error type
    • TextState type specialized for UTF-8 data
    • CharacterSequence parser which matches an exact sequence of characters

testing library features

  • New namespace: fixture for types related to test fixtures
  • In the fixture namespace:
    • FixtureFunction alias for the type of a fixture function
    • FixtureVariant template type which serves as a base class for each kind of fixture
    • BeforeAll, AfterAll, BeforeEach, and AfterEach tag types which differentiate each kind of fixture
    • The Fixture type itself, which abstracts over all of these details
    • In the FixtureVariant type:
      • A constructor accepting a FixtureFunction
      • A getter method called get_name() which returns the name of the fixture variant based on which derived class calls it
      • A method named execute() which runs the fixture and returns an outcome, just like a scenario
    • In the BeforeAll, AfterAll, BeforeEach, and AfterEach types:
      • A constant string field containing the name of the variant for reporting purposes
    • In the Fixture type:
      • A constructor which accepts a name and a fixture variant
      • A template method called has_variant() which checks what kind of fixture this is
      • A method called get_variant_name() which forwards to get_name() on the underlying variant
      • A getter method called get_name() which retrieves the fixture's name
      • A method called execute() which forwards to execute() on the underlying variant
  • In the suite namespace:
    • Four new macros which define fixtures in the same way as scenarios: BEFORE_ALL, AFTER_ALL, BEFORE_EACH, and AFTER_EACH
    • A new type called FixtureRegistrar which is used by the new macros to add fixtures to the suite
    • In the FixtureRegistrar type:
      • A constructor that forwards to add_fixture() on the suite
    • In the Suite singleton:
      • A method called add_fixture() which registers a new fixture in the suite
  • In reporter::Reporter, abstract_reporter::AbstractReporter, and console_reporter::ConsoleReporter:
    • Two new methods called handle_fixture_start() and handle_fixture_end() which are called before and after each fixture
    • Another new method called set_show_fixtures() which toggles how much information is reported about fixtures
  • In the expect namespace:
    • A new template function called fail_comparison(), which is exactly like fail() but formats its output specifically as a comparison failure

Changed

Build system

  • Upgrade the C++ version to C++20
  • Renamed the test library to testing to better fit with other library names (specifically parsing)

testing library features

  • Print a special message when there are no tests in a test suite
  • Tests can now accept a --show-fixtures argument on the command line which causes the reporter to print more information about which fixtures run and when
  • The SCENARIO macro and ScenarioRegistrar type have been moved to the suite namespace
  • The console reporter will now display a count of total fixture invocations in the suite summary
  • All reporters now require a third argument, fixture_count, to the handle_suite_end() method
  • The EXPECT family of macros now print much more detailed information when a test fails
  • In the expect namespace:
    • The fail function now takes more arguments and has been made into a template based on the type of value being EXPECTed

Fixed

parsing library

  • Compilation cast truncates constant value warning on MSVC

testing library

  • Disallow copying and moving the Suite singleton
  • Incorrect include guard symbols
  • Compilation warning on AppleClang: [[nodiscard]] on a function returning void

Build system

  • Give a nice message from CMake instead of weird errors when trying to build for non-64-bit systems

0.1.0

Released on September 04, 2021.

Added

New libraries

  • core library for fundamental types and functions used by everything else
  • test library for testing infrastructure
  • unix library for wrapping Unix-like APIs
  • windows library for wrapping Windows APIs

core library features

  • core::constant_error namespace, containing a ConstantError template for errors with a constant message
  • core::error_chain namespace, containing the ErrorChain class for building complex error types
  • core::none namespace, containing the None type to use as a placeholder
  • core::resource_warden namespace, containing a class template for cleaning up raw resources on scope exit
  • core::result namespace, containing facilities for operations that can fail

test library features

  • test::abstract_reporter namespace, containing the AbstractReporter interface
  • test::cli namespace, containing a function execute() that can be called from main()
  • test::console_reporter namespace, containing a reporter that writes to stdout
  • test::expect namespace, containing macros to express test assertions
  • test::outcome namespace, containing types representing scenario outcomes
  • test::reporter namespace, containing factories for specific reporters and also a wrapper type
  • test::scenario namespace, containing the Scenario type for representing a single test scenario
  • test::suite namespace, containing the Suite singleton used to hold all of the tests in a suite

unix library features

  • unix::errno_error namespace, containing utilities for working with errno
  • unix::fs namespace, containing wrappers for filesystem APIs on Unix-like systems

windows library features

  • windows::fs namespace, containing wrappers for filesystem APIs on Windows
  • windows::transcoding namespace, containing functions for transcoding UTF8 with UTF16 for Windows APIs
  • windows::windows_error namespace, containing functions and a type for reading and formatting Windows errors

Build system features

  • AddCrucibleExecutable module, which provides a wrapper for add_executable()
  • AddCrucibleLibrary module, which provides a wrapper for add_library()
  • AddCrucibleTest module, which provides a wrapper for add_test()
  • EnableCompilerWarnings module, which provides a function that enables common compiler warning flags
  • EnableRuntimeSanitizers module, which provides a function that enables ASAN, TSAN, and UBSAN based on options
  • Write all final build outputs (executables and libraries) to ${PROJECT_BINARY_DIR}/artifacts
  • Automatically export all symbols from all libraries when building Windows DLLs

Repository features

  • Build dependencies in the README
  • Build instructions in the README
  • Test instructions in the README
  • Attribution in the README