mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 14:35:18 +00:00
* Drop stale LCOV_EXCL_LINE from the json_pointer out_of_range.410 throw The comment said the size_type overflow check in array_index() is only triggered on special platforms like 32-bit, and the throw was excluded from coverage. On 64-bit platforms the check is true for SIZE_MAX itself, and unit-json_pointer.cpp has asserted that case four times since #5395, so the line is executed in the coverage job. Reword the comment and remove the exclusion marker so the coverage report notices if the tests stop reaching it. Part of #5725 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Name all three C-array check aliases in the enum-macro NOLINTs NLOHMANN_JSON_SERIALIZE_ENUM(_STRICT) suppressed the c-array warning under modernize-avoid-c-arrays only, but clang-tidy emits the same diagnostic under the aliases cppcoreguidelines-avoid-c-arrays and hicpp-avoid-c-arrays too. Any user running those checks got a false positive at every macro expansion, and our own tests needed a local NOLINT at each call site to work around it. Name all three aliases in the four macro comments instead, and drop the now-redundant c-array names from the five test call-site NOLINTs. Comment-only change; behavior, the public API, and the ABI do not change. Ran make amalgamate. Part of #5725 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Include doctest as a SYSTEM directory instead of disabling warnings for all tests test_main added -Wno-deprecated and -Wno-float-equal as PUBLIC compile options for every non-MSVC compiler, so they were applied to every translation unit, library headers included, and silenced the CI warnings meant to check the library's own -Wfloat-equal pragmas. The only code that actually needed the suppression was the vendored doctest.h, which was included as a normal (non-SYSTEM) directory. Include thirdparty/doctest as SYSTEM for test_main, matching what tests/abi/CMakeLists.txt already does, and drop the two suppressions from both targets. Verified locally that unit-comparison, unit-conversions and unit-constructor1 compile clean with -Werror -Weverything and doctest as -isystem, and that CMake still configures with JSON_BuildTests=ON. Part of #5725 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Remove the no-op ci_clang_analyze target ci_clang_analyze configured the build with the real compiler and only then wrapped ninja with scan-build. scan-build intercepts compiles by overriding CC/CXX, but build.ninja already had the compiler path baked in from the configure step, so every run bypassed the analyzer: CI logs show "No bugs found" after a normal build, never an analysis. The job also used Debian's frozen clang-tools-14 rather than the image's own clang, and CLANG_ANALYZER_CHECKS still named three valist.* checkers that current clang merged into security.VAList. ci_clang_tidy already runs every clang-analyzer-* check (via .clang-tidy's "Checks: '*'") with warnings as errors, so nothing is lost by removing the dead job. Delete ci_clang_analyze, CLANG_ANALYZER_CHECKS and the SCAN_BUILD_TOOL lookup from cmake/ci.cmake, drop it from the ubuntu.yml ci_static_analysis_clang matrix, and drop the now-unused clang-tools apt package (iwyu stays for ci_single_binaries). Reword quality_assurance.md and assurance_case.md, which described the dead job as a working control, to say the Clang Static Analyzer checks run through clang-tidy. Verified that `cmake -DJSON_CI=ON` still configures cleanly and that ci_clang_analyze no longer appears in the generated build or in any CMake/workflow file. Part of #5725 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Re-enable portability-template-virtual-member-function; remove redundant forwards .clang-tidy disabled three checks "to get the CI going" (#4489, 2024-11-13): portability-template-virtual-member-function, bugprone-use-after-move and its alias hicpp-invalid-access-moved. portability-template-virtual-member-function only flagged output_stream_adapter::write_character/write_characters; annotate both with NOLINT and re-enable the check. bugprone-use-after-move flagged several double forwards that have no effect at runtime: - from_json.hpp calls std::forward<BasicJsonType>(j).at(Idx) inside pack expansions; at() has no ref-qualified overloads and always returns an lvalue reference, so the forward is a no-op. Replace with plain j.at(Idx) in all four places. - the move constructor forwards the whole object to its base class and then reads other's members. That is item 9 of #5724 (together with its cppcheck suppressions) and is left to that change. - input_adapters.hpp forwards the container twice on purpose, so the begin/end iterator types match adapter_type; annotate with NOLINT and a comment instead of changing behavior. The check still flags the move constructor (see above) and two sites in at(KeyType&&) (both overloads, json.hpp, in the throw's string_t(std::forward<KeyType>(key)) after find(std::forward<KeyType>(key))). Open PR #5689 rewrites that hunk, so bugprone-use-after-move (and hicpp-invalid-access-moved) stay disabled for now, with a comment explaining why; re-enable them once #5689 and the #5724 move-constructor change have landed. Also resolve the portability-avoid-pragma-once TODO: single_include never has #pragma once (amalgamate.py strips it) and every supported compiler accepts it in include/, so keep it disabled with an explanatory comment instead of a TODO. Fix the stale "json.hpp, around line 1265" comment in unit-class_parser.cpp, which now points at the move constructor's actual line. Behavior, the public API and the ABI do not change. Verified with clang-tidy 22.1.8 that portability-template-virtual-member-function now reports nothing, that bugprone-use-after-move/ hicpp-invalid-access-moved report only the known at(KeyType&&) and move-constructor sites, and that unit-custom-base-class, unit-constructor1, unit-conversions, unit-element_access2, unit-class_parser and unit-diagnostic-positions (JSON_DIAGNOSTIC_POSITIONS=1) compile under ASan/UBSan and pass with the same assertion counts as before. Ran make amalgamate. Part of #5725 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix stale and malformed NOLINT comments json_sax.hpp named "-warnings-as-errors" in the NOLINT list on the two JSON_ASSERT(false) lines; that is the suffix clang-tidy appends to a diagnostic tag under WarningsAsErrors, not a check name, and every other JSON_ASSERT(false) omits it. unit-capacity.cpp carried 30 "// NOLINT(misc-const-correctness)" comments on "json j = ...;" declarations that are all used with non-const members afterwards, so the check has nothing to report there. unit-constructor2.cpp used a blanket "// NOLINT: access after move is OK here" on a use-after-move that hides every check on the line; naming bugprone-use-after-move and hicpp-invalid-access-moved keeps the intent once those checks are re-enabled (#5724). Signed-off-by: Niels Lohmann <mail@nlohmann.me> #5725 item 10 * Remove stale .clang-tidy entries -google-runtime-references disabled a check that neither clang-tidy 22.1.8 nor 23.1.2 lists under --list-checks -checks='*'; it was removed upstream. The commented-out HeaderFilterRegex line has been unused since the active HeaderFilterRegex was introduced in #2561 (2021). Signed-off-by: Niels Lohmann <mail@nlohmann.me> #5725 item 11 * Remove the GCC C++20 -Wignored-attributes pragma in json.hpp The pragma (added in #5164) claimed to work around the C++ modules redefinition errors of #5103, but #5103 is about hard errors (e.g. "redefinition of std::__is_constant_evaluated()", conflicting std::integral_constant) that ignoring a warning cannot suppress; they are traced to GCC PR 124430 and reproduce with <map> or <string> instead of json.hpp too. A GCC 16.2 -std=gnu++20 -fmodules build following #5103's repro steps still fails with the pragma in place, and a build of all test TUs with GCC_CXXFLAGS (which enable -Wignored-attributes) and the pragma removed produces no such warning. The block only hid a warning class from GCC C++20 users while suggesting #5103 was handled. Overlaps #5610, whose hunks touch the closing half of this pragma to insert the json_literals.hpp include. Signed-off-by: Niels Lohmann <mail@nlohmann.me> #5725 item 9 * Fix stale doxygen comments hidden by the -Wdocumentation pragma macro_scope.hpp ignores -Wdocumentation and -Wdocumentation-unknown-command for the whole library, which also hides genuine documentation mistakes: - detail::unescape() documented "@return unescaped string" but returns void and unescapes its argument in place; reworded to "@param[in,out] s string to unescape in place" and dropped the bogus @return. - basic_json::get()'s copy-conversion overload wrote "converted to @tparam ValueType" inside @return, which Doxygen and Clang parse as a second, malformed @tparam; changed to "@a ValueType", matching the two other get() overloads a few lines above that already use it. This narrows the gap the -Wdocumentation pragma needs to cover; fully replacing the Doxygen-only commands it also hides (item 2c) is left for after #5267. Signed-off-by: Niels Lohmann <mail@nlohmann.me> #5725 item 2 * Fix -Wextra-semi-stmt at its actual source, not assert() clang_flags.cmake blamed the global -Wno-extra-semi-stmt on assert(), but assert() expands to an expression under glibc and libc++ and does not trigger this warning. unit-assert_macro.cpp overrides JSON_ASSERT with "{if (!(x)) ++assert_counter; }", a bare block followed by a semicolon at every JSON_ASSERT(...) call site in the library; that was the actual source of 151 of the 208 -Wextra-semi-stmt sites found in a Clang 22 -Weverything sweep of the test suite with the flag removed. Switched to the standard do/while(false) macro idiom, which does not expand to a statement-plus-semicolon, and corrected the comment to name the remaining source instead: vendored Doctest's CAPTURE(x) shim, which already ends in a semicolon. Verified with clang++ -Wextra-semi-stmt (plus the file's other CI ignores) that unit-assert_macro.cpp now compiles without any -Wextra-semi-stmt diagnostic. Signed-off-by: Niels Lohmann <mail@nlohmann.me> #5725 item 8 (step 1 of 2; step 2 covers the CAPTURE() call sites) * Drop the redundant semicolon from CAPTURE() call sites; remove -Wno-extra-semi-stmt doctest_compatibility.h defines CAPTURE(x) as DOCTEST_CAPTURE(x); (with a trailing semicolon baked into the macro), specifically so call sites do not need to add one themselves; most of the ~267 call sites already follow that convention. The remaining 64 call sites across 20 files wrote "CAPTURE(x);" anyway, turning into a statement plus an empty statement and triggering -Wextra-semi-stmt. Dropped the redundant semicolon at each of those sites. With item 6 having already made vendored Doctest a SYSTEM include, and this the last known source of -Wextra-semi-stmt findings, removed the flag from clang_flags.cmake entirely. Verified with clang++ -Wextra-semi-stmt (plus the file's other CI ignores) that all 20 touched files, plus a file with no CAPTURE() use (unit-json_pointer.cpp), compile without any -Wextra-semi-stmt diagnostic. Signed-off-by: Niels Lohmann <mail@nlohmann.me> #5725 item 8 (step 2 of 2) * Switch ci_static_analysis_clang off the frozen LLVM 22 dev image ubuntu.yml pinned the clang-tidy/clang-tidy-sanitizer/single-binaries job to silkeh/clang:dev, a tag last pushed 2026-02-18 that reports "clang version 22.0.0 (...+20251015...)", a pre-release snapshot from before the LLVM 22 release; the maintainer now updates dev-unstable, 22, and latest instead. Switched to silkeh/clang:22, matching the other clang jobs on :latest. Verified with clang-tidy 22.1.8 (the image's actual version) against this repository's .clang-tidy and library headers what the release image newly reports compared to :dev: - readability-redundant-typename fires at ~250 sites across the _cpp20-relevant conversion/to_chars headers; the library targets C++11 and keeps the typenames, so the check is disabled in .clang-tidy, matching how the file already handles checks that don't fit a C++11 codebase. - misc-anonymous-namespace-in-header fires on the two anonymous namespaces in from_json.hpp and to_json.hpp; added the alias to their existing NOLINT (cert-dcl59-cpp, fuchsia-header-anon-namespaces, google-build-namespaces). - bugprone-std-namespace-modification fires on every addition to namespace std: the std::hash, std::formatter and std::swap overloads in json.hpp, and the std::tuple_size/std::tuple_element specializations in iteration_proxy.hpp (this last file is not named in #5725's item 5, found by actually running clang-tidy 22.1.8 against the current tree). All six are legal, deliberate additions to namespace std (explicit/partial specializations of std types, or the pre-C++20 std::swap overload); annotated each with the check name next to its existing cert-dcl58-cpp NOLINT. - modernize-avoid-c-style-cast reported nothing new. Also added clang++-22/21, clang-tidy-22/21, g++-16 and gcov-16 to the find_program search lists in ci.cmake so a local "maximal warnings" configure prefers the current toolchain version over an older one on PATH. #5725 item 5 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Regenerate cmake/gcc_flags.cmake for GCC 16.2.0 GCC_CXXFLAGS was generated for GCC 15.1.0, but ci_test_gcc and ci_test_gcc_cxx{11..26} now run in gcc:latest, currently GCC 16.2.0, so the "maximal warnings" job was missing warnings introduced since 15.1.0 while carrying entries GCC 16 treats as duplicates or no-ops. Regenerated with https://github.com/nlohmann/gcc_flags (patched locally to not crash on an option whose "-x c++ <opt> -" probe fails before it reads stdin, e.g. -Wabi=; the tool otherwise raises BrokenPipeError instead of recording the option as an error) run against g++ 16.2.0 in the official gcc:16 Docker image, keeping the documented -Wno-* exclusions and the same alphabetical placement scheme as before. Also added three GCC 16 warnings the generator cannot discover on its own because it only probes value ranges/lists it finds in the -Q option name itself, not in the enum choices --help=warnings documents separately: - -Wbidi-chars=any, -Wleading-whitespace=spaces: manually verified these compile cleanly with g++ 16.2.0. - -Wstrict-flex-arrays: deliberately NOT added, unlike the other two. Without -fstrict-flex-arrays (which the library does not enable, as it would change codegen for flexible array members), GCC prints "'-Wstrict-flex-arrays' is ignored when '-fstrict-flex-arrays' is not present" on every translation unit, and under our -Werror that note itself aborts the build. This differs from the harmless no-op warnings already kept in the file (-Whsa, -Wsynth, -Wunreachable-code, -Wunsafe-loop-optimizations), which emit nothing; #5725 item 7 named -Wstrict-flex-arrays as one of the flags GCC 16 adds, but did not anticipate this failure mode. Verified: compiled the library header and a representative set of test translation units (including ones touched by items 1, 3, 8, 9, 10 of this issue) with the regenerated GCC_CXXFLAGS plus -Werror under g++ 16.2.0 at -std=c++11 through -std=c++26, with zero warnings; ran the full local test suite (129/129 passing, unrelated to this compiler) as a regression check. CI must still confirm the actual ci_test_gcc / ci_test_standards_gcc targets end to end, since this was verified with direct g++ invocations rather than through the CMake/ CXXFLAGS environment-variable plumbing in ci.cmake. #5725 item 7 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Avoid std::basic_string<CharType> for non-character output_adapter CharType output_adapter<CharType, StringType> defaulted StringType to std::basic_string<CharType>, and (with JSON_NO_IO undefined) always declared a std::basic_ostream<CharType>&-taking constructor. For CharType with no non-deprecated std::char_traits specialization (only std::uint8_t is ever used this way, by the binary writers), simply naming either type - as an unused default template argument, or as an unused, never-called constructor's parameter type - instantiates std::char_traits<CharType> merely to name it, which some standard libraries mark deprecated: with the library-wide -Wdocumentation pragma (item 2's other half, left for a later commit) temporarily removed, an Apple clang 21 / libc++ TU calling json::to_cbor(j, vec) with std::vector<std::uint8_t>& got one -Wdeprecated-declarations warning per binary writer at the old output_adapters.hpp:193. Replaced the eager std::basic_string<CharType> / std::basic_ostream <CharType> defaults with a bool-tagged partial specialization (not std::conditional, which requires naming both branches' types up front regardless of which is selected, reproducing the same warning) that only ever names std::basic_string<CharType> / std::basic_ostream <CharType> when CharType is actually one of char, wchar_t, char16_t, char32_t, or (with __cpp_lib_char8_t) char8_t. For any other CharType, output_adapter's StringType and ostream-constructor parameter fall back to two distinct empty placeholder types, kept distinct so the two constructor overloads do not collide into a single redeclaration. Public API / behavior: passing a std::basic_string<std::uint8_t>& or std::basic_ostream<std::uint8_t>& directly to a binary writer's output_adapter now fails to compile instead of compiling with a deprecation warning; this was neither documented nor tested. All documented uses (std::vector<CharType>, std::basic_ostream<CharType> and StringType for character CharType) are unaffected. Verified with Apple clang 21 / libc++, with the two -Wdocumentation* "ignored" pragma lines in macro_scope.hpp temporarily removed and -std=c++11/c++20 plus the project's -Weverything flag set: calling to_cbor/to_msgpack/to_ubjson/to_bjdata/to_bson/to_bon8 on a std::vector<std::uint8_t> now produces no char_traits<unsigned char> (or any other) deprecation warning, while the char-based string- and ostream-adapter paths, and a to_cbor/from_cbor round trip, still compile and run correctly; also verified with GCC 16.2.0. Ran the full local test suite, including the binary-format unit tests (unit-cbor, unit-msgpack, unit-ubjson, unit-bjdata, unit-bson, unit-bon8, unit-binary_writer_sinks, unit-binary_formats, unit-custom-binary-type): 129/129 passing. #5725 item 2 (step a) Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Remove the library-wide -Wdocumentation pragma; fix what it hid macro_scope.hpp / macro_unscope.hpp pushed and popped a Clang diagnostic region over the entire library that ignored -Wdocumentation and -Wdocumentation-unknown-command. Removed both pragmas and fixed every finding a full -Wdocumentation (which implies -Wdocumentation-unknown-command and -Wdocumentation-deprecated-sync) build reports, so the library now compiles clean under Clang's documentation checks without a blanket suppression. Overlaps #5267, which is still open and edits a nearby doc block (json.hpp's get()/get_impl() @return, already fixed in the item 2 step (b) commit of this branch); this commit does not touch that block again. Unknown Doxygen alias commands (Doxyfile removed in #3071, so these were never rendered by anything) rewritten as plain prose, keeping the same information: - @requirement REQ-JSON-01 / REQ-JSON-02 (iter_impl.hpp, json_reverse_iterator.hpp): now "This class satisfies the following concept requirements (REQ-JSON-0N):". - @liveexample{prose,example-id} (three sites in json.hpp): kept the prose, dropped the command wrapper and the trailing example-id (docs/mkdocs/docs/examples/*.cpp still exist and are used directly by the rendered docs, not through this in-header alias) and unescaped the "\," commas that were only needed for the old alias's comma-separated argument syntax. - @complexity X (json.hpp x4, json_pointer.hpp x2, serializer.hpp x1): now "Complexity: X". Backslash sequences Clang's comment lexer tried to parse as commands, escaped to render as literal backslashes: - lexer.hpp get_codepoint(): two `\u` occurrences. - binary_reader.hpp get_bson_cstr() / get_bson_cstr_bulk(): two `\x00` occurrences. - serializer.hpp: three `\uXXXX` occurrences (constructor @param, append_codepoint_to_string_buffer() @brief, and the ensure_ascii member comment). One finding remained after all of the above: Clang reports "declaration is marked with '@deprecated' command but does not have a deprecation attribute" on the deprecated sax_parse(span_input_adapter&&, ...) overload, even though JSON_HEDLEY_DEPRECATED_FOR does expand to __attribute__((deprecated(...))) for Clang. Several isolated reproductions of this exact declaration shape - doc comment, template<>, two stacked __attribute__ macros, an overload set sharing the name - did not reproduce the warning, so this looks like a Clang comment/declaration-association quirk specific to this overload inside the much larger basic_json class template, not an actual documentation defect. Rather than keep the pragma library-wide for one Clang false positive, added a tightly scoped -Wdocumentation-deprecated-sync push/pop around just that overload. Verified with Apple clang 21 and the project's actual -Weverything flag set (cmake/clang_flags.cmake) on the full header at -std=c++11 and -std=c++20: zero -Wdocumentation* diagnostics. Also compiled clean with GCC 16.2.0 (the pragmas are already __clang__-gated, so this only confirms no unrelated breakage). Ran make check-amalgamation and the full local test suite: 129/129 passing. #5725 item 2 (step c) Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Take the JSON value by const reference in the array and tuple from_json paths Review feedback on #5737 (gregmarr): once the no-op std::forward calls are gone, the forwarding references have no purpose. from_json_fn passes the value as const BasicJsonType&, so these functions were only ever instantiated with a const lvalue anyway. The std::array, std::pair and std::tuple overloads of from_json and their helpers now take const BasicJsonType& and pass j on unchanged. Because the deduced BasicJsonType is now the plain type, tuple_type and the static_assert name const BasicJsonType& explicitly, so the reference checks are unchanged: get<std::tuple<const std::string&>>() still works, and get<std::tuple<std::string&>>() still fails the same static_assert. from_json_tuple_get_impl keeps its forwarding reference, since tuple_type calls it through std::declval. Behavior, the public API and the ABI do not change. unit-conversions, unit-constructor1, unit-udt, unit-udt_macro, unit-regression1/2/3, unit-deserialization, unit-noexcept, unit-items, unit-allocator, unit-custom-object-type, unit-ordered_json2 and unit-brace-init-copy-semantics pass at C++11, C++17 and C++20 with unchanged assertion counts. Ran make amalgamate. Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
902 lines
50 KiB
CMake
902 lines
50 KiB
CMake
# number of parallel jobs for CTest
|
|
set(N 10)
|
|
|
|
###############################################################################
|
|
# Needed tools.
|
|
###############################################################################
|
|
|
|
include(FindPython3)
|
|
find_package(Python3 COMPONENTS Interpreter)
|
|
|
|
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-22 clang++-21 clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
|
|
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
|
|
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
|
|
|
|
find_program(CLANG_TIDY_TOOL NAMES clang-tidy-22 clang-tidy-21 clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
|
|
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
|
|
message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
|
|
|
|
message(STATUS "🔖 CMake ${CMAKE_VERSION} (${CMAKE_COMMAND})")
|
|
|
|
find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++ g++-16 g++-15 g++-14 g++-13 g++-12 g++-11 g++-10)
|
|
execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
|
|
message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
|
|
|
|
find_program(GCOV_TOOL NAMES gcov-HEAD gcov gcov-16 gcov-15 gcov-14 gcov-13 gcov-12 gcov-11 gcov-10)
|
|
execute_process(COMMAND ${GCOV_TOOL} --version OUTPUT_VARIABLE GCOV_TOOL_VERSION ERROR_VARIABLE GCOV_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCOV_TOOL_VERSION "${GCOV_TOOL_VERSION}")
|
|
message(STATUS "🔖 GCOV ${GCOV_TOOL_VERSION} (${GCOV_TOOL})")
|
|
|
|
find_program(GIT_TOOL NAMES git)
|
|
execute_process(COMMAND ${GIT_TOOL} --version OUTPUT_VARIABLE GIT_TOOL_VERSION ERROR_VARIABLE GIT_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GIT_TOOL_VERSION "${GIT_TOOL_VERSION}")
|
|
message(STATUS "🔖 Git ${GIT_TOOL_VERSION} (${GIT_TOOL})")
|
|
|
|
find_program(IWYU_TOOL NAMES include-what-you-use iwyu)
|
|
execute_process(COMMAND ${IWYU_TOOL} --version OUTPUT_VARIABLE IWYU_TOOL_VERSION ERROR_VARIABLE IWYU_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
|
|
message(STATUS "🔖 include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
|
|
|
|
# CMake's CXX_INCLUDE_WHAT_YOU_USE launcher runs IWYU during the normal compile step (useful to see
|
|
# diagnostics inline), but CMake's own __run_co_compile wrapper does not propagate the launched
|
|
# tool's exit code to the build, so IWYU's own "-Xiwyu --error" cannot fail that step (verified: a
|
|
# deliberately-unused #include in a header still lets `cmake --build` finish with exit code 0).
|
|
# iwyu_tool.py, which ships with IWYU, reads compile_commands.json and does return a non-zero exit
|
|
# code for any analyzed file with findings; ci_single_binaries uses it to actually fail on findings.
|
|
find_program(IWYU_TOOL_PY NAMES iwyu_tool iwyu_tool.py iwyu-tool)
|
|
|
|
find_program(INFER_TOOL NAMES infer)
|
|
execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
|
|
message(STATUS "🔖 Infer ${INFER_TOOL_VERSION} (${INFER_TOOL})")
|
|
|
|
find_program(LCOV_TOOL NAMES lcov)
|
|
execute_process(COMMAND ${LCOV_TOOL} --version OUTPUT_VARIABLE LCOV_TOOL_VERSION ERROR_VARIABLE LCOV_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" LCOV_TOOL_VERSION "${LCOV_TOOL_VERSION}")
|
|
message(STATUS "🔖 LCOV ${LCOV_TOOL_VERSION} (${LCOV_TOOL})")
|
|
|
|
find_program(NINJA_TOOL NAMES ninja)
|
|
execute_process(COMMAND ${NINJA_TOOL} --version OUTPUT_VARIABLE NINJA_TOOL_VERSION ERROR_VARIABLE NINJA_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
|
|
message(STATUS "🔖 Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
|
|
|
|
find_program(VALGRIND_TOOL NAMES valgrind)
|
|
execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
|
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
|
|
message(STATUS "🔖 Valgrind ${VALGRIND_TOOL_VERSION} (${VALGRIND_TOOL})")
|
|
|
|
find_program(GENHTML_TOOL NAMES genhtml)
|
|
find_program(PLOG_CONVERTER_TOOL NAMES plog-converter)
|
|
find_program(PVS_STUDIO_ANALYZER_TOOL NAMES pvs-studio-analyzer)
|
|
find_program(SCAN_BUILD_TOOL NAMES scan-build-15 scan-build-14 scan-build-13 scan-build-12 scan-build-11 scan-build)
|
|
|
|
# the individual source files
|
|
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp)
|
|
|
|
###############################################################################
|
|
# Thorough check with recent compilers
|
|
###############################################################################
|
|
|
|
include(clang_flags)
|
|
include(gcc_flags)
|
|
|
|
add_custom_target(ci_test_gcc
|
|
COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with GCC using maximal warning flags"
|
|
)
|
|
|
|
add_custom_target(ci_test_clang
|
|
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with Clang using maximal warning flags"
|
|
)
|
|
|
|
###############################################################################
|
|
# Different C++ Standards.
|
|
###############################################################################
|
|
|
|
foreach(CXX_STANDARD 11 14 17 20 23 26)
|
|
add_custom_target(ci_test_gcc_cxx${CXX_STANDARD}
|
|
COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-DJSON_TestStandards=${CXX_STANDARD}
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with GCC for C++${CXX_STANDARD}"
|
|
)
|
|
|
|
add_custom_target(ci_test_clang_cxx${CXX_STANDARD}
|
|
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-DJSON_TestStandards=${CXX_STANDARD}
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
|
|
)
|
|
|
|
# pass -stdlib=libc++ through CXXFLAGS: an explicit -DCMAKE_CXX_FLAGS would make CMake ignore CXXFLAGS
|
|
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
|
|
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS};-stdlib=libc++" ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-DJSON_TestStandards=${CXX_STANDARD}
|
|
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
|
|
)
|
|
endforeach()
|
|
|
|
###############################################################################
|
|
# Disable exceptions.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_noexceptions
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noexceptions
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noexceptions
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_noexceptions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with exceptions switched off"
|
|
)
|
|
|
|
###############################################################################
|
|
# Disable implicit conversions.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_noimplicitconversions
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_ImplicitConversions=OFF
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noimplicitconversions
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noimplicitconversions
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_noimplicitconversions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with implicit conversions switched off"
|
|
)
|
|
|
|
###############################################################################
|
|
# Enable improved diagnostics.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_diagnostics
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_Diagnostics=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostics
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostics
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostics && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with improved diagnostics enabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Enable diagnostic positions support.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_diagnostic_positions
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_Diagnostic_Positions=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostic_positions
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostic_positions
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostic_positions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with diagnostic positions enabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Enable legacy discarded value comparison.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_legacycomparison
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_LegacyDiscardedValueComparison=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_legacycomparison
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_legacycomparison
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_legacycomparison && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with legacy discarded value comparison enabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Validate UTF-8 with simdutf.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_simdutf
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_TestSimdutf=ON
|
|
# simdutf needs C++17, so the library falls back to its scalar validator
|
|
# below that: build the suite at C++11 to cover the fallback with the macro
|
|
# defined, and at C++17 to run every test against simdutf itself
|
|
"-DJSON_TestStandards=11\;17"
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_simdutf
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_simdutf
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_simdutf && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with simdutf UTF-8 validation enabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Enable strict NUL-byte handling.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_strict_nul_handling
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_StrictNulHandling=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_strict_nul_handling
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_strict_nul_handling
|
|
# unit-testsuites contains a fixture (a "1e308" test value) that relies on the
|
|
# legacy NUL-as-end-of-input behavior this macro disables; exclude it here, as
|
|
# it is expected to fail under strict NUL handling and is out of scope for it
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_strict_nul_handling && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure -E "test-testsuites"
|
|
COMMENT "Compile and test with strict NUL-byte handling enabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Disable global UDLs.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_noglobaludls
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_GlobalUDLs=OFF
|
|
-DCMAKE_CXX_FLAGS=-DJSON_TEST_NO_GLOBAL_UDLS
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noglobaludls
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noglobaludls
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_noglobaludls && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with global UDLs disabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Disable enum serialization.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_disableenumserialization
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_DisableEnumSerialization=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_disableenumserialization
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_disableenumserialization
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_disableenumserialization && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with enum serialization disabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Disable conversion from a one-element tuple of a JSON reference.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_disabletuplereferenceconversion
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_DisableTupleReferenceConversion=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with tuple reference conversion disabled"
|
|
)
|
|
|
|
###############################################################################
|
|
# Skip the multiple-inclusion library version check.
|
|
###############################################################################
|
|
|
|
# tests/src/skip_library_version_check.cpp deliberately simulates a scenario
|
|
# (mixing two differently-versioned inclusions of the library in one
|
|
# translation unit) that unavoidably triggers the compiler's own "macro
|
|
# redefined" warning, so -- unlike the ci_test_* targets above -- it is
|
|
# compiled directly here, with a modest warning set, instead of being folded
|
|
# into the library's own -Weverything/-Werror unit test matrix.
|
|
add_custom_target(ci_test_skiplibraryversioncheck
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/skip_library_version_check
|
|
COMMAND ${CMAKE_CXX_COMPILER} -std=c++11 -Wall -Wextra
|
|
-I${PROJECT_SOURCE_DIR}/include
|
|
${PROJECT_SOURCE_DIR}/tests/src/skip_library_version_check.cpp
|
|
-o ${PROJECT_BINARY_DIR}/skip_library_version_check/skip_library_version_check
|
|
COMMAND ${PROJECT_BINARY_DIR}/skip_library_version_check/skip_library_version_check
|
|
COMMENT "Compile and run a translation unit simulating a mismatched library version, with JSON_SKIP_LIBRARY_VERSION_CHECK defined"
|
|
)
|
|
|
|
###############################################################################
|
|
# Disable thread-local storage.
|
|
###############################################################################
|
|
|
|
# Without thread-local storage, copying and comparing cannot bound their
|
|
# descent and handle every object and array without the call stack. Those paths
|
|
# are otherwise only reached by values nested deeper than the bound, so this
|
|
# target is what runs the whole test suite through them.
|
|
add_custom_target(ci_test_no_thread_local
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON
|
|
-DCMAKE_CXX_FLAGS=-DJSON_NO_THREAD_LOCAL
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_no_thread_local
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_no_thread_local
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_no_thread_local && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test without thread-local storage"
|
|
)
|
|
|
|
###############################################################################
|
|
# Coverage.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_coverage
|
|
COMMAND CXX=g++ ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage"
|
|
-DJSON_BuildTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
|
|
COMMAND CXX=g++ ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="-m32;--coverage;-fprofile-arcs;-ftest-coverage"
|
|
-DJSON_BuildTests=ON -DJSON_32bitTest=ONLY
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage32
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage32
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage32 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
|
|
COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc branch_coverage=1 --rc geninfo_unexecuted_blocks=1 --ignore-errors mismatch --ignore-errors unused
|
|
COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc branch_coverage=1 --ignore-errors unused
|
|
COMMAND ${CMAKE_SOURCE_DIR}/tests/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept
|
|
COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept
|
|
|
|
COMMENT "Compile and test with coverage"
|
|
)
|
|
|
|
###############################################################################
|
|
# Sanitizers.
|
|
###############################################################################
|
|
|
|
set(CLANG_CXX_FLAGS_SANITIZER "-g -O1 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer -fno-sanitize-recover=all -fno-sanitize=unsigned-integer-overflow -fno-sanitize=unsigned-shift-base")
|
|
|
|
add_custom_target(ci_test_clang_sanitizer
|
|
COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXX_FLAGS_SANITIZER} ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_sanitizer
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_sanitizer
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_sanitizer && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with sanitizers"
|
|
)
|
|
|
|
###############################################################################
|
|
# Check if header is amalgamated and sources are properly indented.
|
|
###############################################################################
|
|
|
|
# Same file set as .github/workflows/check_amalgamation.yml, so a direct push to develop/master/release/*
|
|
# (which only this CMake target checks, not the pull_request-only workflow) is held to the same standard.
|
|
file(GLOB_RECURSE INDENT_FILES
|
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp
|
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cu
|
|
${PROJECT_SOURCE_DIR}/include/*.hpp
|
|
${PROJECT_SOURCE_DIR}/include/*.cpp
|
|
${PROJECT_SOURCE_DIR}/include/*.cu
|
|
${PROJECT_SOURCE_DIR}/tests/*.hpp
|
|
${PROJECT_SOURCE_DIR}/tests/*.cpp
|
|
${PROJECT_SOURCE_DIR}/tests/*.cu
|
|
)
|
|
list(FILTER INDENT_FILES EXCLUDE REGEX "/tests/thirdparty/|/tests/abi/include/nlohmann/")
|
|
|
|
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
|
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
|
add_custom_target(ci_test_amalgamation
|
|
COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~
|
|
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
|
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
|
COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
|
|
COMMAND cp ${PROJECT_SOURCE_DIR}/BUILD.bazel ${PROJECT_SOURCE_DIR}/BUILD.bazel~
|
|
|
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
|
|
COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
|
|
COMMAND venv_astyle/bin/astyle --version
|
|
|
|
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
|
|
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
|
COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
|
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
|
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake
|
|
|
|
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
|
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
|
COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
|
|
COMMAND diff ${PROJECT_SOURCE_DIR}/BUILD.bazel~ ${PROJECT_SOURCE_DIR}/BUILD.bazel
|
|
|
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
|
|
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
|
|
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
|
COMMENT "Check amalgamation, formatting, and BUILD.bazel"
|
|
)
|
|
|
|
###############################################################################
|
|
# Build and test using the amalgamated header
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_single_header
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_MultipleHeaders=OFF -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_single_header
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_single_header
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_single_header && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test single-header version"
|
|
)
|
|
|
|
###############################################################################
|
|
# Valgrind.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_valgrind
|
|
COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_Valgrind=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_valgrind
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_valgrind
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_valgrind && ${CMAKE_CTEST_COMMAND} -L valgrind --parallel ${N} --output-on-failure
|
|
COMMENT "Compile and test with Valgrind"
|
|
)
|
|
|
|
###############################################################################
|
|
# Check code with Clang Static Analyzer.
|
|
###############################################################################
|
|
|
|
set(CLANG_ANALYZER_CHECKS "nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
|
|
|
|
add_custom_target(ci_clang_analyze
|
|
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} --use-analyzer=${CLANG_TOOL} -analyze-headers --status-bugs -o ${PROJECT_BINARY_DIR}/report ninja
|
|
COMMENT "Check code with Clang Analyzer"
|
|
)
|
|
|
|
###############################################################################
|
|
# Check code with Cppcheck.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_cppcheck
|
|
COMMAND mkdir -p cppcheck
|
|
COMMAND clang -dM -E -x c++ -std=c++11 ${CMAKE_SOURCE_DIR}/include/nlohmann/thirdparty/hedley/hedley.hpp > default_defines.hpp 2> /dev/null
|
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv_cppcheck
|
|
COMMAND venv_cppcheck/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/cmake/requirements/requirements-cppcheck.txt
|
|
COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force
|
|
--std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include
|
|
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
|
|
--cppcheck-build-dir=cppcheck
|
|
-UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW
|
|
-DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON
|
|
COMMENT "Check code with Cppcheck"
|
|
)
|
|
|
|
###############################################################################
|
|
# Check code with cpplint.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_cpplint
|
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv_cpplint
|
|
COMMAND venv_cpplint/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/cmake/requirements/requirements-cpplint.txt
|
|
COMMAND venv_cpplint/bin/cpplint --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES}
|
|
COMMENT "Check code with cpplint"
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
)
|
|
|
|
###############################################################################
|
|
# Check code with Clang-Tidy.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_clang_tidy
|
|
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_CLANG_TIDY=${CLANG_TIDY_TOOL}
|
|
-DJSON_BuildTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_tidy
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_tidy
|
|
COMMENT "Check code with Clang-Tidy"
|
|
)
|
|
|
|
###############################################################################
|
|
# Check code with Infer <https://fbinfer.com> static analyzer.
|
|
###############################################################################
|
|
|
|
# .inferconfig (repository root) pins --fail-on-issue and the currently-triaged issue types that
|
|
# are disabled until they are addressed separately; see #5715 item 4b.
|
|
add_custom_target(ci_infer
|
|
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run --project-root ${PROJECT_SOURCE_DIR} -- make
|
|
COMMENT "Check code with Infer"
|
|
)
|
|
|
|
###############################################################################
|
|
# Run test suite with previously downloaded test data.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_offline_testdata
|
|
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.2.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_TestDataDirectory=${PROJECT_BINARY_DIR}/build_offline_testdata/test_data/json_test_data
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_offline_testdata
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_offline_testdata
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
|
COMMENT "Check code with previously downloaded test data"
|
|
)
|
|
|
|
###############################################################################
|
|
# Run test suite when project was not checked out from Git
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_non_git_tests
|
|
COMMAND git config --global --add safe.directory ${PROJECT_SOURCE_DIR}
|
|
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_non_git_tests/sources
|
|
COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `${GIT_TOOL} ls-tree --name-only HEAD`\; do cp -r $$FILE ${PROJECT_BINARY_DIR}/build_non_git_tests/sources \; done
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_BINARY_DIR}/build_non_git_tests/sources -B${PROJECT_BINARY_DIR}/build_non_git_tests
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_non_git_tests
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_non_git_tests && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE git_required --output-on-failure
|
|
COMMENT "Check code when project was not checked out from Git"
|
|
)
|
|
|
|
###############################################################################
|
|
# Run test suite and exclude tests that change installed files
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_reproducible_tests
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_reproducible_tests
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_reproducible_tests
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_reproducible_tests && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE not_reproducible --output-on-failure
|
|
COMMENT "Check code and exclude tests that change installed files"
|
|
)
|
|
|
|
###############################################################################
|
|
# Check if every header in the include folder includes sufficient headers to
|
|
# be compiled individually.
|
|
###############################################################################
|
|
|
|
set(iwyu_options -Xiwyu --error -Xiwyu --max_line_length=300)
|
|
set(iwyu_path_and_options ${IWYU_TOOL} ${iwyu_options})
|
|
|
|
# CMake needs to know the exact flags used to compile each src_single/*.cpp below to hand them to
|
|
# iwyu_tool.py; JSON_CI already implies a from-scratch configure, so enabling this project-wide has
|
|
# no downside here.
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
foreach(SRC_FILE ${SRC_FILES})
|
|
# get relative path of the header file
|
|
file(RELATIVE_PATH RELATIVE_SRC_FILE "${PROJECT_SOURCE_DIR}/include/nlohmann" "${SRC_FILE}")
|
|
# replace slashes and strip suffix
|
|
string(REPLACE "/" "_" RELATIVE_SRC_FILE "${RELATIVE_SRC_FILE}")
|
|
string(REPLACE ".hpp" "" RELATIVE_SRC_FILE "${RELATIVE_SRC_FILE}")
|
|
# create code file
|
|
file(WRITE "${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp" "#include \"${SRC_FILE}\" // IWYU pragma: keep\n\nint main()\n{}\n")
|
|
# create executable
|
|
add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp)
|
|
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
|
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
|
|
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
|
|
# remember binary for ci_single_binaries
|
|
list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
|
|
# json.hpp pulls together the whole library behind heavily templated, SFINAE-based code, and
|
|
# IWYU's suggestion for its one truly ambiguous symbol (a container-comparison "swap,
|
|
# operator!=") is not deterministic between runs (observed <set>, <unordered_map>, and <map>
|
|
# for the exact same source across otherwise-identical local and containerized builds). Keep
|
|
# reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it
|
|
# from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a
|
|
# nondeterministic suggestion for a header that already re-exports everything on purpose.
|
|
if(NOT RELATIVE_SRC_FILE STREQUAL "json")
|
|
list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp)
|
|
endif()
|
|
endforeach()
|
|
|
|
if(IWYU_TOOL_PY)
|
|
add_custom_target(ci_single_binaries
|
|
DEPENDS ${single_binaries}
|
|
COMMAND ${IWYU_TOOL_PY} -p ${PROJECT_BINARY_DIR} ${single_binaries_tus} -- ${iwyu_options}
|
|
COMMENT "Check if headers are self-contained"
|
|
)
|
|
else()
|
|
# iwyu_tool.py (ships with IWYU, e.g. as /usr/bin/iwyu_tool on Debian/Ubuntu) was not found;
|
|
# fall back to building the self-containment check without enforcing the IWYU findings.
|
|
add_custom_target(ci_single_binaries
|
|
DEPENDS ${single_binaries}
|
|
COMMENT "Check if headers are self-contained"
|
|
)
|
|
endif()
|
|
|
|
###############################################################################
|
|
# Benchmarks
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_benchmarks
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Release -GNinja
|
|
-S${PROJECT_SOURCE_DIR}/tests/benchmarks -B${PROJECT_BINARY_DIR}/build_benchmarks
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_benchmarks --target json_benchmarks
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_benchmarks && ./json_benchmarks
|
|
COMMENT "Run benchmarks"
|
|
)
|
|
|
|
###############################################################################
|
|
# CMake flags
|
|
###############################################################################
|
|
|
|
# we test the project with different CMake versions:
|
|
# - CMake 3.5 (the earliest supported)
|
|
# - CMake 3.31.6 (the latest 3.x release)
|
|
# - CMake 4.0.0 (the first 4.x release)
|
|
# - the CMake version running this build (usually the latest release)
|
|
|
|
function(ci_get_cmake version var)
|
|
set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}/bin/cmake)
|
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$")
|
|
# Kitware publishes a prebuilt Linux x86_64 archive for every release; unpacking it is far
|
|
# cheaper than compiling all of CMake (including its own test helpers) from source.
|
|
add_custom_command(
|
|
OUTPUT ${${var}}
|
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-linux-x86_64.tar.gz
|
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-SHA-256.txt
|
|
# verify the archive against Kitware's published SHA-256 sums before unpacking it
|
|
COMMAND sh -c "grep ' cmake-${version}-linux-x86_64[.]tar[.]gz$' cmake-${version}-SHA-256.txt | sha256sum -c -"
|
|
COMMAND tar xfz cmake-${version}-linux-x86_64.tar.gz
|
|
COMMAND rm cmake-${version}-linux-x86_64.tar.gz cmake-${version}-SHA-256.txt
|
|
COMMAND ${CMAKE_COMMAND} -E rm -rf cmake-${version}
|
|
COMMAND ${CMAKE_COMMAND} -E rename cmake-${version}-linux-x86_64 cmake-${version}
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
COMMENT "Download prebuilt CMake ${version}"
|
|
)
|
|
else()
|
|
# no prebuilt archive for this platform (e.g. macOS or Linux aarch64): build from source
|
|
add_custom_command(
|
|
OUTPUT ${${var}}
|
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}.tar.gz
|
|
COMMAND tar xfz cmake-${version}.tar.gz
|
|
COMMAND rm cmake-${version}.tar.gz
|
|
# -DCMAKE_POLICY_VERSION_MINIMUM=3.5 required to compile older CMake versions with CMake 4.0.0
|
|
COMMAND cmake -S cmake-${version} -B cmake-${version} -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
|
COMMAND cmake --build cmake-${version} --parallel 10
|
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
|
COMMENT "Download and build CMake ${version} from source"
|
|
)
|
|
endif()
|
|
set(${var} ${${var}} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
ci_get_cmake(3.5.0 CMAKE_3_5_0_BINARY)
|
|
ci_get_cmake(3.31.6 CMAKE_3_31_6_BINARY)
|
|
ci_get_cmake(4.0.0 CMAKE_4_0_0_BINARY)
|
|
|
|
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
|
|
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
|
|
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
|
|
JSON_StrictNulHandling)
|
|
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
|
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
|
|
|
function(ci_add_cmake_flags_targets flag min_version)
|
|
string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
|
|
string(REPLACE . _ min_version_var ${min_version})
|
|
set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
|
|
add_custom_target(${flag_target}_${min_version_var}
|
|
COMMENT "Check CMake flag ${flag} (CMake ${min_version})"
|
|
COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
|
&& ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
|
|
DEPENDS ${cmake_binary}
|
|
)
|
|
list(APPEND JSON_CMAKE_FLAG_TARGETS ${flag_target}_${min_version_var})
|
|
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
|
|
set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
|
|
set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_5_0})
|
|
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.5.0)
|
|
endforeach()
|
|
|
|
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_31_6})
|
|
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.31.6)
|
|
endforeach()
|
|
|
|
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_4_0_0})
|
|
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 4.0.0)
|
|
endforeach()
|
|
|
|
# check the same flags with the CMake version running this build
|
|
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_4_0_0})
|
|
string(TOLOWER "ci_cmake_flag_${JSON_CMAKE_FLAG}" flag_target)
|
|
add_custom_target(${flag_target}
|
|
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${CMAKE_VERSION})"
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-Werror=dev
|
|
-D${JSON_CMAKE_FLAG}=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
|
|
)
|
|
list(APPEND JSON_CMAKE_FLAG_TARGETS ${flag_target})
|
|
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target})
|
|
endforeach()
|
|
|
|
add_custom_target(ci_cmake_flags
|
|
DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
|
|
COMMENT "Check CMake flags"
|
|
)
|
|
|
|
###############################################################################
|
|
# Use more installed compilers.
|
|
###############################################################################
|
|
|
|
foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17 clang++-18 clang++-19 clang++-20)
|
|
find_program(COMPILER_TOOL NAMES ${COMPILER})
|
|
if (COMPILER_TOOL)
|
|
unset(ADDITIONAL_FLAGS)
|
|
|
|
add_custom_target(ci_test_compiler_${COMPILER}
|
|
COMMAND CXX=${COMPILER} ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
|
|
${ADDITIONAL_FLAGS}
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
|
|
COMMENT "Compile and test with ${COMPILER}"
|
|
)
|
|
endif()
|
|
unset(COMPILER_TOOL CACHE)
|
|
endforeach()
|
|
|
|
add_custom_target(ci_test_compiler_default
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_default
|
|
${ADDITIONAL_FLAGS}
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_default --parallel ${N}
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_default && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" -LE git_required --output-on-failure
|
|
COMMENT "Compile and test with default C++ compiler"
|
|
)
|
|
|
|
###############################################################################
|
|
# CUDA example
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_cuda_example
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example
|
|
)
|
|
|
|
###############################################################################
|
|
# C++ 20 modules
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_module_cpp20
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DJSON_CI=ON -DNLOHMANN_JSON_BUILD_MODULES=ON -DJSON_Install=ON
|
|
-S${PROJECT_SOURCE_DIR}/tests/module_cpp20 -B${PROJECT_BINARY_DIR}/ci_module_cpp20
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/ci_module_cpp20
|
|
)
|
|
|
|
###############################################################################
|
|
# Intel C++ Compiler
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_icpc
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpc
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpc
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_icpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
|
|
COMMENT "Compile and test with ICPC"
|
|
)
|
|
|
|
add_custom_target(ci_icpx
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpx
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpx
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_icpx && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
|
|
COMMENT "Compile and test with ICPX (Intel oneAPI DPC++/C++)"
|
|
)
|
|
|
|
###############################################################################
|
|
# NVIDIA HPC SDK C++ Compiler
|
|
###############################################################################
|
|
|
|
# nvc++ defaults to a relaxed, non-IEEE floating-point model that flushes denormals
|
|
# to zero and does not honor NaN ordering; -Kieee restores strict IEEE 754 behavior
|
|
# (needed for the dtoa/grisu and NaN-comparison code paths).
|
|
#
|
|
# -tp=px pins the target processor to the generic x86-64 baseline (SSE2-only) to avoid
|
|
# a nvc++ 25.5 / LLVM issue: when nvc++ auto-detects -tp from the runner's CPU (e.g. -tp znver4),
|
|
# certain attribute combinations trigger an llc instruction-selection crash on std::ldexp<unsigned>.
|
|
# Pinning to px removes this variability and is robust to future llc/nvc++ updates.
|
|
#
|
|
# The following tests are excluded as they trigger known nvc++ 25.5 defects (not
|
|
# library bugs); see https://github.com/nlohmann/json for tracking. Only the
|
|
# affected language-standard variants are excluded so coverage is otherwise kept:
|
|
# - test-comparison_cpp20, test-comparison_legacy_cpp20
|
|
# miscompiles cross-type/<=> comparison (e.g. `-17 <= null`)
|
|
# - test-constructor1_cpp11
|
|
# std::initializer_list lifetime bug -> SIGSEGV
|
|
# - test-deserialization_cpp20
|
|
# mangles the UTF-8 u8"" string literal in the char8_t (C++20) section
|
|
add_custom_target(ci_nvhpc
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
|
-DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++
|
|
-DCMAKE_CXX_FLAGS="-Kieee;-tp=px"
|
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_nvhpc
|
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
|
# the pipes are escaped so the surrounding shell passes them to ctest verbatim
|
|
# instead of treating them as shell pipe operators
|
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_nvhpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode\\|test-comparison_cpp20\\|test-comparison_legacy_cpp20\\|test-constructor1_cpp11\\|test-deserialization_cpp20" --output-on-failure
|
|
COMMENT "Compile and test with NVIDIA HPC SDK (nvc++)"
|
|
)
|
|
|
|
###############################################################################
|
|
# REUSE
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_reuse_compliance
|
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv_reuse
|
|
COMMAND venv_reuse/bin/pip3 --quiet install -r ${PROJECT_SOURCE_DIR}/cmake/requirements/requirements-reuse.txt
|
|
COMMAND venv_reuse/bin/reuse --root ${PROJECT_SOURCE_DIR} lint
|
|
COMMENT "Check REUSE specification compliance"
|
|
)
|
|
|
|
###############################################################################
|
|
# test documentation
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_test_examples
|
|
COMMAND make CXX="${GCC_TOOL}" check_output_portable -j8
|
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/docs
|
|
COMMENT "Check that all examples compile and create the desired output"
|
|
)
|
|
|
|
add_custom_target(ci_test_build_documentation
|
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv
|
|
COMMAND venv/bin/pip3 --quiet install -r requirements.txt
|
|
COMMAND make build
|
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/docs/mkdocs
|
|
COMMENT "Build the documentation"
|
|
)
|
|
|
|
###############################################################################
|
|
# Clean up all generated files.
|
|
###############################################################################
|
|
|
|
add_custom_target(ci_clean
|
|
COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* ${PROJECT_BINARY_DIR}/cmake-3.5.0 ${PROJECT_BINARY_DIR}/cmake-3.31.6 ${PROJECT_BINARY_DIR}/cmake-4.0.0 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
|
|
COMMENT "Clean generated directories"
|
|
)
|