diff options
| author | Leitwolf | 2026-11-02 00:51:11 +0300 |
|---|---|---|
| committer | GitHub | 2026-11-02 00:51:11 +0300 |
| commit | 268698be92962247a21a86dda4de2d4267adcf8f (patch) | |
| tree | 510f7ece1750b2da6d9b4666b7c58908c8d193bb | |
| parent | 13324a043042110eba456424fa39c1334857ceaa (diff) | |
| parent | 3ed0fd930371823b6d44ae64d00dbd79e421a552 (diff) | |
| download | catch3-268698be92962247a21a86dda4de2d4267adcf8f.tar.gz | |
Merge pull request #36 from Progmasoft/feature/cpp-tools
Move the tools from Python to C++17 and Bazel
50 files changed, 2503 insertions, 1292 deletions
diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 4a634ea3..deaa4062 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -46,16 +46,16 @@ "custom.regex", ], - // third_party/ holds copies of release archives, which - // tools/scripts/updateThirdParty.py pins by version and sha256. Renovate - // changes the version; the pull request then needs the new digest and - // --update, which the third_party check of CI asks for. + // third_party/ holds copies of release archives, which MODULE.bazel pins by + // version and sha256. Renovate changes the version; the pull request then + // needs the new digest and //tools:third_party -- --update, which the + // third_party check of CI asks for. customManagers: [ { customType: "regex", - managerFilePatterns: ["/^tools/scripts/updateThirdParty\\.py$/"], + managerFilePatterns: ["/^MODULE\\.bazel$/"], matchStrings: [ - "# renovate: datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)( extractVersion=(?<extractVersion>\\S+))?\\s+\"version\": \"(?<currentValue>[^\"]+)\"", + "# renovate: datasource=(?<datasource>\\S+) depName=(?<depName>\\S+)( extractVersion=(?<extractVersion>\\S+))?\\s+\\w+_VERSION = \"(?<currentValue>[^\"]+)\"", ], }, ], diff --git a/.github/workflows/validate-header-guards.yml b/.github/workflows/validate-header-guards.yml index a8ba91ba..bceb79ae 100644 --- a/.github/workflows/validate-header-guards.yml +++ b/.github/workflows/validate-header-guards.yml @@ -19,31 +19,23 @@ jobs: with: persist-credentials: false - - name: Setup Dependencies - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0 with: - python-version: '3.12' - - # Every header is guarded with #pragma once, as the Progmasoft C++ Style - # asks; the amalgamation script relies on it. - - name: Check that every header starts its guard with pragma once - run: | - wrong_files=$(grep -rL --include='*.hpp' '^#pragma once' src/Progmasoft || true) - if [[ $wrong_files ]]; then - echo "Headers without #pragma once:" - echo $wrong_files - exit 1 - fi - - - name: Check that there are no duplicated filenames - run: | - ./tools/scripts/checkDuplicateFilenames.py - - - name: Check that all source files have the correct license header - run: | - ./tools/scripts/checkLicense.py + bazelisk-cache: true + repository-cache: true + + - name: Test the tools + run: bazel test //tools:tools_tests + env: + CC: clang + + - name: Check licenses, headers, file names, versions and the amalgamation + run: bazel run //tools:check + env: + CC: clang # third_party/ must be the pinned release archives, byte for byte. - name: Check that third_party matches its pinned archives - run: | - ./tools/scripts/updateThirdParty.py --check + run: bazel run //tools:third_party -- --check + env: + CC: clang diff --git a/MODULE.bazel b/MODULE.bazel index f8069a79..c4196428 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -5,6 +5,33 @@ bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "rules_license", version = "1.0.0") bazel_dep(name = "platforms", version = "1.0.0") +# The archives third_party/ holds copies of. Renovate changes a version; the +# pull request then needs the digest of the new archive and +# `bazelisk run //tools:third_party -- --update`, which CI asks for. +http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +# renovate: datasource=github-tags depName=ibireme/yyjson +YYJSON_VERSION = "0.13.0" + +http_archive( + name = "yyjson_archive", + build_file_content = 'exports_files(["src/yyjson.c", "src/yyjson.h"])', + sha256 = "34e0f62a2bc11ab20d601e8ca1cc2b2079503aa45119a19133d89d19b94a0fae", + strip_prefix = "yyjson-" + YYJSON_VERSION, + urls = ["https://github.com/ibireme/yyjson/archive/refs/tags/" + YYJSON_VERSION + ".tar.gz"], +) + +# renovate: datasource=github-tags depName=zeux/pugixml extractVersion=^v(?<version>.+)$ +PUGIXML_VERSION = "1.16" + +http_archive( + name = "pugixml_archive", + build_file_content = 'exports_files(["src/pugiconfig.hpp", "src/pugixml.cpp", "src/pugixml.hpp"])', + sha256 = "357bcab8877dc9943f355d3a72daba1b053238ba955f50fa81586afb65090219", + strip_prefix = "pugixml-" + PUGIXML_VERSION, + urls = ["https://github.com/zeux/pugixml/archive/refs/tags/v" + PUGIXML_VERSION + ".tar.gz"], +) + # rules_swift reaches the graph through protobuf and rules_apple. Up to 3.4.1 # its Windows autoconfiguration, which runs whenever swiftc.exe is on PATH, # writes a toolchain that indexes APPLE_PLATFORMS_CONSTRAINTS with an diff --git a/docs/contributing.md b/docs/contributing.md index ecccf68f..9f2cffc2 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -47,13 +47,28 @@ Meson, Xmake and Premake builds exist as well and are checked in CI. Before you push, run the repository checks: ``` -python tools/scripts/checkLicense.py -python tools/scripts/checkConvenienceHeaders.py -python tools/scripts/checkDuplicateFilenames.py +bazelisk run //tools:check ``` -A change to anything under `src/` also regenerates the single-file -distribution with `python tools/scripts/generateAmalgamatedFiles.py`. +It checks licenses, convenience headers, header guards, file names, that every +place states the same version, and that the single-file distribution is up to +date. A change to anything under `src/` regenerates that distribution: + +``` +bazelisk run //tools:amalgamate +``` + +The tools in `tools/` are C++17 and run through Bazel, with arguments after +`--`: + +| Tool | Does | +| --- | --- | +| `//tools:amalgamate` | writes the single-file distribution; `-- --check` only compares it | +| `//tools:check` | runs the repository checks | +| `//tools:third_party` | `-- --check` compares `third_party/` with the archives `MODULE.bazel` pins, `-- --update` writes it | +| `//tools:version` | prints the version; `-- --next` or `-- <version>` moves every place that states it, and the distribution | +| `//tools:release_notes` | prints a section of the release notes, of `-- <version>` or the current one | +| `//tools:repo_info` | reports the checkout and the tools on `PATH`; `-- --json` writes it as JSON | ## Two parts, two sets of rules @@ -71,8 +86,7 @@ AdditionRef-Progmasoft-Exception-2.0`, follows the 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 -header of its part. +`//tools:check` checks that every source file carries the header of its part. ## Tests @@ -88,7 +102,7 @@ comes with a test that fails without it. User documentation lives in `docs/`. A new page is linked from [the documentation index](Readme.md#top), and a page with sections gets a table -of contents; `python tools/scripts/updateDocumentToC.py` keeps them current. +of contents. A user-visible change gets a line in [the release notes](release-notes.md#top). diff --git a/docs/upstream-status.md b/docs/upstream-status.md index 0899e31d..93483fb3 100644 --- a/docs/upstream-status.md +++ b/docs/upstream-status.md @@ -36,7 +36,7 @@ backported, in upstream order, and the compatibility engine is now 3.16.1: Each applied without a conflict in the sources. The amalgamated distribution under `extras/` did conflict, because it is generated; it was generated again -from the sources of this repository with `generateAmalgamatedFiles.py`, which +from the sources of this repository with `//tools:amalgamate`, which also brought it up to date with fork changes it had not yet picked up. No fork-owned file under `src/Progmasoft` needed a change. diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp index df0d8f3c..5be0c78b 100644 --- a/extras/catch_amalgamated.cpp +++ b/extras/catch_amalgamated.cpp @@ -7,7 +7,6 @@ // SPDX-License-Identifier: BSL-1.0 // Catch3 v0.3.0.2, on the Catch2 v3.16.1 engine -// Generated: 2026-11-01 23:05:23.688401 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp index d6bc26f6..fad2f28c 100644 --- a/extras/catch_amalgamated.hpp +++ b/extras/catch_amalgamated.hpp @@ -7,7 +7,6 @@ // SPDX-License-Identifier: BSL-1.0 // Catch3 v0.3.0.2, on the Catch2 v3.16.1 engine -// Generated: 2026-11-01 23:05:23.296246 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. diff --git a/extras/catch_amalgamated_third_party.hpp b/extras/catch_amalgamated_third_party.hpp index 5cad151d..5a3aa21c 100644 --- a/extras/catch_amalgamated_third_party.hpp +++ b/extras/catch_amalgamated_third_party.hpp @@ -1,5 +1,4 @@ // Catch3 v0.3.0.2: yyjson and pugixml for catch_amalgamated.cpp -// Generated: 2026-11-01 23:05:24.053462 // ---------------------------------------------------------- // This file is an amalgamation of src/Progmasoft/Runner/Yyjson.inl, // src/Progmasoft/PugiXml.inl and the libraries they include from diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 40ed1358..b6b9b52c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,7 +33,7 @@ if(CATCH3_BUILD_SURROGATES) function(ExtractCatch3Headers OutArg) # The engine's headers are the ones that come from Catch2; the surrogates # check them at the language level of the build. - file(STRINGS "${CATCH_DIR}/tools/scripts/upstreamFiles.txt" upstreamFiles REGEX "^src/") + file(STRINGS "${CATCH_DIR}/tools/upstreamFiles.txt" upstreamFiles REGEX "^src/") get_target_property(targetSources Catch3 SOURCES) foreach(Source ${targetSources}) string(REGEX MATCH "^.*\\.hpp$" isHeader ${Source}) @@ -366,15 +366,6 @@ set_tests_properties(TagAlias PROPERTIES PASS_REGULAR_EXPRESSION "[1-9][0-9]* matching test\\(s\\)" ) -add_test(NAME CheckConvenienceHeaders - COMMAND - Python3::Interpreter ${CATCH_DIR}/tools/scripts/checkConvenienceHeaders.py -) -set_tests_properties(CheckConvenienceHeaders - PROPERTIES - LABELS "uses-python" -) - add_test(NAME "Benchmarking::SkipBenchmarkMacros" COMMAND $<TARGET_FILE:SelfTest> --no-history "Skip benchmark macros" diff --git a/third_party/pugixml/BUILD.bazel b/third_party/pugixml/BUILD.bazel index a73f10b7..120463bf 100644 --- a/third_party/pugixml/BUILD.bazel +++ b/third_party/pugixml/BUILD.bazel @@ -4,7 +4,7 @@ load("@rules_cc//cc:defs.bzl", "cc_library") # pugixml (MIT), the XML writer of the reports. -# The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +# The version is pinned in MODULE.bazel. Catch3 # compiles the library into one of its own translation units with # internal linkage, so this target only provides the files. cc_library( diff --git a/third_party/pugixml/CMakeLists.txt b/third_party/pugixml/CMakeLists.txt index 85113fa3..d6e6004d 100644 --- a/third_party/pugixml/CMakeLists.txt +++ b/third_party/pugixml/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 # pugixml (MIT), the XML writer of the reports. -# The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +# The version is pinned in MODULE.bazel. Catch3 # compiles the library into one of its own translation units with # internal linkage, so this target only provides the include directory. # Catch3 links it through $<BUILD_INTERFACE:...>; it is never installed. diff --git a/third_party/pugixml/meson.build b/third_party/pugixml/meson.build index 972ca1f1..b1897d87 100644 --- a/third_party/pugixml/meson.build +++ b/third_party/pugixml/meson.build @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 # pugixml (MIT), the XML writer of the reports. -# The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +# The version is pinned in MODULE.bazel. Catch3 # compiles the library into one of its own translation units with # internal linkage, so this only provides the include directory. pugixml_dep = declare_dependency( diff --git a/third_party/pugixml/premake5.lua b/third_party/pugixml/premake5.lua index ee9ebd81..999fae79 100644 --- a/third_party/pugixml/premake5.lua +++ b/third_party/pugixml/premake5.lua @@ -2,7 +2,7 @@ -- SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 -- pugixml (MIT), the XML writer of the reports. --- The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +-- The version is pinned in MODULE.bazel. Catch3 -- compiles the library into one of its own translation units with -- internal linkage, so the workspace only needs its directory. catch3_third_party = catch3_third_party or {} diff --git a/third_party/pugixml/xmake.lua b/third_party/pugixml/xmake.lua index 198b54b7..29b985b1 100644 --- a/third_party/pugixml/xmake.lua +++ b/third_party/pugixml/xmake.lua @@ -2,7 +2,7 @@ -- SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 -- pugixml (MIT), the XML writer of the reports. --- The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +-- The version is pinned in MODULE.bazel. Catch3 -- compiles the library into one of its own translation units with -- internal linkage, so this target only provides the files. target("catch3_pugixml") diff --git a/third_party/yyjson/BUILD.bazel b/third_party/yyjson/BUILD.bazel index e44d069c..6b791e0d 100644 --- a/third_party/yyjson/BUILD.bazel +++ b/third_party/yyjson/BUILD.bazel @@ -4,7 +4,7 @@ load("@rules_cc//cc:defs.bzl", "cc_library") # yyjson (MIT), the JSON reader and writer of the runner. -# The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +# The version is pinned in MODULE.bazel. Catch3 # compiles the library into one of its own translation units with # internal linkage, so this target only provides the files. cc_library( @@ -12,5 +12,8 @@ cc_library( hdrs = ["yyjson.h"], includes = ["."], textual_hdrs = ["yyjson.c"], - visibility = ["//src/Progmasoft:__pkg__"], + visibility = [ + "//src/Progmasoft:__pkg__", + "//tools:__pkg__", + ], ) diff --git a/third_party/yyjson/CMakeLists.txt b/third_party/yyjson/CMakeLists.txt index 77200553..30623718 100644 --- a/third_party/yyjson/CMakeLists.txt +++ b/third_party/yyjson/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 # yyjson (MIT), the JSON reader and writer of the runner. -# The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +# The version is pinned in MODULE.bazel. Catch3 # compiles the library into one of its own translation units with # internal linkage, so this target only provides the include directory. # Catch3 links it through $<BUILD_INTERFACE:...>; it is never installed. diff --git a/third_party/yyjson/meson.build b/third_party/yyjson/meson.build index b3683188..6a6566e8 100644 --- a/third_party/yyjson/meson.build +++ b/third_party/yyjson/meson.build @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 # yyjson (MIT), the JSON reader and writer of the runner. -# The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +# The version is pinned in MODULE.bazel. Catch3 # compiles the library into one of its own translation units with # internal linkage, so this only provides the include directory. yyjson_dep = declare_dependency( diff --git a/third_party/yyjson/premake5.lua b/third_party/yyjson/premake5.lua index 07f3b3c9..fc17e1bf 100644 --- a/third_party/yyjson/premake5.lua +++ b/third_party/yyjson/premake5.lua @@ -2,7 +2,7 @@ -- SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 -- yyjson (MIT), the JSON reader and writer of the runner. --- The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +-- The version is pinned in MODULE.bazel. Catch3 -- compiles the library into one of its own translation units with -- internal linkage, so the workspace only needs its directory. catch3_third_party = catch3_third_party or {} diff --git a/third_party/yyjson/xmake.lua b/third_party/yyjson/xmake.lua index 207ecf61..e4e9c58c 100644 --- a/third_party/yyjson/xmake.lua +++ b/third_party/yyjson/xmake.lua @@ -2,7 +2,7 @@ -- SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 -- yyjson (MIT), the JSON reader and writer of the runner. --- The version is pinned in tools/scripts/updateThirdParty.py. Catch3 +-- The version is pinned in MODULE.bazel. Catch3 -- compiles the library into one of its own translation units with -- internal linkage, so this target only provides the files. target("catch3_yyjson") diff --git a/tools/AmalgamateMain.cpp b/tools/AmalgamateMain.cpp new file mode 100644 index 00000000..c5e2218c --- /dev/null +++ b/tools/AmalgamateMain.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2026 Progmasoft. +// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 + +// bazelisk run //tools:amalgamate [-- --check] + +#include <iostream> +#include <string_view> + +#include "tools/Amalgamation.hpp" +#include "tools/Repository.hpp" + +int +main(int argc, char **argv) +{ + using namespace Progmasoft::Catch3::Tools; + + const bool check = argc == 2 && std::string_view{ argv[1] } == "--check"; + if (argc > 2 || (argc == 2 && !check)) + { + std::cerr << "usage: bazelisk run //tools:amalgamate [-- --check]\n"; + return 2; + } + const auto root = RepositoryRoot(); + if (!root) + { + std::cerr << "run this tool with bazelisk run\n"; + return 2; + } + Problems problems; + const auto amalgamation = GenerateAmalgamation(*root, problems); + if (problems.empty()) + { + if (check) + { + CheckAmalgamation(*root, amalgamation, problems); + } + else + { + WriteAmalgamation(*root, amalgamation, problems); + } + } + return Finish(problems); +} diff --git a/tools/Amalgamation.cpp b/tools/Amalgamation.cpp new file mode 100644 index 00000000..fc1d459a --- /dev/null +++ b/tools/Amalgamation.cpp @@ -0,0 +1,582 @@ +// Copyright (c) 2026 Progmasoft. +// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0 + +#include <algorithm> +#include <array> +#include <cctype> +#include <map> +#include <set> +#include <utility> +#include <vector> + +#include "tools/Amalgamation.hpp" + +namespace Progmasoft::Catch3::Tools +{ + namespace + { + namespace fs = std::filesystem; + + constexpr std::string_view kHeaderHead = R"( +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +)"; + + constexpr std::string_view kHeaderTail + = R"(// ---------------------------------------------------------- +// 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-2.0). The runner needs C++17. +// ---------------------------------------------------------- +)"; + + constexpr std::string_view kThirdPartyTail + = R"(// ---------------------------------------------------------- +// This file is an amalgamation of src/Progmasoft/Runner/Yyjson.inl, +// src/Progmasoft/PugiXml.inl and the libraries they include from +// third_party/. You probably shouldn't edit it directly. +// +// yyjson and pugixml keep their MIT licenses, stated in their text below; +// the rest is MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0. Only +// catch_amalgamated.cpp includes this file. +// ---------------------------------------------------------- +)"; + + // The comments at the top of each engine file. + constexpr std::array<std::string_view, 5> kCopyrightLines{ + "// Copyright Catch2 Authors\n", + "// Distributed under the Boost Software License, Version 1.0.\n", + "// (See accompanying file LICENSE.txt or copy at\n", + "// https://www.boost.org/LICENSE_1_0.txt)\n", + "// SPDX-License-Identifier: BSL-1.0\n", + }; + + constexpr std::string_view kUserConfig + = "Progmasoft/Catch3/UserConfig.hpp"; + + const std::map<std::string, std::string> & + ThirdPartyFiles() + { + static const auto *files = new std::map<std::string, std::string>{ + { "yyjson.c", "yyjson/yyjson.c" }, + { "yyjson.h", "yyjson/yyjson.h" }, + { "pugix |