diff --git a/.cirrus.yml b/.cirrus.yml index be6331506..c7f4c15e2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,15 +3,15 @@ arm_container: check_task: check_script: - - wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz - - tar xfz cmake-3.20.2.tar.gz - - cd cmake-3.20.2 - - ./configure - - make cmake ctest -j4 - - cd .. + # the gcc image ships an outdated CMake, so fetch a recent prebuilt binary + # instead of compiling CMake from source + - wget -q https://github.com/Kitware/CMake/releases/download/v4.3.4/cmake-4.3.4-linux-aarch64.tar.gz + - tar xfz cmake-4.3.4-linux-aarch64.tar.gz + - export PATH="$(pwd)/cmake-4.3.4-linux-aarch64/bin:$PATH" + - cmake --version - mkdir build - cd build - - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON + - cmake .. -DJSON_FastTests=ON - make -j4 - cd tests - - ../../cmake-3.20.2/bin/ctest -j4 + - ctest -j4 diff --git a/.github/config.yml b/.github/config.yml index 4e3217479..c67361263 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -13,7 +13,7 @@ sentimentBotReplyComment: > # *Required* Comment to reply with requestInfoReplyComment: > - We would appreciate it if you could provide us with more info about this issue or pull request! Please check the [issue template](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE.md) and the [pull request template](https://github.com/nlohmann/json/blob/develop/.github/PULL_REQUEST_TEMPLATE.md). + We would appreciate it if you could provide us with more info about this issue or pull request! Please check the [issue template](https://github.com/nlohmann/json/issues/new/choose) and the [pull request template](https://github.com/nlohmann/json/blob/develop/.github/PULL_REQUEST_TEMPLATE.md). # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given requestInfoLabelToAdd: "state: needs more info" diff --git a/.github/labeler.yml b/.github/labeler.yml index 024d3e6da..828660daf 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -23,11 +23,11 @@ labels: - label: "CI" files: - - "github/workflows/.*" + - ".github/workflows/.*" - label: "CI" files: - - "github/external_ci/.*" + - ".github/external_ci/.*" - label: "S" size-below: 10 diff --git a/.github/workflows/check_amalgamation.yml b/.github/workflows/check_amalgamation.yml index 903dee83b..480488af7 100644 --- a/.github/workflows/check_amalgamation.yml +++ b/.github/workflows/check_amalgamation.yml @@ -43,12 +43,14 @@ jobs: with: path: main ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false - name: Checkout tools uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: path: tools ref: develop + persist-credentials: false - name: Install astyle run: | diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index e1d7609c7..eb9f77fa6 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -13,6 +13,9 @@ jobs: with: egress-policy: audit + # The OSS-Fuzz CIFuzz actions are referenced via @master as recommended by + # the OSS-Fuzz documentation; the project does not publish tags or releases + # to pin to. See https://google.github.io/oss-fuzz/getting-started/continuous-integration/ - name: Build Fuzzers id: build uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6f328f527..436b6a47f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -33,6 +33,8 @@ jobs: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 8c9c71d66..59399d488 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -23,5 +23,7 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: 'Dependency Review' uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 diff --git a/.github/workflows/flawfinder.yml b/.github/workflows/flawfinder.yml index b452cd2e2..3ff26c4e5 100644 --- a/.github/workflows/flawfinder.yml +++ b/.github/workflows/flawfinder.yml @@ -33,6 +33,8 @@ jobs: - name: Checkout code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: flawfinder_scan uses: david-a-wheeler/flawfinder@c4216b74cf2639ffa98503768bd6e4299b5440c9 # v2.0.20 @@ -41,6 +43,6 @@ jobs: output: 'flawfinder_results.sarif' - name: Upload analysis results to GitHub Security tab - uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: sarif_file: ${{github.workspace}}/flawfinder_results.sarif diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index e311eb379..e4ee9295b 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -21,6 +21,6 @@ jobs: with: egress-policy: audit - - uses: srvaroa/labeler@e8fbb2561481ef6e711a770f0234e9379dc76892 # master + - uses: srvaroa/labeler@bf262763a8a8e191f5847873aecc0f29df84f957 # v1.14.0 env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 7e2e2d741..205628d51 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -17,60 +17,6 @@ permissions: contents: read jobs: -# macos-11 is deprecated -# macos-11: -# runs-on: macos-11 -# strategy: -# matrix: -# xcode: ['11.7', '12.4', '12.5.1', '13.0'] -# env: -# DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer -# -# steps: -# - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 -# - name: Run CMake -# run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -# - name: Build -# run: cmake --build build --parallel 10 -# - name: Test -# run: cd build ; ctest -j 10 --output-on-failure - -# macos-12 is deprecated (https://github.com/actions/runner-images/issues/10721) -# macos-12: -# runs-on: macos-12 # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md -# strategy: -# matrix: -# xcode: ['13.1', '13.2.1', '13.3.1', '13.4.1', '14.0', '14.0.1', '14.1'] -# env: -# DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer -# -# steps: -# - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 -# - name: Run CMake -# run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -# - name: Build -# run: cmake --build build --parallel 10 -# - name: Test -# run: cd build ; ctest -j 10 --output-on-failure - -# macos-13 is deprecated (https://github.com/actions/runner-images/issues/13046) -# macos-13: -# runs-on: macos-13 # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md -# strategy: -# matrix: -# xcode: ['14.1', '14.2', '14.3', '14.3.1', '15.0.1', '15.1', '15.2'] -# env: -# DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer -# -# steps: -# - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 -# - name: Run CMake -# run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON -# - name: Build -# run: cmake --build build --parallel 10 -# - name: Test -# run: cd build ; ctest -j 10 --output-on-failure - macos-14: runs-on: macos-14 # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md strategy: @@ -81,6 +27,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON - name: Build @@ -98,6 +46,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON - name: Build @@ -113,6 +63,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_TestStandards=${{ matrix.standard }} - name: Build diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index ec4d62940..559e6a58e 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -38,6 +38,8 @@ jobs: # Checkout project source - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false # Scan code using project's configuration on https://semgrep.dev/manage - uses: returntocorp/semgrep-action@713efdd345f3035192eaa63f56867b88e63e4e5d @@ -48,7 +50,7 @@ jobs: # Upload SARIF file generated in previous step - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: sarif_file: semgrep.sarif if: always() diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 72176c255..9e2a1f7b2 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -22,6 +22,8 @@ jobs: container: gcc:latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -34,6 +36,8 @@ jobs: container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -53,6 +57,8 @@ jobs: - name: Install Valgrind run: sudo apt-get update ; sudo apt-get install -y valgrind - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -70,6 +76,8 @@ jobs: - name: Install git, clang-tools, iwyu (ci_single_binaries), and unzip run: apt-get update ; apt-get install -y git clang-tools iwyu unzip - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -87,6 +95,8 @@ jobs: - name: Install build-essential run: apt-get update ; apt-get install -y build-essential unzip wget git libssl-dev - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -103,6 +113,8 @@ jobs: egress-policy: audit - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Install dependencies and de_DE locale run: | sudo apt-get clean @@ -134,6 +146,8 @@ jobs: container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On - name: Build @@ -148,6 +162,8 @@ jobs: container: gcc:${{ matrix.compiler }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -163,6 +179,8 @@ jobs: container: silkeh/clang:${{ matrix.compiler }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10 @@ -181,6 +199,8 @@ jobs: standard: [11, 14, 17, 20, 23, 26] steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -199,6 +219,8 @@ jobs: - name: Install git and unzip run: apt-get update ; apt-get install -y git unzip - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -215,6 +237,8 @@ jobs: container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -228,8 +252,23 @@ jobs: container: ${{ matrix.container }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Get latest CMake and ninja + with: + persist-credentials: false + # The module test uses `import std;`, which needs CMake's experimental + # import-std support. Its opt-in token is CMake-version-specific, so pin + # CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt. + - name: Get pinned CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 + with: + cmakeVersion: 4.3.4 + # 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 + # path — repoint it at the real module sources. + - name: Use libc++ and fix its module manifest path (Clang) + if: matrix.container == 'silkeh/clang:latest' + run: | + echo "CXXFLAGS=-stdlib=libc++" >> "$GITHUB_ENV" + mkdir -p /usr/lib/share && ln -sf /usr/lib/llvm-*/share/libc++ /usr/lib/share/libc++ - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -240,6 +279,8 @@ jobs: container: ghcr.io/nlohmann/json-ci:v2.2.0 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -258,6 +299,8 @@ jobs: - name: Install emscripten uses: mymindstorm/setup-emsdk@4528d102f7230f0e7b276855c01ea1159be0e984 # v16 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Get latest CMake and ninja uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 - name: Run CMake @@ -277,6 +320,8 @@ jobs: egress-policy: audit - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d37c53067..01f7a8f43 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -25,6 +25,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Set up MinGW uses: egor-tensin/setup-mingw@41b837e47d7f85214629d255b9c4bc3fcbe9fd63 # v3.0 with: @@ -48,6 +50,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Set extra CXX_FLAGS for latest std_version id: cxxflags run: | @@ -78,6 +82,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Install Clang run: curl -fsSL -o LLVM${{ matrix.version }}.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.version }}/LLVM-${{ matrix.version }}-win64.exe ; 7z x LLVM${{ matrix.version }}.exe -y -o"C:/Program Files/LLVM" - name: Set up MinGW @@ -106,6 +112,8 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Run CMake run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On - name: Build @@ -117,6 +125,15 @@ jobs: runs-on: windows-2022 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + # The module test uses `import std;`, which needs CMake's experimental + # import-std support. Its opt-in token is CMake-version-specific, so pin + # CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt. + - name: Get pinned CMake and ninja + uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4 + with: + cmakeVersion: 4.3.4 - name: Run CMake (Debug) run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_CI=ON -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" - name: Build diff --git a/CMakeLists.txt b/CMakeLists.txt index 6415b3838..9669946a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,11 @@ endif() ## ## set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) -include(ExternalProject) + +if (POLICY CMP0077) + # Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory. + cmake_policy(SET CMP0077 NEW) +endif () # ---- C++ Modules Support (optional) ---- option(NLOHMANN_JSON_BUILD_MODULES "Build C++ modules support" OFF) @@ -38,12 +42,7 @@ endif() ## OPTIONS ## -if (POLICY CMP0077) - # Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory. - cmake_policy(SET CMP0077 NEW) -endif () - -# VERSION_GREATER_EQUAL is not available in CMake 3.1 +# VERSION_GREATER_EQUAL is not available in older CMake (< 3.7) if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)) set(JSON_BuildTests_INIT ON) else() @@ -98,7 +97,7 @@ if (NOT JSON_ImplicitConversions) endif() if (JSON_DisableEnumSerialization) - message(STATUS "Enum integer serialization is disabled (JSON_DISABLE_ENUM_SERIALIZATION=0)") + message(STATUS "Enum integer serialization is disabled (JSON_DISABLE_ENUM_SERIALIZATION=1)") endif() if (JSON_LegacyDiscardedValueComparison) @@ -164,7 +163,7 @@ if (MSVC) endif() # Install a pkg-config file, so other tools can find this. -CONFIGURE_FILE( +configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" @ONLY @@ -174,9 +173,11 @@ CONFIGURE_FILE( ## TESTS ## create and configure the unit test target ## -if (JSON_BuildTests) +# Only build tests when JSON_BuildTests is set and testing has not been +# disabled by a parent project via BUILD_TESTING (see the CTest module, which +# also calls enable_testing()). +if (JSON_BuildTests AND (NOT DEFINED BUILD_TESTING OR BUILD_TESTING)) include(CTest) - enable_testing() add_subdirectory(tests) endif() @@ -212,7 +213,7 @@ if(JSON_Install) install( FILES ${NLOHMANN_NATVIS_FILE} DESTINATION . - ) + ) endif() export( TARGETS ${NLOHMANN_JSON_TARGET_NAME} diff --git a/FILES.md b/FILES.md index 91326ab6a..b68167336 100644 --- a/FILES.md +++ b/FILES.md @@ -9,6 +9,30 @@ This file describes the source for supporting files; that is, files that are not ## Continuous Integration +### `.github/workflows` + +The [GitHub Actions](https://docs.github.com/en/actions) workflows that build, test, and analyze the library. Each file in this folder defines one workflow: + +- `ubuntu.yml`, `macos.yml`, `windows.yml` — build and run the test suite on Linux, macOS, and Windows. +- `check_amalgamation.yml` — verify that the single-header amalgamation in `single_include` is up to date on pull requests. +- `comment_check_amalgamation.yml` — comment on a pull request when the amalgamation check failed. +- `cifuzz.yml` — run short fuzzing sessions via [OSS-Fuzz CIFuzz](https://google.github.io/oss-fuzz/getting-started/continuous-integration/) on pull requests. +- `codeql-analysis.yml` — run [CodeQL](https://codeql.github.com) code scanning. +- `flawfinder.yml` — run the [Flawfinder](https://dwheeler.com/flawfinder/) static analysis. +- `semgrep.yml` — run [Semgrep](https://semgrep.dev) static analysis. +- `scorecards.yml` — run the [OpenSSF Scorecard](https://securityscorecards.dev) supply-chain security checks. +- `dependency-review.yml` — scan dependency changes in pull requests for known vulnerabilities. +- `labeler.yml` — the "Pull Request Labeler" workflow (see `.github/labeler.yml`). +- `stale.yml` — comment on and close stale issues and pull requests. +- `publish_documentation.yml` — build and publish the documentation on every merge to the `develop` branch. + +Further documentation: + +- [Workflow syntax for GitHub Actions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) + +> [!IMPORTANT] +> The folder `.github/workflows` is predetermined by GitHub. + ### `.cirrus.yml` Configuration file for the pipeline at [Cirrus CI](https://cirrus-ci.com/github/nlohmann/json). @@ -123,7 +147,7 @@ Further documentation: > [!IMPORTANT] > The folder `.github/ISSUE_TEMPLATE` is predetermined by GitHub. -### `.github/ISSUE_TEMPLATE/config.yaml` +### `.github/ISSUE_TEMPLATE/config.yml` Issue template chooser configuration. The file is used to configure the dialog when a new issue is created. @@ -132,7 +156,7 @@ Further documentation: - [Configuring issue templates for your repository](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository) > [!IMPORTANT] -> The filename `.github/ISSUE_TEMPLATE/config.yaml` is predetermined by GitHub. +> The filename `.github/ISSUE_TEMPLATE/config.yml` is predetermined by GitHub. ### `.github/labeler.yml` @@ -165,7 +189,7 @@ Further documentation: - [Adding a security policy to your repository](https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository) > [!IMPORTANT] -> The filename `.github/SECURITY.yml` is predetermined by GitHub. +> The filename `.github/SECURITY.md` is predetermined by GitHub. > [!NOTE] > The file is part of the documentation and is included in `docs/mkdocs/docs/community/security_policy.md`. @@ -234,6 +258,16 @@ make BUILD.bazel ### `meson.build` +The build definition for the [Meson](https://mesonbuild.com) build system. + ### `Package.swift` -### `WORKSPACE.bazel` +The package manifest for the [Swift Package Manager](https://www.swift.org/package-manager/). + +### `MODULE.bazel` + +The module definition for [Bazel](https://bazel.build)'s [Bzlmod](https://bazel.build/external/module) dependency system. It complements `BUILD.bazel` and replaces the previously used `WORKSPACE.bazel`. + +Further documentation: + +- [Bazel modules](https://bazel.build/external/module) diff --git a/Makefile b/Makefile index fa2e5a54e..d99d6f5f3 100644 --- a/Makefile +++ b/Makefile @@ -205,7 +205,7 @@ json.tar.xz: # We use `-X` to make the resulting ZIP file reproducible, see # . include.zip: BUILD.bazel - zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel WORKSPACE.bazel meson.build LICENSE.MIT + zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT # Create the files for a release and add signatures and hashes. release: include.zip json.tar.xz diff --git a/README.md b/README.md index 97ac8f451..81b54c36b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/1mp10JbaANo6FUc7) [![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://json.nlohmann.me) -[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) +[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/develop/LICENSE.MIT) [![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) [![Packaging status](https://repology.org/badge/tiny-repos/nlohmann-json.svg)](https://repology.org/project/nlohmann-json/versions) [![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases) @@ -70,7 +70,7 @@ Other aspects were not so important to us: - **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set. -See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. +See the [contribution guidelines](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md#please-dont) for more information. ## Sponsors @@ -429,6 +429,8 @@ struct MyIterator { using reference = const char&; using iterator_category = std::input_iterator_tag; + explicit MyIterator(MyContainer* tgt = nullptr) : target(tgt) {} + MyIterator& operator++() { target->advance(); return *this; @@ -450,12 +452,12 @@ MyIterator begin(MyContainer& tgt) { } MyIterator end(const MyContainer&) { - return {}; + return MyIterator{}; } void foo() { MyContainer c; - json j = json::parse(c); + json j = json::parse(begin(c), end(c)); } ``` @@ -756,9 +758,9 @@ int i = 42; json jn = i; auto f = jn.get(); // NOT RECOMMENDED -double f2 = jb; +double f2 = jn; double f3; -f3 = jb; +f3 = jn; // etc. ``` @@ -1465,7 +1467,7 @@ I deeply appreciate the help of the following people. 57. [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types. 58. [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. 59. [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. -60. [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. +60. [ukhegg](https://github.com/ukhegg) proposed an improvement for the examples section. 61. [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README. 62. [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. 63. [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. @@ -1839,7 +1841,7 @@ The library supports **Unicode input** as follows: This library does not support comments by default. It does so for three reasons: 1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript. -2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012: +2. This was not an oversight: Douglas Crockford [wrote on this](https://news.ycombinator.com/item?id=3912149) in May 2012: > I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't. > @@ -1847,7 +1849,7 @@ This library does not support comments by default. It does so for three reasons: 3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this. -However, you can set set parameter `ignore_comments` to true in the `parse` function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace. +However, you can set parameter `ignore_comments` to true in the `parse` function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace. ### Trailing commas diff --git a/cmake/download_test_data.cmake b/cmake/download_test_data.cmake index 6f63a08ac..b7211ac54 100644 --- a/cmake/download_test_data.cmake +++ b/cmake/download_test_data.cmake @@ -12,7 +12,7 @@ else() # create a header with the path to the downloaded test data file(WRITE ${CMAKE_BINARY_DIR}/include/test_data.hpp "#define TEST_DATA_DIRECTORY \"${CMAKE_BINARY_DIR}/test_files\"\n") - # download test data from GitHub release + # download test data from the GitHub tag source archive ExternalProject_Add(download_test_data_project URL "${JSON_TEST_DATA_URL}/archive/refs/tags/v${JSON_TEST_DATA_VERSION}.zip" SOURCE_DIR "${CMAKE_BINARY_DIR}/test_files" @@ -32,13 +32,17 @@ endif() # determine the operating system (for debug and support purposes) find_program(UNAME_COMMAND uname) -find_program(VER_COMMAND ver) find_program(LSB_RELEASE_COMMAND lsb_release) find_program(SW_VERS_COMMAND sw_vers) set(OS_VERSION_STRINGS "${CMAKE_SYSTEM}") -if (VER_COMMAND) - execute_process(COMMAND ${VER_COMMAND} OUTPUT_VARIABLE VER_COMMAND_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) - set(OS_VERSION_STRINGS "${OS_VERSION_STRINGS}; ${VER_COMMAND_RESULT}") +if (CMAKE_HOST_WIN32) + # "ver" is a cmd.exe builtin rather than a standalone executable, so it + # cannot be located with find_program and must be invoked through cmd + execute_process(COMMAND cmd /c ver OUTPUT_VARIABLE VER_COMMAND_RESULT ERROR_QUIET) + string(STRIP "${VER_COMMAND_RESULT}" VER_COMMAND_RESULT) + if (VER_COMMAND_RESULT) + set(OS_VERSION_STRINGS "${OS_VERSION_STRINGS}; ${VER_COMMAND_RESULT}") + endif() endif() if (SW_VERS_COMMAND) execute_process(COMMAND ${SW_VERS_COMMAND} OUTPUT_VARIABLE SW_VERS_COMMAND_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) diff --git a/cmake/test.cmake b/cmake/test.cmake index 7105b97c3..5922c5106 100644 --- a/cmake/test.cmake +++ b/cmake/test.cmake @@ -35,6 +35,8 @@ foreach(feature ${CMAKE_CXX_COMPILE_FEATURES}) set(compiler_supports_cpp_20 TRUE) elseif (${feature} STREQUAL cxx_std_23) set(compiler_supports_cpp_23 TRUE) + elseif (${feature} STREQUAL cxx_std_26) + set(compiler_supports_cpp_26 TRUE) endif() endforeach() @@ -92,7 +94,6 @@ function(json_test_set_test_options tests) target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS}) target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES}) target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS}) - #set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}") set_property(DIRECTORY PROPERTY ${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}" ) @@ -102,7 +103,6 @@ endfunction() # for internal use by _json_test_add_test() function(_json_test_apply_test_properties test_target properties_target) - #get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES) get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES) if(test_properties) set_tests_properties(${test_target} PROPERTIES ${test_properties}) @@ -213,10 +213,10 @@ function(json_test_add_test_for file) if("${args_NAME}" STREQUAL "") get_filename_component(file_basename ${file} NAME_WE) - string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename}) + string(REGEX REPLACE "unit-(.+)" "test-\\1" test_name ${file_basename}) else() set(test_name ${args_NAME}) - if(NOT test_name MATCHES "test-[^$]+") + if(NOT test_name MATCHES "test-.+") message(FATAL_ERROR "Test name must start with 'test-'.") endif() endif() diff --git a/docs/mkdocs/docs/api/basic_json/dump.md b/docs/mkdocs/docs/api/basic_json/dump.md index e92c2d5a0..1334d8eee 100644 --- a/docs/mkdocs/docs/api/basic_json/dump.md +++ b/docs/mkdocs/docs/api/basic_json/dump.md @@ -27,8 +27,8 @@ and `ensure_ascii` parameters. `error_handler` (in) : how to react on decoding errors; there are three possible values (see [`error_handler_t`](error_handler_t.md): `strict` (throws an exception in case a decoding error occurs; default), `replace` (replace invalid UTF-8 sequences - with U+FFFD), and `ignore` (ignore invalid UTF-8 sequences during serialization; all bytes are copied to the output - unchanged)). + with U+FFFD), and `ignore` (ignore invalid UTF-8 sequences during serialization; all valid bytes are copied to the + output unchanged, and invalid bytes are dropped)). ## Return value diff --git a/docs/mkdocs/docs/api/basic_json/error_handler_t.md b/docs/mkdocs/docs/api/basic_json/error_handler_t.md index dc32ced9b..f20c33c03 100644 --- a/docs/mkdocs/docs/api/basic_json/error_handler_t.md +++ b/docs/mkdocs/docs/api/basic_json/error_handler_t.md @@ -18,7 +18,7 @@ replace : replace invalid UTF-8 sequences with U+FFFD (� REPLACEMENT CHARACTER) ignore -: ignore invalid UTF-8 sequences; all bytes are copied to the output unchanged +: ignore invalid UTF-8 sequences; all valid bytes are copied to the output unchanged, and invalid bytes are dropped ## Examples diff --git a/docs/mkdocs/docs/community/quality_assurance.md b/docs/mkdocs/docs/community/quality_assurance.md index 7ddd93871..4282163da 100644 --- a/docs/mkdocs/docs/community/quality_assurance.md +++ b/docs/mkdocs/docs/community/quality_assurance.md @@ -17,9 +17,9 @@ violations will result in a failed build. | Compiler | Architecture | Operating System | CI | |----------------------------------------------|--------------|-----------------------------------|-----------| - | AppleClang 15.0.0.15000040; Xcode 15.0.1 | x86_64 | macOS 13.7.2 (Ventura) | GitHub | - | AppleClang 15.0.0.15000100; Xcode 15.1 | x86_64 | macOS 13.7.2 (Ventura) | GitHub | - | AppleClang 15.0.0.15000100; Xcode 15.2 | x86_64 | macOS 13.7.2 (Ventura) | GitHub | + | 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 | @@ -28,6 +28,7 @@ violations will result in a failed build. | 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 | @@ -60,7 +61,8 @@ violations will result in a failed build. | 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.0.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | + | Clang 21.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | + | CUDA 11.0.221 (nvcc) | x86_64 | Ubuntu 20.04 LTS | GitHub | | Emscripten 4.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 4.8.5 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | | GNU 4.9.3 | x86_64 | Ubuntu 22.04.1 LTS | GitHub | @@ -79,8 +81,9 @@ violations will result in a failed build. | 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 14.2.0 | arm64 | Linux 6.1.100 | Cirrus CI | | 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 | Linux 6.1.100 | Cirrus CI | | icpc (ICC) 2021.5.0 20211109 | x86_64 | Ubuntu 20.04.3 LTS | GitHub | | MSVC 19.0.24241.7 | x86 | Windows 8.1 | AppVeyor | | MSVC 19.16.27035.0 | x86 | Windows-10 (Build 14393) | AppVeyor | diff --git a/docs/mkdocs/docs/features/comments.md b/docs/mkdocs/docs/features/comments.md index a4c2adf19..dec04e38a 100644 --- a/docs/mkdocs/docs/features/comments.md +++ b/docs/mkdocs/docs/features/comments.md @@ -3,7 +3,7 @@ This library does not support comments *by default*. It does so for three reasons: 1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript. -2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012: +2. This was not an oversight: Douglas Crockford [wrote on this](https://news.ycombinator.com/item?id=3912149) in May 2012: > I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't. diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index fefc750fd..28f203458 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -86,6 +86,21 @@ */ NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +// Trait to detect std::optional specializations. It is defined here rather +// than in type_traits.hpp so that adding the include does not change +// the include order of the C++20 module's global module fragment (the include +// is already pulled in by the conversion headers above); see src/modules/json.cppm. +template +struct is_std_optional : std::false_type {}; + +#ifdef JSON_HAS_CPP_17 +template +struct is_std_optional> : std::true_type {}; +#endif +} // namespace detail + /*! @brief a class to store JSON values @@ -1937,6 +1952,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #endif #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI detail::negation>, +#endif +#if defined(JSON_HAS_CPP_17) + // std::optional can construct itself from basic_json; excluding it + // here avoids an ambiguity with that constructor (e.g., under C++26) + detail::negation>, #endif detail::is_detected_lazy >::value, int >::type = 0 > diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0e23b09a6..617e97ff1 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -20604,6 +20604,21 @@ NLOHMANN_JSON_NAMESPACE_END */ NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +// Trait to detect std::optional specializations. It is defined here rather +// than in type_traits.hpp so that adding the include does not change +// the include order of the C++20 module's global module fragment (the include +// is already pulled in by the conversion headers above); see src/modules/json.cppm. +template +struct is_std_optional : std::false_type {}; + +#ifdef JSON_HAS_CPP_17 +template +struct is_std_optional> : std::true_type {}; +#endif +} // namespace detail + /*! @brief a class to store JSON values @@ -22455,6 +22470,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #endif #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI detail::negation>, +#endif +#if defined(JSON_HAS_CPP_17) + // std::optional can construct itself from basic_json; excluding it + // here avoids an ambiguity with that constructor (e.g., under C++26) + detail::negation>, #endif detail::is_detected_lazy >::value, int >::type = 0 > diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2620d9655..41301ab67 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13...3.14) +cmake_minimum_required(VERSION 3.13...4.0) option(JSON_Valgrind "Execute test suite with Valgrind." OFF) option(JSON_FastTests "Skip expensive/slow tests." OFF) @@ -148,9 +148,9 @@ message(STATUS "${msg}") # *DO* use json_test_set_test_options() above this line json_test_should_build_32bit_test(json_32bit_test json_32bit_test_only "${JSON_32bitTest}") -file(GLOB files src/unit-*.cpp) +file(GLOB files CONFIGURE_DEPENDS src/unit-*.cpp) if(json_32bit_test_only) - set(files src/unit-32bit.cpp) + set(files src/unit-32bit.cpp) elseif(NOT json_32bit_test) list(FILTER files EXCLUDE REGEX src/unit-32bit.cpp) endif() diff --git a/tests/module_cpp20/CMakeLists.txt b/tests/module_cpp20/CMakeLists.txt index b6d395aaa..92d4b27e0 100644 --- a/tests/module_cpp20/CMakeLists.txt +++ b/tests/module_cpp20/CMakeLists.txt @@ -1,19 +1,28 @@ -cmake_minimum_required(VERSION 3.28) +cmake_minimum_required(VERSION 3.30) + +# `import std;` (used by main.cpp) needs CMake's experimental C++ import-std +# 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) +# import std; requires C++23 and the std library module +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_MODULE_STD ON) + set(NLOHMANN_JSON_BUILD_MODULES ON CACHE BOOL "Enable nlohmann.json module support") add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/tests) add_executable(json_test main.cpp) -target_link_libraries(json_test - PRIVATE +target_link_libraries(json_test + PRIVATE nlohmann_json_modules ) -target_compile_definitions(json_test - PRIVATE NLOHMANN_JSON_BUILD_MODULES -) - -target_compile_features(json_test PUBLIC cxx_std_20) +target_compile_features(json_test PRIVATE cxx_std_23) diff --git a/tests/module_cpp20/main.cpp b/tests/module_cpp20/main.cpp index 9a2f3d360..390398f1b 100644 --- a/tests/module_cpp20/main.cpp +++ b/tests/module_cpp20/main.cpp @@ -6,9 +6,54 @@ // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann // SPDX-License-Identifier: MIT +import std; import nlohmann.json; +using namespace nlohmann::literals; + +// Exercise the surface exported by the nlohmann.json module so that a missing +// or broken export is caught at compile time. +// +// Standard-library facilities are pulled in via `import std;` rather than +// textual `#include`s: mixing `import` with textual standard headers does not +// 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) +// import-std support; see CMakeLists.txt. int main() { - nlohmann::json j; + // basic_json / json: parsing and value access + nlohmann::json j = nlohmann::json::parse(R"({"a": 1, "list": [1, 2, 3]})"); + const int a = j["a"].get(); + + // json_pointer and operator""_json_pointer + nlohmann::json_pointer ptr = "/list/2"_json_pointer; + const int last = j[ptr].get(); + + // operator""_json literal + const nlohmann::json lit = R"([1, 2, 3])"_json; + + // ordered_json + nlohmann::ordered_json oj; + oj["b"] = 2; + const int b = oj["b"].get(); + + // ordered_map alias + nlohmann::ordered_map m; + m["x"] = 1; + + // adl_serializer (reference the exported template) + using serializer = nlohmann::adl_serializer; + static_cast(sizeof(serializer)); + + // to_string + const std::string dumped = nlohmann::to_string(j); + + // operator<< (hidden friend, reached via ADL through the module) + std::ostringstream os; + os << j << oj << lit; + + // use every result so the references cannot be optimized away + return (a == 1 && last == 3 && b == 2 && lit.size() == 3 + && m.size() == 1 && !dumped.empty() && !os.str().empty()) + ? 0 : 1; }