diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index dc604bde8..9e2a1f7b2 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -247,18 +247,28 @@ jobs: ci_module_cpp20: strategy: matrix: - # Only Clang for now: GCC's C++20 modules support (as of GCC 16.1) cannot - # compile non-trivial use of the imported module (redefinition / missing - # include errors in libstdc++). - container: ['silkeh/clang:latest'] + container: ['gcc:latest', 'silkeh/clang:latest'] runs-on: ubuntu-latest container: ${{ matrix.container }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - name: Get latest CMake and ninja + # 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 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c2da1a8da..01f7a8f43 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -127,6 +127,13 @@ jobs: - 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/tests/module_cpp20/CMakeLists.txt b/tests/module_cpp20/CMakeLists.txt index 6b5cb1881..92d4b27e0 100644 --- a/tests/module_cpp20/CMakeLists.txt +++ b/tests/module_cpp20/CMakeLists.txt @@ -1,7 +1,20 @@ -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) @@ -12,4 +25,4 @@ target_link_libraries(json_test nlohmann_json_modules ) -target_compile_features(json_test PRIVATE 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 56384b9af..390398f1b 100644 --- a/tests/module_cpp20/main.cpp +++ b/tests/module_cpp20/main.cpp @@ -6,22 +6,19 @@ // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann // SPDX-License-Identifier: MIT +import std; import nlohmann.json; -#include -#include - using namespace nlohmann::literals; -// This test exercises the surface exported by the nlohmann.json module so that -// a missing or broken export is caught at compile time. +// Exercise the surface exported by the nlohmann.json module so that a missing +// or broken export is caught at compile time. // -// NOTE: It is only built with Clang. GCC's C++20 modules implementation (as of -// GCC 16.1) cannot compile non-trivial use of the imported module: any standard -// library facility reached through the module triggers redefinition or missing -// include errors in libstdc++ (and using `import` together with textual -// `#include`s of standard headers fails as well). The ci_module_cpp20 job is -// therefore restricted to Clang until GCC's modules support matures. +// 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() { // basic_json / json: parsing and value access