* Fix the ci_cmake_flags wiring so every option is checked
The CMake 3.31.6 flag list referred to itself before it was defined,
so only JSON_BuildTests was checked with that version. The targets for
the CMake running the build ("_2") were created but never added to
ci_cmake_flags, and the three versions shared one build directory.
JSON_StrictNulHandling was not in the list at all.
Use the 3.5.0 list for 3.31.6, add JSON_StrictNulHandling, and create
one ci_cmake_flag_<flag> target per option for the running CMake with
its own build directory. Also use the function parameter in the
COMMENT, refresh the stale version comment, and let ci_clean remove
the downloaded cmake-<version> directories instead of the long-gone
cmake-3.5.0-Darwin64.
Part of #5715
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Fix ci_test_clang_libcxx_cxx* jobs silently building without warnings
CMake only seeds CMAKE_CXX_FLAGS from the CXXFLAGS environment variable
when the cache entry is unset, so the explicit -DCMAKE_CXX_FLAGS="-stdlib=libc++"
argument made it ignore CXXFLAGS="${CLANG_CXXFLAGS}" entirely. The six
ci_test_standards_clang (..., libcxx) jobs therefore compiled without
-Weverything/-Werror while their libstdc++ siblings did use them.
Pass -stdlib=libc++ through the same CXXFLAGS value instead of a separate
-D argument, and give the target its own build directory
(build_clang_libcxx_cxx${CXX_STANDARD}) so it no longer shares a CMake
cache with the libstdc++ variant. Suppress the resulting
-Wthread-safety-negative finding from libc++'s std::mutex annotations,
which fires on doctest's reporters in this translation unit only.
Part of #5715
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Remove the no-op AppVeyor with_win_header job
The with_win_header matrix entry patched Windows.h into
single_include/nlohmann/json.hpp before building, but JSON_MultipleHeaders
has defaulted to ON since #3532 (2022-06), so CMakeLists.txt points the
tests at include/ and the patched single header is never compiled. The
job has been a no-op VS2015 build since then.
Windows.h coverage already exists through tests/src/unit-windows_h.cpp
(#3631), which runs in every MSVC job. Delete the dead matrix entry and
its before_build steps, and cite unit-windows_h.cpp from the QA page.
Part of #5715
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Remove unused ci_oclint and ci_pvs_studio targets
No workflow invokes ci_oclint, ci_pvs_studio, or their tool discovery.
ci_oclint also had a side effect on every JSON_CI configure: it copied
the single header into src_single/all.cpp and added an add_executable()
for it without EXCLUDE_FROM_ALL, so a plain build compiled a 1.2 MB
translation unit that only that unused target consumed. ci_pvs_studio
duplicates the Makefile's pvs_studio target, which is kept.
Also drop the duplicate --check-level=exhaustive flag passed twice to
the same ci_cppcheck invocation.
Part of #5715
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Stop Dependabot from proposing astyle bumps
astyle is deliberately pinned at 3.4.13 because newer versions reformat
unrelated lines and this version defines the formatting that
check_amalgamation.yml enforces. Without an ignore rule, Dependabot
keeps opening PRs for every new astyle release (most recently #4580,
#4942, #5445, #5448), each of which fails the amalgamation check and
gets closed unmerged.
Part of #5715
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Move Linux arm64 CI from dead Cirrus CI to ubuntu-24.04-arm
Cirrus CI stopped reporting check runs on develop sometime after
d10879bca (2026-05-26); every commit since has only github-actions
check runs, so .cirrus.yml silently lost its only consumer while
README.md, FILES.md and the QA page kept advertising the coverage.
Add a ci_test_arm64 job to ubuntu.yml using the same pinned
actions/checkout and lukka/get-cmake actions as the other jobs, on the
native ubuntu-24.04-arm runner, with a step that confirms uname -m
reports aarch64. Delete .cirrus.yml and its README badge and FILES.md
section, and update the QA page's arm64 row.
Part of #5715
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Make scan-build fail on findings and drop irrelevant checkers (#5715 item 4a)
ci_clang_analyze ran scan-build without --status-bugs, so the job
passed whenever the ninja build succeeded, no matter what the
analyzer found ("No bugs found" in a green run gave no signal either
way). It is also missing --use-analyzer=${CLANG_TOOL}, so scan-build
picks whichever clang happens to be first on PATH inside the
silkeh/clang:dev container instead of the one this file already
selected and versioned.
Add --status-bugs and --use-analyzer=${CLANG_TOOL} to the scan-build
invocation. While here, drop the osx.*, webkit.*, fuchsia.*, and
optin.mpi.* checkers from CLANG_ANALYZER_CHECKS: none of them apply
to this portable C++ library, and leaving them enabled only adds
noise once the job can actually fail on a finding.
The job is currently clean (0 bugs), so this alone does not surface
any new finding; it only makes the existing "no bugs found" result
authoritative. This is 4a of 3 independent steps in #5715 item 4;
4b (Infer) and 4c (IWYU) still need their existing findings triaged
before --fail-on-issue/-Xiwyu --error can be added, and are handled
in separate commits.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Deduplicate the amalgamation/format check's file set and add BUILD.bazel (#5715 item 5)
The amalgamation/format check existed three times with three different
file sets: the Makefile's pretty/check-amalgamation, the pull_request-only
check_amalgamation.yml workflow, and the ci_test_amalgamation CMake target
that also runs on direct pushes to develop/master/release/*. The CMake
target's glob was a strict subset of the workflow's (missing the
docs/mkdocs/docs/examples/*.hpp headers, tests/abi/, tests/cmake_*/project/,
tests/cuda_example/, tests/fmt_formatter/, and tests/module_cpp20/), and it
never checked BUILD.bazel at all, so a misformatted file in any of those
paths, or a stale BUILD.bazel, could reach develop through a direct push
even though the PR-only workflow would have caught it.
Make ci_test_amalgamation glob the same roots (docs/mkdocs/docs/examples,
include, tests) and extensions (*.hpp, *.cpp, *.cu) as check_amalgamation.yml,
excluding tests/thirdparty/ and tests/abi/include/nlohmann/ the same way, and
regenerate and diff BUILD.bazel next to json.hpp/json_fwd.hpp. Also add
docs/mkdocs/docs/examples/*.hpp to the Makefile's pretty/pretty_format
targets, which were missing the four custom_*_type.hpp example headers, and
drop the stale "called by Travis" comment on check-amalgamation (Travis is
gone; nothing currently calls that Makefile target from CI).
Leaves the workflow itself untouched: it deliberately runs amalgamate.py
from a fresh develop checkout so a PR cannot change the tool that checks it.
Overlaps #5610 and #5621, which each add a new amalgamated header and touch
the same INDENT_FILES/ci_test_amalgamation/check_amalgamation.yml hunks.
Verified with `make check-amalgamation` on this branch: clean, no diff.
#5715 item 5.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Download prebuilt CMake binaries on Linux x86_64 instead of building from source (#5715 item 6)
ci_get_cmake() downloaded the source tarball of CMake 3.5.0, 3.31.6, and
4.0.0 and compiled each one completely (including CMake's own test
helpers) with -DCMAKE_POLICY_VERSION_MINIMUM=3.5 as a workaround for
building old CMake with a newer one. On CI this made the
ci_cmake_options (ci_cmake_flags) job take about 11 minutes, most of it
spent building CMake itself, even though Kitware has published
ready-to-run Linux x86_64 archives for all three of these releases
since 3.20 (lowercase platform name).
On Linux x86_64, download and unpack the prebuilt
cmake-<version>-linux-x86_64.tar.gz archive instead and point the
existing ${var} output at its bin/cmake, skipping the configure/build
steps and CMAKE_POLICY_VERSION_MINIMUM entirely. Keep the previous
source build as a fallback for any other platform (macOS, Linux
aarch64), since Kitware does not publish binaries for every
CMake/platform combination this project might build on.
Verify the downloaded archive against Kitware's own published checksum
before unpacking it: download cmake-<version>-SHA-256.txt alongside the
archive and run `sha256sum -c` on the matching line. A CI job that wgets
and untars a binary from a release page with no integrity check is a
supply-chain gap; Kitware has published this file for every release
since 3.20, so checking it costs one extra download and one grep.
As a separate, mechanical change: the ci_cmake_options job's container
only needed to stay on ubuntu:focal for the source build's
libssl-dev dependency and its own aging toolchain; now that the
Linux/x86_64 path never compiles CMake, drop libssl-dev from its apt
install line and move the job to ubuntu:24.04 (Ubuntu 20.04 left
standard support in May 2025). ci_clean already removes the
cmake-3.5.0/cmake-3.31.6/cmake-4.0.0 directories from the #5715 item 3
fix, and the prebuilt path reuses those same directory names, so no
further cleanup changes are needed.
Overlaps #5598, which edits the same ci_cmake_options matrix line in
ubuntu.yml; a rebase may be needed once that lands.
Verified locally: `cmake -S . -B build -DJSON_CI=On` configures cleanly
on macOS/arm64 (source-build fallback branch) and on Linux/x86_64 in an
ubuntu:24.04 Docker container (47 `ci_cmake_flag_*` targets generated,
one built and run successfully); `.github/workflows/ubuntu.yml` still
parses as valid YAML; downloaded the real v3.31.6 Linux x86_64 archive
and SHA-256 file from Kitware and confirmed the `grep | sha256sum -c`
pipeline both accepts the genuine file and is anchored to the exact
filename (not a prefix match).
CI must confirm: the prebuilt-binary path actually runs on the
ubuntu-latest/ubuntu:24.04 x86_64 runner, all `ci_cmake_options`
entries still pass with the new container's GCC, and the job's
runtime drops from roughly 11 minutes.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Make Infer fail on findings, with a type-level baseline for the ~174 pre-existing ones (#5715 item 4b)
ci_infer ran `infer run` without --fail-on-issue, so the job passed
regardless of what Pulse found; the last recorded run (35829411620,
commit 1054b2097) logged "Found 174 issues" and still went green.
report.txt was also never uploaded, so the full finding list was only
ever visible in the truncated 5-issue console excerpt.
Add a repository-root .inferconfig (auto-discovered by Infer; passing
--project-root on the `infer run` invocation makes sure it is found
even though the analysis runs from build/build_infer) that sets
fail-on-issue and disables the six PULSE issue types that made up all
174 findings in that run: PULSE_UNNECESSARY_COPY_ASSIGNMENT (129),
PULSE_UNNECESSARY_COPY (22), PULSE_UNNECESSARY_COPY_INTERMEDIATE (15),
PULSE_RESOURCE_LEAK (5), PULSE_CONST_REFABLE (2), and
PULSE_UNNECESSARY_COPY_OPTIONAL (1).
This is a deliberate, narrower fix than "triage and fix everything in
this PR": the visible sample is entirely doctest-macro copies in test
code (for example tests/src/unit-algorithms.cpp:141 and
tests/src/unit-bjdata.cpp:3706), but 169 of the 174 findings were never
uploaded anywhere and this PR cannot respectably claim to have fixed
issues it never saw, including the resource-leak and const-refable
ones that are the most likely to be genuine bugs. Disabling by issue
type is a coarser baseline than a per-finding one (Infer has no
built-in per-finding baseline short of the two-run `infer reportdiff`
workflow, which this repository does not have the CI infrastructure
for), but it has the same effect today: the job goes from always green
to green-only-when-clean-of-everything-else, so CI now fails the
moment a *new* issue type appears, and report.txt is uploaded as a
workflow artifact on every run (including failures) so the six
disabled types can be triaged and re-enabled incrementally in follow-up
PRs.
#5715 item 4b. 4a (scan-build) and 4c (IWYU) are handled in separate
commits.
Verified: .inferconfig parses as JSON, ubuntu.yml still parses as
YAML. Infer itself is not available in this environment (v1.3.0 tar.xz
requires a Linux x86_64 runner), so CI must confirm that `infer run
--project-root ... -- make` picks up .inferconfig, that fail-on-issue
takes effect, and that the six disabled types actually suppress the
existing findings without also hiding an unrelated new one.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Fix IWYU findings for json.hpp/json_fwd.hpp/ordered_map.hpp and make CI fail on new ones (#5715 item 4c)
ci_single_binaries ran IWYU via CMake's CXX_INCLUDE_WHAT_YOU_USE launcher
property, which only printed "Warning: include-what-you-use reported
diagnostics" without failing the build: CMake's own __run_co_compile
wrapper does not propagate the launched tool's exit code, so even
`-Xiwyu --error` could never fail `cmake --build` this way. Verified
this empirically by injecting a deliberately-unused #include and
confirming the build still exited 0.
Fix the findings from the last recorded run (issue #5715 item 4, log
35829411620):
- ordered_map.hpp: add <new> (placement new) and
nlohmann/detail/abi_macros.hpp; drop <memory> (std::allocator is
still visible transitively via <vector>, confirmed by full local and
containerized test suite runs).
- json_fwd.hpp: drop <memory> (same reasoning). Keep every forward
declaration IWYU wanted removed (adl_serializer, basic_json,
json_pointer, ordered_map): this file's only job is to forward-declare
them for downstream users, so "nothing in this TU uses them" is
expected, not a real finding. Mark each with `// IWYU pragma: keep`.
- json.hpp: add <cmath>, <cstdint>, <set>, <type_traits>,
<unordered_map>, and the detail/abi_macros.hpp, detail/input/json_sax.hpp,
detail/meta/detected.hpp, thirdparty/hedley/hedley.hpp includes IWYU
says it needs. Do NOT remove adl_serializer.hpp,
detail/conversions/from_json.hpp, detail/conversions/to_json.hpp,
detail/macro_unscope.hpp, or ordered_map.hpp as IWYU suggests: nothing
else in include/nlohmann includes adl_serializer.hpp or
ordered_map.hpp, so basic_json<>'s own default template arguments
(JSONSerializer = adl_serializer, and ordered_json = basic_json<ordered_map>)
would lose their complete type; detail/macro_unscope.hpp is what
undoes the JSON_* macros detail/macro_scope.hpp defines earlier in
this same file, and removing it leaks those macros into every
translation unit that includes <nlohmann/json.hpp>. Verified by
actually removing them in a scratch test: the header still "compiles"
stand-alone but ordered_json and every macro-using translation unit
break. Marked each `// IWYU pragma: keep`.
Enforce it with `iwyu_tool` (ships with IWYU, e.g. as /usr/bin/iwyu_tool
on Debian/Ubuntu) instead of relying on the launcher property: it reads
compile_commands.json (now exported project-wide under JSON_CI) and
does return a real exit code for its own analysis, independent of
CMake's wrapper. ci_single_binaries now runs it over every
src_single/*.cpp with `-Xiwyu --error`, so a *new* finding fails CI.
json.hpp itself is excluded from that hard gate: even after every fix
above, IWYU's suggestion for one remaining symbol (a container
`swap, operator!=` used somewhere via a templated comparator) is not
deterministic — repeated, otherwise-identical containerized runs
reported <set>, then <unordered_map>, then <map> as "the" header to
add/remove for the exact same source. Gating a whole CI job on a
nondeterministic suggestion would make ci_single_binaries flaky rather
than informative, so json.hpp keeps the existing informational warning
(still shown during its normal compile) without failing the build on
it. Every other one of the ~50 single-header checks is included in the
hard gate.
#5715 item 4c. 4a (scan-build) and 4b (Infer) are separate commits.
Verified: full local ctest suite (129/129) and the ci_single_binaries
target itself both green in a containerized silkeh/clang:dev run
(matching the actual CI job) after this fix; a deliberately-reintroduced
unused #include in ordered_map.hpp was confirmed to fail
`cmake --build ... --target ci_single_binaries` (exit 2) with this
change, and to pass without it, on the same container/IWYU version CI
uses. `make check-amalgamation` is clean. Compiled with Clang and GCC
at -std=c++11/14/17/20 locally with no new warnings.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
---------
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
18 KiB
Quality assurance
Ensuring quality is paramount for this project, particularly because numerous other projects depend on it. Each commit to the library undergoes rigorous checks against the following requirements, and any violations will result in a failed build.
C++ language compliance and compiler compatibility
!!! success "Requirement: Compiler support"
Any compiler with complete C++11 support can compile the library without warnings.
Note: C++20 modules support may hit compiler-specific issues not covered by the general compiler matrix below. See Modules for known issues and workarounds.
Note: Some modern features (like C++20 ranges or filesystem support) may be disabled on specific broken or incomplete toolchains even when standard feature-test macros indicate support. See JSON_HAS_RANGES and JSON_HAS_FILESYSTEM for details on known exclusions.
-
The library is compiled with 50+ different C++ compilers with different operating systems and platforms, including the oldest versions known to compile the library.
??? abstract "Compilers used in continuous integration"
| Compiler | Architecture | Operating System | CI | |----------------------------------------------|--------------|-----------------------------------|-----------| | AppleClang 15.0.0.15000040; Xcode 15.0.1 | arm64 | macOS 14.7.2 (Sonoma) | GitHub | | AppleClang 15.0.0.15000100; Xcode 15.1 | arm64 | macOS 14.7.2 (Sonoma) | GitHub | | AppleClang 15.0.0.15000100; Xcode 15.2 | arm64 | macOS 14.7.2 (Sonoma) | GitHub | | AppleClang 15.0.0.15000309; Xcode 15.3 | arm64 | macOS 14.7.2 (Sonoma) | GitHub | | AppleClang 15.0.0.15000309; Xcode 15.4 | arm64 | macOS 14.7.2 (Sonoma) | GitHub | | AppleClang 16.0.0.16000026; Xcode 16 | arm64 | macOS 15.2 (Sequoia) | GitHub | | AppleClang 16.0.0.16000026; Xcode 16.1 | arm64 | macOS 15.2 (Sequoia) | GitHub | | AppleClang 16.0.0.16000026; Xcode 16.2 | arm64 | macOS 15.2 (Sequoia) | GitHub | | AppleClang 17.0.0.17000013; Xcode 16.3 | arm64 | macOS 15.5 (Sequoia) | GitHub | | AppleClang 17.0.0.17000013; Xcode 16.4 | arm64 | macOS 15.5 (Sequoia) | GitHub | | AppleClang 17.0.0.17000319; Xcode 26.0.1 | arm64 | macOS 15.5 (Sequoia) | GitHub | | Clang 3.4.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 3.5.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 3.6.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 3.7.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 3.8.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 3.9.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 4.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 5.0.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 6.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 7.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 8.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 9.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 10.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 11.0.1 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 11.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 12.0.1 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 12.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 13.0.1 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 13.0.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 14.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 14.0.6 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 15.0.7 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 15.0.7 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 16.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 16.0.6 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 17.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 18.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 18.1.8 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 19.1.5 with MSVC-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 19.1.7 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 19.1.7 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 20.1.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 20.1.8 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | Clang 21.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | Clang 22.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | CUDA 11.8.0 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub | | CUDA 12.1.1 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub | | CUDA 12.6.3 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub | | Emscripten 4.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 4.8.5 | x86_64 | Ubuntu 20.04 LTS | GitHub | | GNU 4.9.3 | x86_64 | Ubuntu 20.04 LTS | GitHub | | GNU 5.5.0 | x86_64 | Ubuntu 20.04 LTS | GitHub | | GNU 6.4.0 | x86_64 | Ubuntu 20.04 LTS | GitHub | | GNU 7.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 8.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 9.3.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 9.4.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 9.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 10.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 11.4.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 11.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 12.2.0 (MinGW-W64 i686-ucrt-posix-dwarf) | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | GNU 12.2.0 (MinGW-W64 x86_64-ucrt-posix-seh) | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | GNU 12.4.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 13.3.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 14.2.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 15.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 16.1.0 | arm64 | Ubuntu 24.04 | GitHub | | icpc (ICC) 2021.10.0 20230609 | x86_64 | Ubuntu 22.04 LTS | GitHub | | icpx (Intel oneAPI DPC++/C++) 2025.3.2 | x86_64 | Ubuntu 24.04 LTS | GitHub | | nvc++ (NVIDIA HPC SDK) 25.5-0 | x86_64 | Ubuntu 22.04 LTS | GitHub | | MSVC 19.0.24241.7 | x86 | Windows 8.1 | AppVeyor | | MSVC 19.16.27035.0 | x86 | Windows-10 (Build 14393) | AppVeyor | | MSVC 19.29.30157.0 | x86 | Windows-10 (Build 17763) | AppVeyor | | MSVC 19.44.35207.0 | arm64 | Windows 11 (Build 26200) | GitHub | | MSVC 19.44.35214.0 | x86 | Windows Server 2022 (Build 20348) | GitHub | | MSVC 19.44.35214.0 | x86_64 | Windows Server 2022 (Build 20348) | GitHub | | MSVC 19.51.36231.0 | x86 | Windows Server 2025 (Build 26100) | GitHub | | MSVC 19.51.36231.0 | x86_64 | Windows Server 2025 (Build 26100) | GitHub | -
The library is compiled with all C++ language revisions (C++11, C++14, C++17, C++20, C++23, and C++26) to detect and fix language deprecations early.
-
The library is checked for compiler warnings:
-
On Clang,
-Weverythingis used with 8 exceptions.??? abstract "Clang warnings"
```cmake --8<-- "../../../cmake/clang_flags.cmake" ``` -
On GCC, 300+ warnings are enabled with 8 exceptions.
??? abstract "GCC warnings"
```cmake --8<-- "../../../cmake/gcc_flags.cmake" ```
-
C++ standard library compliance
!!! success "Requirement: No prerequisites"
The library has no prerequisites other than the Standard Template Library (STL).
- The library is compiled and tested with both libc++ and libstdc++ to detect subtle differences or incompatibilities.
- The code checked with Include What You Use (IWYU) that all required standard headers are included.
- On Windows, the library is compiled with
<Windows.h>being included to detect and avoid common bugs (seeunit-windows_h.cpp). - The library is compiled with exceptions disabled to support alternative means of error handling.
Stable public API
!!! success "Requirement: Stable public API"
Any change to the library does not break the public API.
- All public API functions are tested with a variety of arguments.
- The library is compiled and tested with different template arguments for number, string, array, and object types.
- Unit tests cover all lines of the code base.
- Every exception of the library is thrown in the test suite, and the error messages and exception ids are checked.
!!! success "Requirement: Complete documentation"
The public API is extensively documented.
- Every public API function has a dedicated page in the API reference documentation with a self-contained code example.
- All examples in the documentation are tested, and changes in their output are treated as an error.
Robust input processing
!!! success "Requirement: Standards compliance"
The library is compliant to JSON as defined in [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259).
- The lexer is tested with all valid Unicode code points and all prefixes of all invalid Unicode code points.
- The parser is tested against extensive correctness suites for JSON compliance.
- In addition, the library is continuously fuzz-tested at OSS-Fuzz where the library is checked against billions of inputs.
- Every crash reported by OSS-Fuzz is fixed together with a unit test that reproduces it, and the fix references the OSS-Fuzz issue. The round-trip checks of the fuzzer drivers are also part of the unit tests. See the fuzz testing documentation.
Static analysis
!!! success "Requirement: State-of-the-art code analysis"
The code is checked with state-of-the-art static code analysis tools.
-
The code is checked with the latest Clang-Tidy.
??? abstract "Clang-Tidy configuration (.clang-tidy)"
```ini --8<-- "../../../.clang-tidy" ``` -
The code is checked with the latest Cppcheck with all warnings enabled.
-
The code is checked with the latest Clang Static Analyzer with 89 enabled rules.
-
The code is checked with Infer.
-
The code is checked with Codacy.
Dynamic analysis
!!! success "Requirement: Correctness"
The library is checked for memory correctness and absence of undefined behavior.
- The test suite is executed with enabled runtime assertions to check invariants and preconditions of functions to detect undefined behavior.
- The test suite is executed with Valgrind (Memcheck) to detect memory leaks.
- The test suite is executed with Sanitizers (address sanitizer, undefined behavior sanitizer, integer overflow detection, nullability violations).
Dependencies
!!! success "Requirement: No vulnerable dependencies"
The library has no dependencies besides the C++ standard library. The tools used to build, test, and document it
are kept free of known vulnerabilities.
- GitHub Actions are pinned to a commit hash, and the Python packages used by the documentation and the tools are pinned to exact versions.
- Dependabot checks these dependencies daily and proposes updates as pull requests.
- Every pull request is checked with the dependency review action. A pull request that adds a dependency with a known vulnerability of any severity fails this check and is not merged.
- Vulnerability alerts for dependencies are fixed or dismissed with a documented reason before the next release. No release is made while such an alert is open.
- Third-party code included in the repository for testing, such as doctest, is updated manually.
Style check
!!! success "Requirement: Common code style"
A common code style is used throughout all code files of the library.
-
The code is formatted with Artistic Style (astyle) against a style configuration that is also enforced in the CI.
??? abstract "Astyle configuration (tools/astyle/.astylerc)"
```ini --8<-- "../../../tools/astyle/.astylerc" ``` -
The code style is checked with cpplint with 61 enabled rules.
Simple integration
!!! success "Requirement: Single header"
The library can be used by adding a single header to a C++ project.
- An amalgamation script is used to check if the source code is exposed as a self-contained single-header file.
- The test suite is checked against the amalgamated source file as well as the individual source file.
!!! success "Requirement: CMake as primary development tool"
All library functions are exposed and usable by CMake.
- All library options are exposed as CMake options and tested.
- The library is tested against relevant CMake versions:
- CMake 3.5 (the earliest supported)
- CMake 3.31.6 (the latest 3.x release)
- CMake 4.0.0 (a very recent release)