diff options
| author | Leitwolf | 2026-10-31 17:18:21 +0300 |
|---|---|---|
| committer | GitHub | 2026-10-31 17:18:21 +0300 |
| commit | 326ea0c0213aeecb6b984bba3dabb0ebad97679e (patch) | |
| tree | 5cec698f0bc0b8a60f45e866fb40f2fd8a358bd1 | |
| parent | 6a42cdf6461b2577106ef094d6f98025554b6077 (diff) | |
| parent | afe91797e9d50cd4712d3694a2e5fedfc0b966b1 (diff) | |
| download | catch3-326ea0c0213aeecb6b984bba3dabb0ebad97679e.tar.gz | |
Merge pull request #22 from Progmasoft/build/cpp17
Build Catch3 as C++17
46 files changed, 444 insertions, 264 deletions
@@ -1,12 +1,12 @@ build --enable_platform_specific_config -build:gcc9 --cxxopt=-std=c++2a -build:gcc11 --cxxopt=-std=c++2a -build:gcc13 --cxxopt=-std=c++2a +build:gcc9 --cxxopt=-std=c++17 +build:gcc11 --cxxopt=-std=c++17 +build:gcc13 --cxxopt=-std=c++17 build:clang13 --cxxopt=-std=c++17 build:vs2019 --cxxopt=/std:c++17 build:vs2022 --cxxopt=/std:c++17 build:windows --config=vs2022 build:linux --config=gcc11 -build:macos --cxxopt=-std=c++2b +build:macos --cxxopt=-std=c++17 diff --git a/.clang-format b/.clang-format index 05a21827..d6dcd25c 100644 --- a/.clang-format +++ b/.clang-format @@ -7,7 +7,7 @@ # PascalCase/camelCase conventions of Progmasoft C++ Style. Language: Cpp BasedOnStyle: LLVM -Standard: c++20 +Standard: c++17 UseTab: Never IndentWidth: 4 diff --git a/.github/workflows/linux-builds.yml b/.github/workflows/linux-builds.yml index 8597f658..5290574b 100644 --- a/.github/workflows/linux-builds.yml +++ b/.github/workflows/linux-builds.yml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: build_type: [Debug, Release] - std: [14, 17] + std: [17, 20] steps: - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 @@ -93,7 +93,7 @@ jobs: fail-fast: false matrix: build_type: [Debug, Release] - std: [14, 17] + std: [17, 20] steps: # Git comes first: without it the checkout falls back to an archive of diff --git a/.github/workflows/windows-simple-builds.yml b/.github/workflows/windows-simple-builds.yml index 164ff839..3de156c6 100644 --- a/.github/workflows/windows-simple-builds.yml +++ b/.github/workflows/windows-simple-builds.yml @@ -22,7 +22,7 @@ jobs: os: [windows-2025-vs2026] platform: [Win32, x64] build_type: [Debug, Release] - std: [14, 17] + std: [17, 20] steps: - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: diff --git a/CMake/catch3.pc.in b/CMake/catch3.pc.in index 60f81e7f..0e63b475 100644 --- a/CMake/catch3.pc.in +++ b/CMake/catch3.pc.in @@ -4,7 +4,7 @@ includedir=${prefix}/@include_dir@ libdir=${prefix}/@lib_dir@ Name: Catch3 -Description: A C++ test framework with a Catch2-compatible API; headers need C++14 and above +Description: A C++ test framework with a Catch2-compatible API; headers need C++17 and above URL: https://github.com/Progmasoft/catch3 Version: @Catch3_VERSION@ Cflags: -I${includedir} @@ -6,7 +6,7 @@ An independently maintained C++ test framework: Catch3 keeps the practical, expressive test-writing model that developers expect, while adding a separately -owned C++20 library for property checks, snapshots, structured results, and XML +owned C++17 library for property checks, snapshots, structured results, and XML serialization. > Catch3 is not an official Catch2 release and is not endorsed by Catch2's @@ -33,7 +33,7 @@ serialization. - **Structured results and XML output.** The runner's result model, with every attempt, and its deterministic JUnit XML writer are public. - **A compiled library, not a header-only package.** Snapshot I/O and result/XML - serialization are compiled C++20 implementations; templates and assertion + serialization are compiled C++17 implementations; templates and assertion macros remain in headers where needed. Catch3 is in an early development stage. Catch2's command line and reporters @@ -87,8 +87,8 @@ target_link_libraries(MyTests PRIVATE Catch3::Catch3WithMain) `Catch3::Catch3` is the library: the engine, the runner, property testing and snapshots; `Catch3::Catch3WithMain` adds the default `main`. Tests include `<Progmasoft/Catch3/TestMacros.hpp>` and the other `Progmasoft/Catch3/` -headers. The library is built as C++20; code that includes only the engine's -headers needs C++14. Catch3 and Catch2 can be installed side by side, as +headers. The library is C++17, and its headers work in C++17 +and later. Catch3 and Catch2 can be installed side by side, as their package, target, header and pkg-config names differ. ## Documentation diff --git a/docs/Readme.md b/docs/Readme.md index 18bdf927..3da1a8ca 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -2,7 +2,7 @@ # Catch3 documentation Catch3 keeps Catch2's API for writing tests, runs them with -[its own runner](progmasoft-runner.md#top) and adds Progmasoft's C++20 +[its own runner](progmasoft-runner.md#top) and adds Progmasoft's C++17 extensions. Start with the [tutorial](tutorial.md#top), then read [the runner](progmasoft-runner.md#top), [what Catch3 adds](progmasoft-catch3.md), [native property testing](progmasoft-properties.md), [the roadmap](progmasoft-roadmap.md) and diff --git a/docs/cmake-integration.md b/docs/cmake-integration.md index 01c9905a..c6e3771c 100644 --- a/docs/cmake-integration.md +++ b/docs/cmake-integration.md @@ -16,8 +16,8 @@ Catch3's CMake package is `Catch3`. It exports two targets: 1. `Catch3::Catch3`, the library: the Catch2-compatible engine, the Catch3 - runner, property testing and snapshots. It is built as C++20; code that - includes only the engine's headers needs C++14. + runner, property testing and snapshots. It is C++17, and its headers + work in C++17 and later. 2. `Catch3::Catch3WithMain`, the library with the default `main`. `Catch3.cmake` registers each `TEST_CASE` with CTest. diff --git a/docs/contributing.md b/docs/contributing.md index 05c1f415..82e82675 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -62,13 +62,13 @@ distribution with `python tools/scripts/generateAmalgamatedFiles.py`. what Catch3 promises to keep: code that compiles against Catch2's headers must keep compiling. It stays under the Boost Software License 1.0, keeps the `Catch2 Authors` header and follows the style of the surrounding Catch2 code. -Code that includes only its headers needs C++14. +Code that includes its headers needs C++17 or later. `src/Progmasoft` holds what Progmasoft adds: the runner, the results model, property testing and snapshots. It is licensed `MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1`, follows the [Progmasoft C++ Style](https://github.com/Progmasoft/progmasoft-cpp), is -C++20, reports recoverable errors with `Expected` rather than exceptions, and +C++17, reports recoverable errors with `Expected` rather than exceptions, and is formatted with the `.clang-format` beside it. `tools/scripts/checkLicense.py` checks that every source file carries the diff --git a/docs/faq.md b/docs/faq.md index 1ae93bca..63ada4e2 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -41,7 +41,7 @@ as needed later. The bundled Catch2-compatible engine provides no ABI stability guarantee. Its C++ interfaces should be compiled with a consistent compiler and build -configuration. The Progmasoft C++20 extension library does not currently +configuration. The Progmasoft C++17 extension library does not currently promise a stable binary ABI either. Catch2 is not designed to be distributed as dynamic library, and you diff --git a/docs/progmasoft-catch3.md b/docs/progmasoft-catch3.md index 7dc09822..49754af1 100644 --- a/docs/progmasoft-catch3.md +++ b/docs/progmasoft-catch3.md @@ -170,8 +170,8 @@ call-site expansion require it. ## Build and integration The CMake package is `Catch3`, with the targets `Catch3::Catch3` and -`Catch3::Catch3WithMain`. The library is built as C++20; code that includes -only the engine's headers still needs only C++14. After installation, +`Catch3::Catch3WithMain`. The library is C++17, and its headers work in C++17 +and later. After installation, consumers can use: ```cmake @@ -186,7 +186,7 @@ ways to build the same engine and property tests. Their root files are `CMakeLists.txt`, `meson.build`, `xmake.lua`, and `premake5.lua`. Xmake and Premake materialize the default generated configuration header, `Progmasoft/Catch3/UserConfig.hpp`, from the checked-in template. Meson 1.1.0 or newer is required for the Clang-CL -C++20 test target. +C++17 test target. For project history, compatibility intent, license split, and current feature limits, read [Why Progmasoft Catch3?](why-catch3.md). diff --git a/docs/progmasoft-properties.md b/docs/progmasoft-properties.md index e4302383..0b13ad60 100644 --- a/docs/progmasoft-properties.md +++ b/docs/progmasoft-properties.md @@ -224,6 +224,6 @@ A mismatch reports both results as notes. ## Compatibility -The engine is C++20 and part of the `Catch3::Catch3` library. It does not +The engine is C++17 and part of the `Catch3::Catch3` library. It does not change the `Catch` namespace, and it needs no exceptions: a client built without them gets the same results, except that an exception thrown by a body cannot be caught. diff --git a/docs/why-catch3.md b/docs/why-catch3.md index 4d29c4ff..120295f0 100644 --- a/docs/why-catch3.md +++ b/docs/why-catch3.md @@ -17,7 +17,7 @@ Catch2's runner with [its own](progmasoft-runner.md#top). | --- | --- | --- | | Test execution | Catch2's test registration, `RunContext` and listeners | The Catch3 runner: parallel worker processes, retries, flaky-test detection, quarantine, history, selection, sharding and its own command line and reports; `CATCH3_CHECK_FOR_ALL` and `CATCH3_CHECK_PROPERTY` report property outcomes through Catch2's assertion path | | Public include path | The engine's headers moved to `Progmasoft/Catch3/...` with Progmasoft names, such as `TestMacros.hpp` | `Progmasoft/Catch3.hpp` and the other `Progmasoft/Catch3/...` headers | -| C++ baseline | Code that includes the engine's headers needs C++14; the library, which holds the runner, is built as C++20 | The added property API requires C++20 | +| C++ baseline | C++17; the headers work in C++17 and later | The same | | Randomness | Catch2's existing behavior is unchanged | A specified SplitMix64 sequence provides deterministic trial seeds and unbiased bounded integer sampling | | Generated values | No change to existing Catch2 generators | Strategies for numbers, text, collections and structures with `Map`, `Filter` and `FlatMap`; shrinking of recorded choices, so every combination shrinks; replay tokens and an example database; state machines, `Classify`/`Cover` statistics, targeted search, and differential and metamorphic oracles | | Build identity | One library: the `Catch3` CMake package with `Catch3::Catch3` and `Catch3::Catch3WithMain`, `//:catch3` in Bazel, `catch3` in Meson and pkg-config | The same library | @@ -41,7 +41,7 @@ continuity with the included Catch2 3.16.1 base; this is not a promise that ever future Catch2 upstream change will be adopted unchanged or that all downstream projects have already been validated. -The engine, the runner and the Progmasoft additions are one compiled C++20 +The engine, the runner and the Progmasoft additions are one compiled C++17 library. Template-based generators and call-site assertion macros remain in headers; snapshot I/O, result aggregation, and XML serialization are compiled implementations. diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp index fc87bf40..3b15cc2d 100644 --- a/extras/catch_amalgamated.cpp +++ b/extras/catch_amalgamated.cpp @@ -7,14 +7,14 @@ // SPDX-License-Identifier: BSL-1.0 // Catch3 v0.3.0, on the Catch2 v3.16.1 engine -// Generated: 2026-10-29 19:30:41.305371 +// Generated: 2026-10-31 13:33:37.309963 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. // // The parts that come from src/Progmasoft, the Catch3 runner, keep // their own copyright and license lines (MPL-2.0 WITH -// AdditionRef-Progmasoft-Exception-1.1). The runner needs C++20. +// AdditionRef-Progmasoft-Exception-1.1). The runner needs C++17. // ---------------------------------------------------------- #include "catch_amalgamated.hpp" @@ -14663,18 +14663,22 @@ namespace Progmasoft::Catch3::Runner for (const auto &[name, value] : additions) { const std::wstring wideName = Widen(name); - std::erase_if(entries, [&](const std::wstring &entry) { - // A leading '=' marks the hidden per-drive variables. - const auto equals = entry.find(L'=', 1); - return equals == wideName.size() - && CompareStringOrdinal( - entry.data(), - static_cast<int>(equals), - wideName.data(), - static_cast<int>(wideName.size()), - TRUE) - == CSTR_EQUAL; - }); + const auto removed = std::remove_if( + entries.begin(), + entries.end(), + [&](const std::wstring &entry) { + // A leading '=' marks the hidden per-drive variables. + const auto equals = entry.find(L'=', 1); + return equals == wideName.size() + && CompareStringOrdinal( + entry.data(), + static_cast<int>(equals), + wideName.data(), + static_cast<int>(wideName.size()), + TRUE) + == CSTR_EQUAL; + }); + entries.erase(removed, entries.end()); entries.push_back(wideName + L"=" + Widen(value)); } std::wstring block; @@ -15429,11 +15433,17 @@ namespace Progmasoft::Catch3::Runner } for (const auto &[name, value] : options.environment) { - std::erase_if(environmentStorage, [&](const std::string &entry) { - return entry.size() > name.size() - && entry.compare(0, name.size(), name) == 0 - && entry[name.size()] == '='; - }); + // A lambda cannot capture a structured binding in C++17. + const std::string &variable = name; + const auto removed = std::remove_if( + environmentStorage.begin(), + environmentStorage.end(), + [&](const std::string &entry) { + return entry.size() > variable.size() + && entry.compare(0, variable.size(), variable) == 0 + && entry[variable.size()] == '='; + }); + environmentStorage.erase(removed, environmentStorage.end()); environmentStorage.push_back(name + "=" + value); } std::vector<char *> environment; diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp index 09e99fb2..18d52356 100644 --- a/extras/catch_amalgamated.hpp +++ b/extras/catch_amalgamated.hpp @@ -7,14 +7,14 @@ // SPDX-License-Identifier: BSL-1.0 // Catch3 v0.3.0, on the Catch2 v3.16.1 engine -// Generated: 2026-10-29 19:30:41.164140 +// Generated: 2026-10-31 13:33:37.220554 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. // // The parts that come from src/Progmasoft, the Catch3 runner, keep // their own copyright and license lines (MPL-2.0 WITH -// AdditionRef-Progmasoft-Exception-1.1). The runner needs C++20. +// AdditionRef-Progmasoft-Exception-1.1). The runner needs C++17. // ---------------------------------------------------------- #ifndef CATCH_AMALGAMATED_HPP_INCLUDED #define CATCH_AMALGAMATED_HPP_INCLUDED diff --git a/extras/catch_amalgamated_third_party.hpp b/extras/catch_amalgamated_third_party.hpp index f5961365..3462ff20 100644 --- a/extras/catch_amalgamated_third_party.hpp +++ b/extras/catch_amalgamated_third_party.hpp @@ -1,5 +1,5 @@ // Catch3 v0.3.0: yyjson and pugixml for catch_amalgamated.cpp -// Generated: 2026-10-29 19:10:35.543593 +// Generated: 2026-10-31 13:33:37.396913 // ---------------------------------------------------------- // This file is an amalgamation of src/Progmasoft/Runner/Yyjson.inl, // src/Progmasoft/PugiXml.inl and the libraries they include from diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index c5b71e9c..03e205ce 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -8,7 +8,7 @@ add_library(fuzzhelper NullOStream.h NullOStream.cpp) target_link_libraries(fuzzhelper PUBLIC Catch3::Catch3) # The runner fuzzers include its C++20 headers. -target_compile_features(fuzzhelper PUBLIC cxx_std_20) +target_compile_features(fuzzhelper PUBLIC cxx_std_17) # This should be possible to set from the outside to be oss-fuzz compatible, # fix later. For now, target libFuzzer only. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f3b7812d..398260fd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -398,8 +398,7 @@ set_target_properties(Catch3 PROPERTIES # Code that includes the engine's headers needs C++14, and the other # Progmasoft/ headers C++20; the library itself, with the runner, is built as C++20. -target_compile_features(Catch3 PUBLIC cxx_std_14) -set_target_properties(Catch3 PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON) +target_compile_features(Catch3 PUBLIC cxx_std_17) configure_file( "${SOURCES_DIR}/UserConfig.hpp.in" @@ -491,7 +490,7 @@ if(CATCH3_BUILD_EXAMPLES OR CATCH3_BUILD_EXTRA_TESTS) ) # These targets compile the library's sources themselves, the runner's # among them, which need C++20. - target_compile_features(Catch3_buildall_interface INTERFACE cxx_std_20) + target_compile_features(Catch3_buildall_interface INTERFACE cxx_std_17) endif() list(APPEND CATCH_IMPL_TARGETS Catch3 Catch3WithMain) diff --git a/src/Progmasoft/BUILD.bazel b/src/Progmasoft/BUILD.bazel index 5824d1b6..a3b4d68e 100644 --- a/src/Progmasoft/BUILD.bazel +++ b/src/Progmasoft/BUILD.bazel @@ -4,12 +4,11 @@ load("@bazel_skylib//rules:expand_template.bzl", "expand_template") load("@rules_cc//cc:defs.bzl", "cc_library") # Catch3: the Catch2-compatible engine in Catch3/, the runner in Runner/, -# property testing and snapshots. It is built as C++20; code that includes -# only the engine's headers needs C++14. //:catch3 and //:catch3_main are the -# public names. -CPP20 = select({ - "@platforms//os:windows": ["/std:c++20"], - "//conditions:default": ["-std=c++20"], +# property testing and snapshots. It is C++17 and its headers work in C++17 +# and later. //:catch3 and //:catch3_main are the public names. +CPP17 = select({ + "@platforms//os:windows": ["/std:c++17"], + "//conditions:default": ["-std=c++17"], }) # The engine's configuration header, with Bazel support switched on. @@ -89,7 +88,7 @@ cc_library( exclude = ["Catch3/Internal/Main.cpp"], ), hdrs = glob(["**/*.hpp"]) + [":Catch3/UserConfig.hpp"], - copts = CPP20, + copts = CPP17, linkstatic = True, strip_include_prefix = "/src", visibility = ["//:__pkg__"], @@ -102,7 +101,7 @@ cc_library( cc_library( name = "catch3_main", srcs = ["Catch3/Internal/Main.cpp"], - copts = CPP20, + copts = CPP17, linkstatic = True, visibility = ["//:__pkg__"], deps = [":catch3"], diff --git a/src/Progmasoft/Catch3/Detail/TypeTraits.hpp b/src/Progmasoft/Catch3/Detail/TypeTraits.hpp new file mode 100644 index 00000000..56f06665 --- /dev/null +++ b/src/Progmasoft/Catch3/Detail/TypeTraits.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2026 Progmasoft. +// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1 +#pragma once + +#include <type_traits> +#include <utility> + +namespace Progmasoft::Catch3::Detail +{ + + /// std::remove_cvref_t, which C++17 does not have. + template<typename Type> + using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<Type>>; + + /// std::identity, which C++17 does not have. + struct Identity final + { + template<typename Type> + [[nodiscard]] constexpr Type && + operator()(Type &&value) const noexcept + { + return std::forward<Type>(value); + } + }; + + /// An integral type that holds numbers, so anything but bool. + template<typename Type> + inline constexpr bool kIsInteger + = std::is_integral_v<Type> + && !std::is_same_v<std::remove_cv_t<Type>, bool>; + + /// Limits a function template to the types of kIsInteger. + template<typename Type> + using EnableIfInteger = std::enable_if_t<kIsInteger<Type>, int>; + + template<typename Type, typename = void> + inline constexpr bool kIsEqualityComparable = false; + + template<typename Type> + inline constexpr bool kIsEqualityComparable< + Type, + std::enable_if_t< + std::is_convertible_v<decltype(std::declval<const Type &>() + == std::declval<const Type &>()), + bool>>> = true; + +} // namespace Progmasoft::Catch3::Detail diff --git a/src/Progmasoft/Catch3/ForAll.hpp b/src/Progmasoft/Catch3/ForAll.hpp index e41bfdb6..748b89c6 100644 --- a/src/Progmasoft/Catch3/ForAll.hpp +++ b/src/Progmasoft/Catch3/ForAll.hpp @@ -148,7 +148,27 @@ namespace Progmasoft::Catch3 template<typename Type> inline constexpr bool kIsPropertyOptions - = std::is_same_v<std::remove_cvref_t<Type>, PropertyOptions>; + = std::is_same_v<RemoveCvRef<Type>, PropertyOptions>; + + template<typename Arguments, std::size_t... Index> + [[nodiscard]] PropertyResult + ForAllWithOptions(Arguments &all, std::index_sequence<Index...>) + { + constexpr std::size_t kCount = std::tuple_size_v<Arguments>; + return ForAllWith(std::get<0>(all), + std::get<kCount - 1U>(all), + std::get<Index + 1U>(all)...); + } + + template<typename Arguments, std::size_t... Index> + [[nodiscard]] PropertyResult + ForAllWithDefaults(Arguments &all, std::index_sequence<Index...>) + { + constexpr std::size_t kCount = std::tuple_size_v<Arguments>; + return ForAllWith(PropertyOptions{}, + std::get<kCount - 1U>(all), + std::get<Index>(all)...); + } } // namespace Detail @@ -172,19 +192,15 @@ namespace Pr |