Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/boost-asio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ jobs:
- { name: clang, version: 17 }
- { name: clang, version: 18 }
- { name: clang, version: 20 }
- { name: gcc, version: 12 }
- { name: gcc, version: 13 }
- { name: gcc, version: 14 }
boost_version: [1.88.0, 1.73.0]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gcc-erlang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
gcc: [12, 13, 14]
gcc: [13, 14]
build_type: [Debug]
std: [23]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gcc-x86.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
gcc: [12, 13, 14]
gcc: [13, 14]
build_type: [Debug]
std: [23]

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
gcc: [12, 13, 14]
gcc: [13, 14]
build_type: [Debug]
std: [23]

Expand Down
112 changes: 112 additions & 0 deletions .github/workflows/modules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: C++20 Modules

on:
push:
branches:
- main
- feature/*
paths-ignore:
- '**/*.md'
- 'docs/**'
pull_request:
branches:
- main
paths-ignore:
- '**/*.md'
- 'docs/**'
workflow_dispatch:

jobs:
clang-modules:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
clang: [20]
build_type: [Release]
std: [23]

env:
CC: clang-${{matrix.clang}}
CXX: clang++-${{matrix.clang}}
LLVM_VERSION: ${{matrix.clang}}

steps:
- uses: actions/checkout@v4

- name: Install Clang and Ninja
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${{matrix.clang}} main" | sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt-get clean
sudo apt-get update
sudo apt-get install -y --fix-missing clang-${{matrix.clang}} libc++-${{matrix.clang}}-dev libc++abi-${{matrix.clang}}-dev ninja-build

- name: Set path for clang
run: |
echo "PATH=/usr/lib/llvm-${{matrix.clang}}/bin:$PATH" >> $GITHUB_ENV
clang-${{matrix.clang}} --version
clang++-${{matrix.clang}} --version

- name: Configure CMake with Modules
run: |
cmake -B ${{github.workspace}}/build -G Ninja \
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
-DCMAKE_C_COMPILER=${{env.CC}} \
-DCMAKE_CXX_COMPILER=${{env.CXX}} \
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ -lc++abi" \
-Dglaze_BUILD_MODULES=ON

- name: Build Module Tests
run: cmake --build build --target json_module_test -j $(nproc)

- name: Run Module Tests
run: ./build/tests/module_test/json_module_test

gcc-modules:
runs-on: ubuntu-24.04
container:
image: gcc:15

strategy:
fail-fast: false
matrix:
build_type: [Release]
std: [23]

env:
CC: gcc
CXX: g++

steps:
- name: Install build dependencies
env:
DEBIAN_FRONTEND: noninteractive
run: |
apt-get update
apt-get install -y --no-install-recommends \
ca-certificates \
cmake \
git \
libssl-dev \
ninja-build \
python3
update-ca-certificates

- uses: actions/checkout@v4

- name: Configure CMake with Modules
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
-Dglaze_BUILD_MODULES=ON

- name: Build Module Tests
run: cmake --build build --target json_module_test -j $(nproc)

- name: Run Module Tests
run: ./build/tests/module_test/json_module_test
47 changes: 47 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,53 @@ target_include_directories(
INTERFACE "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
)

option(glaze_BUILD_MODULES "Build C++20 module targets (requires CMake 3.28+)" OFF)

if(glaze_BUILD_MODULES)
message(STATUS "Building with C++20 module support")

if(CMAKE_VERSION VERSION_LESS "3.28")
message(FATAL_ERROR "glaze_BUILD_MODULES requires CMake 3.28 or later")
endif()

# Compiler compatibility warnings
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "15")
message(WARNING "GCC 15+ recommended for C++20 modules")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "20")
message(WARNING "Clang 20+ recommended for C++20 modules")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
message(WARNING "Apple Clang does not support CMake's module dependency scanning. Use LLVM Clang instead.")
endif()

# JSON module target
add_library(glaze_json_module)
add_library(glaze::json_module ALIAS glaze_json_module)

target_sources(glaze_json_module
PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:include>"
FILES "${PROJECT_SOURCE_DIR}/include/glaze/module/glaze_json.cppm"
)

target_compile_features(glaze_json_module PUBLIC cxx_std_23)
target_include_directories(glaze_json_module
PUBLIC "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
)
target_link_libraries(glaze_json_module PUBLIC glaze::glaze)

set_target_properties(glaze_json_module PROPERTIES
EXPORT_NAME json_module
CXX_SCAN_FOR_MODULES ON
)
endif()

if(NOT CMAKE_SKIP_INSTALL_RULES)
include(cmake/install-rules.cmake)
endif()
Expand Down
10 changes: 10 additions & 0 deletions cmake/install-rules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ install(
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

# Install module targets when modules are enabled
if(glaze_BUILD_MODULES)
install(
TARGETS glaze_json_module
EXPORT glazeTargets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
FILE_SET CXX_MODULES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
endif()

write_basic_package_version_file(
"${package}ConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
Expand Down
113 changes: 112 additions & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This guide covers some of the ways to install and integrate the Glaze JSON libra
### Compiler Support
- **C++23** standard required
- **Clang 17+**
- **GCC 12+**
- **GCC 13+**
- **MSVC 2022+**
- **Apple Clang (latest Xcode)**

Expand Down Expand Up @@ -165,6 +165,117 @@ For cross-compilation to ARM or other architectures:
set(glaze_ENABLE_AVX2 OFF)
```

## C++20 Module Support

Glaze provides opt-in C++20 module wrappers for cleaner imports and potentially faster compile times.

### Requirements

- **CMake 3.28+** (for `FILE_SET CXX_MODULES` support)
- **Ninja** or **Visual Studio 17.4+** generator (Make does not support modules)
- **Compiler with C++20 module support**:
- LLVM Clang 20+ with libc++ (recommended)
- GCC 15+ (Linux only)
- MSVC 19.34+ (VS 2022 17.4+)

> **Note:** Apple Clang is not supported for modules. See [Troubleshooting](#troubleshooting) for platform-specific guidance.

### Enabling Modules

```cmake
cmake_minimum_required(VERSION 3.28)
project(MyProject LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)

include(FetchContent)
FetchContent_Declare(
glaze
GIT_REPOSITORY https://github.com/stephenberry/glaze.git
GIT_TAG main
GIT_SHALLOW TRUE
)

# Enable module support (set cache entry before the project loads)
set(glaze_BUILD_MODULES ON CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(glaze)

add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE glaze::json_module)

# Enable module scanning for your target
set_target_properties(myapp PROPERTIES CXX_SCAN_FOR_MODULES ON)
```

### Building with Modules

Modules require the Ninja generator:

```bash
cmake -B build -G Ninja -Dglaze_BUILD_MODULES=ON
cmake --build build
```

### Usage

When using modules, include standard library headers **before** the module import to avoid ODR conflicts:

```cpp
// Standard headers first
#include <string>
#include <vector>

// Then import the module
import glaze.json;

struct Person {
std::string name;
int age;
};

int main() {
Person person{"John", 30};

// Write to JSON
auto json = glz::write_json(person);
if (json) {
std::cout << json.value() << std::endl;
}

// Read from JSON
auto result = glz::read_json<Person>(R"({"name":"Jane","age":25})");
if (result) {
std::cout << result->name << std::endl;
}
}
```

### macOS with LLVM Clang

On macOS, use Homebrew's LLVM Clang (not Apple Clang) and set the SDK path:

```bash
SDKROOT=$(xcrun --show-sdk-path)
cmake -B build -G Ninja \
-DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ \
-DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang \
-DCMAKE_OSX_SYSROOT="$SDKROOT" \
-Dglaze_BUILD_MODULES=ON
cmake --build build
```

### Troubleshooting

**"The compiler does not provide a way to discover import graph dependencies"**
- Apple Clang does not support CMake's module dependency scanning (P1689)
- Solution: Use LLVM Clang 20+ installed via Homebrew on macOS

**Module not found / import errors**
- Ensure you're using the Ninja generator (`-G Ninja`)
- Make generators do not support C++20 modules
- Ensure `glaze_BUILD_MODULES=ON` is set before `FetchContent_MakeAvailable`

## Example Project Setup

### Complete CMakeLists.txt Example
Expand Down
2 changes: 1 addition & 1 deletion include/glaze/core/reflect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ namespace glz
template <class T>
constexpr auto make_enum_to_string_map()
{
constexpr auto N = reflect<T>::size;
static constexpr auto N = reflect<T>::size;
return [&]<size_t... I>(std::index_sequence<I...>) {
using key_t = std::underlying_type_t<T>;
return normal_map<key_t, sv, N>(std::array<pair<key_t, sv>, N>{
Expand Down
Loading
Loading