Compare commits

..
Author SHA1 Message Date
Niels Lohmann f2f64eb67c Bump lukka/get-cmake from 4.4.5 to 4.5.0
get-cmake 4.4.5 does not know CMake 4.5.0, so the ci_module_cpp20 jobs
that request '^4.5.0' failed in the setup step. Bump every pin so all
jobs use the same action version.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-11-13 14:32:21 +01:00
Niels Lohmann 3004829134 Use CMake 4.5's stable import std support in the module test
CMake 4.5 makes `import std` available to every target that scans for
C++ modules and drops the experimental CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
gate and the CXX_MODULE_STD property. The module test no longer needs the
version-specific opt-in token, so the ci_module_cpp20 jobs no longer have
to pin CMake 4.3.4 and now request CMake ^4.5.0.

The modules, CMake and README documentation now list the CMake, generator
and toolchain requirements for building the module and for `import std;`.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-11-13 09:36:55 +01:00
13 changed files with 82 additions and 99 deletions

No files matched your search

+21 -23
View File
@@ -25,7 +25,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -38,7 +38,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Check that Meson and pkg-config offer the CMake options - name: Check that Meson and pkg-config offer the CMake options
run: make check_build_options run: make check_build_options
- name: Install Meson - name: Install Meson
@@ -92,7 +92,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -123,7 +123,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -142,7 +142,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -168,7 +168,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -244,7 +244,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -262,7 +262,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -279,7 +279,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Disable filesystem support (std::filesystem is unusable) for clang 7 / 8 / 9 / 10 - name: Disable filesystem support (std::filesystem is unusable) for clang 7 / 8 / 9 / 10
run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV" run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV"
if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }} if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }}
@@ -299,7 +299,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -319,7 +319,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build with libc++ - name: Build with libc++
@@ -346,7 +346,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -362,13 +362,11 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: with:
persist-credentials: false persist-credentials: false
# The module test uses `import std;`, which needs CMake's experimental # The module test uses `import std;`, which needs CMake 4.5 or newer.
# import-std support. Its opt-in token is CMake-version-specific, so pin - name: Get CMake 4.5+ and ninja
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt. uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Get pinned CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
with: with:
cmakeVersion: 4.3.4 cmakeVersion: '^4.5.0'
# Clang: the std library module is provided by libc++ (the image's libstdc++ # Clang: the std library module is provided by libc++ (the image's libstdc++
# ships none), and the image's libc++ module manifest has a broken relative # ships none), and the image's libc++ module manifest has a broken relative
# path — repoint it at the real module sources. # path — repoint it at the real module sources.
@@ -392,7 +390,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -409,7 +407,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -423,7 +421,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -443,7 +441,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja
- name: Build - name: Build
@@ -484,7 +482,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Check that the job runs natively on arm64 - name: Check that the job runs natively on arm64
run: uname -m && test "$(uname -m)" = aarch64 run: uname -m && test "$(uname -m)" = aarch64
- name: Run CMake - name: Run CMake
+5 -7
View File
@@ -90,7 +90,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5 uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Set extra CXX_FLAGS for latest std_version - name: Set extra CXX_FLAGS for latest std_version
# /wd5285 silences C5285 emitted by the bundled third-party doctest.h, which # /wd5285 silences C5285 emitted by the bundled third-party doctest.h, which
# specializes std::tuple (newly diagnosed by the VS2026 v145 toolset) # specializes std::tuple (newly diagnosed by the VS2026 v145 toolset)
@@ -212,13 +212,11 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: with:
persist-credentials: false persist-credentials: false
# The module test uses `import std;`, which needs CMake's experimental # The module test uses `import std;`, which needs CMake 4.5 or newer.
# import-std support. Its opt-in token is CMake-version-specific, so pin - name: Get CMake 4.5+ and ninja
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt. uses: lukka/get-cmake@16e8153a8b4918849d92aad131befe67a3705daa # v4.5.0
- name: Get pinned CMake and ninja
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
with: with:
cmakeVersion: 4.3.4 cmakeVersion: '^4.5.0'
# CMAKE_CXX_FLAGS replaces CMake's MSVC defaults (which include /EHsc), and # CMAKE_CXX_FLAGS replaces CMake's MSVC defaults (which include /EHsc), and
# ci_module_cpp20 forwards it to the module build, so list /EHsc explicitly # ci_module_cpp20 forwards it to the module build, so list /EHsc explicitly
- name: Run CMake (Debug) - name: Run CMake (Debug)
+2 -1
View File
@@ -165,7 +165,8 @@ std::ifstream f("example.json");
json data = json::parse(f); json data = json::parse(f);
``` ```
If using modules (enabled with `NLOHMANN_JSON_BUILD_MODULES`), this example becomes: If using modules (enabled with `NLOHMANN_JSON_BUILD_MODULES`; `import std;` needs CMake 4.5 or newer, see the
[modules documentation](https://json.nlohmann.me/features/modules/)), this example becomes:
```cpp ```cpp
import std; import std;
import nlohmann.json; import nlohmann.json;
@@ -27,7 +27,7 @@ comparison of two [`json_view`](../basic_json_view/index.md) documents has a fix
and does not depend on it either. and does not depend on it either.
The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the
limit*, where the cost per level is up to about 1.8 KiB in an unoptimized and up to about 0.5 KiB in an optimized build limit*, where the cost per level is up to about 2.3 KiB in an unoptimized and up to about 0.5 KiB in an optimized build
(see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few (see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few
hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl
C C
@@ -67,7 +67,7 @@ When the macro is not defined, the library defines it to its default value.
the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a
copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at
most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be
useful: `254` levels need up to 448 KiB of stack in an unoptimized build already, twice as much as the useful: `254` levels need up to 576 KiB of stack in an unoptimized build already, twice as much as the
default.) default.)
### Stack needed ### Stack needed
@@ -83,7 +83,7 @@ Unoptimized (`-O0`):
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 | | Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
|---|---:|---:|---:|---:|---:| |---|---:|---:|---:|---:|---:|
| `dump()` and `dump(indent)`, `operator<<` | 16 / 16 | 16 / 16 | 32 / 32 | 48 / 48 | 96 / 96 | | `dump()` and `dump(indent)`, `operator<<` | 48 / 32 | 80 / 64 | 144 / 128 | 288 / 256 | 576 / 512 |
| copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 | | copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 | | `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 |
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 | | `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 |
@@ -123,24 +123,23 @@ The rule of thumb is
> stack needed ≈ a few KiB + cost per level × limit > stack needed ≈ a few KiB + cost per level × limit
with a cost per level of up to 1.8 KiB (conversion to another `basic_json` type at `-O0` with Clang; 1.3 KiB with with a cost per level of up to 2.3 KiB (`dump` at `-O0` with Clang; 2.1 KiB with GCC), 1.7 KiB for copying and merging
GCC), 1.7 KiB for copying and merging (1.3 KiB with GCC), 0.4 KiB for `dump`, and 0.1 to 0.5 KiB for most other (1.3 KiB with GCC), and 0.1 to 0.5 KiB for most other operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers
operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers come from the difference between the limits `128` and come from the difference between the limits `128` and `254` in the tables, so they are rough: other compilers,
`254` in the tables, so they are rough: other compilers, other targets (the frames of x86-64 code are about as large), other targets (the frames of x86-64 code are about as large), other standard libraries, `JSON_DIAGNOSTICS`, and
other standard libraries, `JSON_DIAGNOSTICS`, and sanitizers change them. Measure with your own tool chain (see the sanitizers change them. Measure with your own tool chain (see the example below) rather than relying on the tables.
example below) rather than relying on the tables. The stack that your own code and the operating system need comes on The stack that your own code and the operating system need comes on top of these numbers.
top of these numbers.
Which limit to choose, for the stack that you can spare for the library (the largest limit of those measured Which limit to choose, for the stack that you can spare for the library (the largest limit of those measured
for which the slowest operation needs at most that much): for which the slowest operation needs at most that much):
| Stack for the library | optimized (`-O2`) | unoptimized (`-O0`) | | Stack for the library | optimized (`-O2`) | unoptimized (`-O0`) |
|---|---:|---:| |---|---:|---:|
| 32 KiB | 64 | 16 | | 32 KiB | 64 | 0 |
| 64 KiB | 128 | 32 | | 64 KiB | 128 | 16 |
| 128 KiB (the default stack of threads on musl) | 254 | 64 | | 128 KiB (the default stack of threads on musl) | 254 | 32 |
| 256 KiB | 254 | 128 | | 256 KiB | 254 | 64 |
| 512 KiB | 254 | 254 | | 512 KiB | 254 | 128 |
| 1 MiB or more | 254 | 254 | | 1 MiB or more | 254 | 254 |
### Speed ### Speed
+14 -2
View File
@@ -9,7 +9,19 @@ Importing the module instead of including the header reduces the compile time of
## Requirements ## Requirements
The `nlohmann.json` module requires that the build system is configured to build and resolve modules when imported. Obviously, as modules were introduced in C++20, this feature can only be used in C++20 and subsequent versions. The `nlohmann.json` module requires that the build system is configured to build and resolve modules when imported. Obviously, as modules were introduced in C++20, this feature can only be used in C++20 and subsequent versions.
To enable building the `nlohmann.json` module (which is not done by default), the macro `NLOHMANN_JSON_BUILD_MODULES` must be passed to the build system. To enable building the `nlohmann.json` module (which is not done by default), set the CMake option
[`NLOHMANN_JSON_BUILD_MODULES`](../integration/cmake.md#nlohmann_json_build_modules) and link the
`nlohmann_json_modules` target.
With CMake, building the module needs:
- CMake 3.28 or newer, and
- a generator that scans for modules: Ninja (1.11 or newer), Ninja Multi-Config, or Visual Studio 2022 or newer.
The example below also uses `import std;`. CMake supports it without experimental opt-in since version 4.5, and then
only with the Ninja generators and these toolchains: Clang 18.1.2 or newer (with libc++ or libstdc++), MSVC toolset 14.36
(Visual Studio 17.6) or newer, and GCC 15 or newer (GCC 16 on macOS). With older CMake versions, `import std;` needs
CMake's version-specific experimental opt-in.
## Example ## Example
When using modules rather than headers, the previous example for creating a `json` object through a JSON file, would instead be: When using modules rather than headers, the previous example for creating a `json` object through a JSON file, would instead be:
@@ -67,7 +79,7 @@ and should not be used directly:
## Known issues ## Known issues
C++20 modules support is exercised in CI against current GCC and Clang on Ubuntu, and the default MSVC toolset on Windows Server 2022 — there is no documented minimum compiler version, unlike feature-test-macro-gated features such as [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md). C++20 modules support is exercised in CI with CMake 4.5 and `import std;` against current GCC and Clang on Ubuntu, and the default MSVC toolset on Windows Server 2022 — there is no documented minimum compiler version, unlike feature-test-macro-gated features such as [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md).
!!! info "Known compiler issues" !!! info "Known compiler issues"
@@ -64,13 +64,13 @@ stack for the nesting.)
The call stack still needs room for the levels that are recursed into, and the default limit assumes a stack of ordinary The call stack still needs room for the levels that are recursed into, and the default limit assumes a stack of ordinary
size. The stack that an operation needs is roughly proportional to the limit; with the default of 128 levels, the most size. The stack that an operation needs is roughly proportional to the limit; with the default of 128 levels, the most
demanding operations (copying a value and converting it to another `basic_json` type, in an unoptimized build) needed demanding operation (`dump` in an unoptimized build) needed up to 288 KiB, and an optimized build needed 48 KiB or less,
up to 224 KiB, and an optimized build needed 48 KiB or less, in measurements on macOS with arm64. The most demanding in measurements on macOS with arm64. The most demanding operation needed this much stack at the limits `0`, `32`,
operation needed this much stack at the limits `0`, `32`, `128`, and `254`: `128`, and `254`:
| Stack needed, in KiB | limit 0 | limit 32 | limit 128 (default) | limit 254 | | Stack needed, in KiB | limit 0 | limit 32 | limit 128 (default) | limit 254 |
|---|---:|---:|---:|---:| |---|---:|---:|---:|---:|
| unoptimized build (`-O0`) | 16 or less | 64 | 224 | 448 | | unoptimized build (`-O0`) | 16 or less | 80 | 288 | 576 |
| optimized build (`-O2`) | 16 or less | 16 or less | 48 | 112 | | optimized build (`-O2`) | 16 or less | 16 or less | 48 | 112 |
A thread with a smaller stack (a task of a real-time operating system, a fiber, or a thread of the musl C library, whose A thread with a smaller stack (a task of a real-time operating system, a fiber, or a thread of the musl C library, whose
+3
View File
@@ -269,6 +269,9 @@ target_link_libraries(myproject PRIVATE nlohmann_json_modules)
target_compile_definitions(myproject PRIVATE NLOHMANN_JSON_BUILD_MODULES) target_compile_definitions(myproject PRIVATE NLOHMANN_JSON_BUILD_MODULES)
``` ```
If `main.cpp` also uses `import std;`, the project needs CMake 4.5 or newer and a Ninja generator; see
[Modules](../features/modules.md#requirements) for the supported toolchains.
## See also ## See also
- [Macros](../api/macros/index.md) - reference of all macros - [Macros](../api/macros/index.md) - reference of all macros
-10
View File
@@ -230,16 +230,6 @@
// detail/recursion_depth_limit.hpp. Like JSON_NO_THREAD_LOCAL it is neither part // detail/recursion_depth_limit.hpp. Like JSON_NO_THREAD_LOCAL it is neither part
// of the ABI tag nor undefined at the end of json.hpp. // of the ABI tag nor undefined at the end of json.hpp.
// forced inlining of the serializer's helpers only in optimized builds: at -O0,
// GCC and Clang give every inlined copy its own stack slots, which made the
// recursive frame of serializer::dump_container() about 2.3 KB (MSVC does not
// expand __forceinline at /Ob0, so it keeps it)
#if defined(__OPTIMIZE__) || defined(_MSC_VER)
#define JSON_INTERNAL_SERIALIZER_INLINE JSON_HEDLEY_ALWAYS_INLINE
#else
#define JSON_INTERNAL_SERIALIZER_INLINE inline
#endif
// allow disabling exceptions // allow disabling exceptions
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
#define JSON_THROW(exception) throw exception #define JSON_THROW(exception) throw exception
@@ -11,7 +11,6 @@
// clean up // clean up
#undef JSON_ASSERT #undef JSON_ASSERT
#undef JSON_INTERNAL_CATCH #undef JSON_INTERNAL_CATCH
#undef JSON_INTERNAL_SERIALIZER_INLINE
#undef JSON_THROW #undef JSON_THROW
#undef JSON_PRIVATE_UNLESS_TESTED #undef JSON_PRIVATE_UNLESS_TESTED
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
@@ -265,7 +265,7 @@ class serializer
for a container; writing them from here spares each the entry and exit of for a container; writing them from here spares each the entry and exit of
that function. that function.
*/ */
JSON_INTERNAL_SERIALIZER_INLINE void dump_element(const BasicJsonType& val, JSON_HEDLEY_ALWAYS_INLINE void dump_element(const BasicJsonType& val,
const std::size_t current_indent, const std::size_t current_indent,
const std::size_t depth) const std::size_t depth)
{ {
@@ -971,7 +971,7 @@ class serializer
} }
/// write out the bytes pending in @ref string_buffer and reset @a bytes /// write out the bytes pending in @ref string_buffer and reset @a bytes
JSON_INTERNAL_SERIALIZER_INLINE void emit_pending(std::size_t& bytes) JSON_HEDLEY_ALWAYS_INLINE void emit_pending(std::size_t& bytes)
{ {
if (bytes != 0) if (bytes != 0)
{ {
@@ -983,7 +983,7 @@ class serializer
/// write buffer and reset index if fewer than 13 bytes are left, as this /// write buffer and reset index if fewer than 13 bytes are left, as this
/// is the maximal number of bytes to be written ("\uxxxx\uxxxx\0") for one /// is the maximal number of bytes to be written ("\uxxxx\uxxxx\0") for one
/// code point /// code point
JSON_INTERNAL_SERIALIZER_INLINE void reserve_string_buffer(std::size_t& bytes) JSON_HEDLEY_ALWAYS_INLINE void reserve_string_buffer(std::size_t& bytes)
{ {
if (string_buffer.size() - bytes < 13) if (string_buffer.size() - bytes < 13)
{ {
@@ -1344,7 +1344,7 @@ class serializer
inlining both into the pretty-printing loops once @ref dump_escaped inlining both into the pretty-printing loops once @ref dump_escaped
has grown, which made indented output up to 13% slower has grown, which made indented output up to 13% slower
*/ */
JSON_INTERNAL_SERIALIZER_INLINE void put_indent(std::size_t indent) JSON_HEDLEY_ALWAYS_INLINE void put_indent(std::size_t indent)
{ {
// closing braces at the outermost level ask for no indentation at all // closing braces at the outermost level ask for no indentation at all
if (indent == 0) if (indent == 0)
@@ -1398,7 +1398,7 @@ class serializer
its room and four stores of the indentation, see @ref put_short_literal_indent. its room and four stores of the indentation, see @ref put_short_literal_indent.
*/ */
template<std::size_t N> template<std::size_t N>
JSON_INTERNAL_SERIALIZER_INLINE void put_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) JSON_HEDLEY_ALWAYS_INLINE void put_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{ {
if (JSON_HEDLEY_LIKELY(put_short_literal_indent(s, indent))) if (JSON_HEDLEY_LIKELY(put_short_literal_indent(s, indent)))
{ {
@@ -1418,7 +1418,7 @@ class serializer
@a indent is wider or the write buffer lacks the room. @a indent is wider or the write buffer lacks the room.
*/ */
template<std::size_t N> template<std::size_t N>
JSON_INTERNAL_SERIALIZER_INLINE bool put_short_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) JSON_HEDLEY_ALWAYS_INLINE bool put_short_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{ {
constexpr std::size_t length = N - 1; constexpr std::size_t length = N - 1;
if (indent > 32 || write_buffer_pos + length + 32 > write_buffer.size()) if (indent > 32 || write_buffer_pos + length + 32 > write_buffer.size())
@@ -1445,7 +1445,7 @@ class serializer
write-through path for oversized runs. write-through path for oversized runs.
*/ */
template<std::size_t N> template<std::size_t N>
JSON_INTERNAL_SERIALIZER_INLINE void put_literal(const char (&s)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) JSON_HEDLEY_ALWAYS_INLINE void put_literal(const char (&s)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{ {
static_assert(N >= 2, "put_literal expects a non-empty string literal"); static_assert(N >= 2, "put_literal expects a non-empty string literal");
// the array bound counts the terminating NUL, which is not written // the array bound counts the terminating NUL, which is not written
+7 -18
View File
@@ -2603,16 +2603,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP
// detail/recursion_depth_limit.hpp. Like JSON_NO_THREAD_LOCAL it is neither part // detail/recursion_depth_limit.hpp. Like JSON_NO_THREAD_LOCAL it is neither part
// of the ABI tag nor undefined at the end of json.hpp. // of the ABI tag nor undefined at the end of json.hpp.
// forced inlining of the serializer's helpers only in optimized builds: at -O0,
// GCC and Clang give every inlined copy its own stack slots, which made the
// recursive frame of serializer::dump_container() about 2.3 KB (MSVC does not
// expand __forceinline at /Ob0, so it keeps it)
#if defined(__OPTIMIZE__) || defined(_MSC_VER)
#define JSON_INTERNAL_SERIALIZER_INLINE JSON_HEDLEY_ALWAYS_INLINE
#else
#define JSON_INTERNAL_SERIALIZER_INLINE inline
#endif
// allow disabling exceptions // allow disabling exceptions
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
#define JSON_THROW(exception) throw exception #define JSON_THROW(exception) throw exception
@@ -36995,7 +36985,7 @@ class serializer
for a container; writing them from here spares each the entry and exit of for a container; writing them from here spares each the entry and exit of
that function. that function.
*/ */
JSON_INTERNAL_SERIALIZER_INLINE void dump_element(const BasicJsonType& val, JSON_HEDLEY_ALWAYS_INLINE void dump_element(const BasicJsonType& val,
const std::size_t current_indent, const std::size_t current_indent,
const std::size_t depth) const std::size_t depth)
{ {
@@ -37701,7 +37691,7 @@ class serializer
} }
/// write out the bytes pending in @ref string_buffer and reset @a bytes /// write out the bytes pending in @ref string_buffer and reset @a bytes
JSON_INTERNAL_SERIALIZER_INLINE void emit_pending(std::size_t& bytes) JSON_HEDLEY_ALWAYS_INLINE void emit_pending(std::size_t& bytes)
{ {
if (bytes != 0) if (bytes != 0)
{ {
@@ -37713,7 +37703,7 @@ class serializer
/// write buffer and reset index if fewer than 13 bytes are left, as this /// write buffer and reset index if fewer than 13 bytes are left, as this
/// is the maximal number of bytes to be written ("\uxxxx\uxxxx\0") for one /// is the maximal number of bytes to be written ("\uxxxx\uxxxx\0") for one
/// code point /// code point
JSON_INTERNAL_SERIALIZER_INLINE void reserve_string_buffer(std::size_t& bytes) JSON_HEDLEY_ALWAYS_INLINE void reserve_string_buffer(std::size_t& bytes)
{ {
if (string_buffer.size() - bytes < 13) if (string_buffer.size() - bytes < 13)
{ {
@@ -38074,7 +38064,7 @@ class serializer
inlining both into the pretty-printing loops once @ref dump_escaped inlining both into the pretty-printing loops once @ref dump_escaped
has grown, which made indented output up to 13% slower has grown, which made indented output up to 13% slower
*/ */
JSON_INTERNAL_SERIALIZER_INLINE void put_indent(std::size_t indent) JSON_HEDLEY_ALWAYS_INLINE void put_indent(std::size_t indent)
{ {
// closing braces at the outermost level ask for no indentation at all // closing braces at the outermost level ask for no indentation at all
if (indent == 0) if (indent == 0)
@@ -38128,7 +38118,7 @@ class serializer
its room and four stores of the indentation, see @ref put_short_literal_indent. its room and four stores of the indentation, see @ref put_short_literal_indent.
*/ */
template<std::size_t N> template<std::size_t N>
JSON_INTERNAL_SERIALIZER_INLINE void put_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) JSON_HEDLEY_ALWAYS_INLINE void put_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{ {
if (JSON_HEDLEY_LIKELY(put_short_literal_indent(s, indent))) if (JSON_HEDLEY_LIKELY(put_short_literal_indent(s, indent)))
{ {
@@ -38148,7 +38138,7 @@ class serializer
@a indent is wider or the write buffer lacks the room. @a indent is wider or the write buffer lacks the room.
*/ */
template<std::size_t N> template<std::size_t N>
JSON_INTERNAL_SERIALIZER_INLINE bool put_short_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) JSON_HEDLEY_ALWAYS_INLINE bool put_short_literal_indent(const char (&s)[N], const std::size_t indent) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{ {
constexpr std::size_t length = N - 1; constexpr std::size_t length = N - 1;
if (indent > 32 || write_buffer_pos + length + 32 > write_buffer.size()) if (indent > 32 || write_buffer_pos + length + 32 > write_buffer.size())
@@ -38175,7 +38165,7 @@ class serializer
write-through path for oversized runs. write-through path for oversized runs.
*/ */
template<std::size_t N> template<std::size_t N>
JSON_INTERNAL_SERIALIZER_INLINE void put_literal(const char (&s)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) JSON_HEDLEY_ALWAYS_INLINE void put_literal(const char (&s)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{ {
static_assert(N >= 2, "put_literal expects a non-empty string literal"); static_assert(N >= 2, "put_literal expects a non-empty string literal");
// the array bound counts the terminating NUL, which is not written // the array bound counts the terminating NUL, which is not written
@@ -47895,7 +47885,6 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
// clean up // clean up
#undef JSON_ASSERT #undef JSON_ASSERT
#undef JSON_INTERNAL_CATCH #undef JSON_INTERNAL_CATCH
#undef JSON_INTERNAL_SERIALIZER_INLINE
#undef JSON_THROW #undef JSON_THROW
#undef JSON_PRIVATE_UNLESS_TESTED #undef JSON_PRIVATE_UNLESS_TESTED
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
+3 -9
View File
@@ -1,11 +1,6 @@
cmake_minimum_required(VERSION 3.30) # `import std;` (used by main.cpp) is supported without experimental opt-in
# since CMake 4.5: it is available to every target that scans for C++ modules.
# `import std;` (used by main.cpp) needs CMake's experimental C++ import-std cmake_minimum_required(VERSION 4.5)
# support. The accepted token is CMake-version-specific; this value matches the
# CMake version pinned in the ci_module_cpp20 CI jobs (4.3.x). If that pin is
# bumped, this token must be updated to match (configuration fails loudly
# otherwise).
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "451f2fe2-a8a2-47c3-bc32-94786d8fc91b")
project(json_test CXX) project(json_test CXX)
@@ -13,7 +8,6 @@ project(json_test CXX)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_MODULE_STD ON)
set(NLOHMANN_JSON_BUILD_MODULES ON CACHE BOOL "Enable nlohmann.json module support") set(NLOHMANN_JSON_BUILD_MODULES ON CACHE BOOL "Enable nlohmann.json module support")
+2 -2
View File
@@ -17,8 +17,8 @@ using namespace nlohmann::literals;
// Standard-library facilities are pulled in via `import std;` rather than // Standard-library facilities are pulled in via `import std;` rather than
// textual `#include`s: mixing `import` with textual standard headers does not // textual `#include`s: mixing `import` with textual standard headers does not
// compile under GCC's C++20 modules implementation, whereas `import std;` works // compile under GCC's C++20 modules implementation, whereas `import std;` works
// across GCC, Clang, and MSVC. This requires C++23 and CMake's (experimental) // across GCC, Clang, and MSVC. This requires C++23 and CMake 4.5 or newer;
// import-std support; see CMakeLists.txt. // see CMakeLists.txt.
int main() int main()
{ {
// basic_json / json: parsing and value access // basic_json / json: parsing and value access