Skip to content

Commit b7f7411

Browse files
Add proper C++20 module support (#4799)
1 parent d70e46b commit b7f7411

File tree

10 files changed

+123
-24
lines changed

10 files changed

+123
-24
lines changed

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ endif()
2222
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
2323
include(ExternalProject)
2424

25+
# ---- C++ Modules Support (optional) ----
26+
option(NLOHMANN_JSON_BUILD_MODULES "Build C++ modules support" OFF)
27+
28+
if(NLOHMANN_JSON_BUILD_MODULES)
29+
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
30+
message(STATUS "Building nlohmann.json C++ module")
31+
add_subdirectory(src/modules)
32+
else()
33+
message(WARNING "Skipping nlohmann.json C++ module (requires CMake 3.28+, found ${CMAKE_VERSION})")
34+
endif()
35+
endif()
36+
2537
##
2638
## OPTIONS
2739
##

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ std::ifstream f("example.json");
158158
json data = json::parse(f);
159159
```
160160
161+
If using modules (enabled with `NLOHMANN_JSON_BUILD_MODULES`), this example becomes:
162+
```cpp
163+
import std;
164+
import nlohmann.json;
165+
166+
using json = nlohmann::json;
167+
168+
// ...
169+
170+
std::ifstream f("example.json");
171+
json data = json::parse(f);
172+
```
173+
161174
### Creating `json` objects from JSON literals
162175

163176
Assume you want to create hard-code this literal JSON value in a file, as a `json` object:

cmake/ci.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,8 @@ add_custom_target(ci_cuda_example
665665

666666
add_custom_target(ci_module_cpp20
667667
COMMAND ${CMAKE_COMMAND}
668-
-DCMAKE_BUILD_TYPE=Debug -GNinja
668+
-DCMAKE_BUILD_TYPE=Debug -GNinja
669+
-DJSON_CI=ON -DNLOHMANN_JSON_BUILD_MODULES=ON -DJSON_Install=ON
669670
-S${PROJECT_SOURCE_DIR}/tests/module_cpp20 -B${PROJECT_BINARY_DIR}/ci_module_cpp20
670671
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/ci_module_cpp20
671672
)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Modules
2+
3+
This library has experimental support for C++ modules, introduced in C++20. The library can be imported by writing `import nlohmann.json;` instead of `#include <nlohmann/json.hpp>`.
4+
5+
Please be aware that the module is experimental and a full test is outstanding, and the exported symbols are subject to change.
6+
7+
## Requirements
8+
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.
9+
10+
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.
11+
12+
## Example
13+
When using modules rather than headers, the previous example for creating a `json` object through a JSON file, would instead be:
14+
```cpp
15+
import std;
16+
import nlohmann.json;
17+
18+
using json = nlohmann::json;
19+
20+
// ...
21+
22+
std::ifstream f("example.json");
23+
json data = json::parse(f);
24+
```
25+
26+
## Modules do not export macros
27+
It should be noted that as modules do not export macros, the `nlohmann.json` module will not export any macros, but rather only the following symbols:
28+
- `nlohmann::adl_serializer`
29+
- `nlohmann::basic_json`
30+
- `nlohmann::json`
31+
- `nlohmann::json_pointer`
32+
- `nlohmann::ordered_map`
33+
- `nlohmann::ordered_json`

docs/mkdocs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ nav:
7777
- features/json_pointer.md
7878
- features/json_patch.md
7979
- features/merge_patch.md
80+
- features/modules.md
8081
- 'nlohmann Namespace': features/namespace.md
8182
- features/object_order.md
8283
- Parsing:

src/modules/CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required(VERSION 3.28)
2+
3+
add_library(nlohmann_json_modules)
4+
5+
set(NLOHMANN_JSON_MODULES
6+
json.cppm
7+
)
8+
9+
if(NOT COMMAND configure_cpp_module_target)
10+
function(configure_cpp_module_target target)
11+
target_sources(${target} PUBLIC FILE_SET CXX_MODULES FILES ${NLOHMANN_JSON_MODULES})
12+
endfunction()
13+
endif()
14+
15+
configure_cpp_module_target(nlohmann_json_modules)
16+
17+
target_link_libraries(nlohmann_json_modules
18+
PUBLIC
19+
nlohmann_json::nlohmann_json
20+
)
21+
22+
target_include_directories(nlohmann_json_modules
23+
PRIVATE
24+
${PROJECT_SOURCE_DIR}/include
25+
)
26+
27+
target_compile_features(nlohmann_json_modules PUBLIC cxx_std_20)

src/modules/json.cppm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module;
2+
3+
#include <nlohmann/json.hpp>
4+
5+
export module nlohmann.json;
6+
7+
export namespace nlohmann {
8+
template <typename T = void, typename SFINAE = void>
9+
using adl_serializer = ::nlohmann::adl_serializer<T, SFINAE>;
10+
11+
using basic_json = ::nlohmann::basic_json<>;
12+
13+
using json = ::nlohmann::json;
14+
15+
template <typename RefStringType>
16+
using json_pointer = ::nlohmann::json_pointer<RefStringType>;
17+
18+
using ::nlohmann::ordered_json;
19+
20+
template <class Key, class T, class IgnoredLess, class Allocator>
21+
using ordered_map = ::nlohmann::ordered_map<Key, T, IgnoredLess, Allocator>;
22+
} // namespace nlohmann

tests/module_cpp20/CMakeLists.txt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@ cmake_minimum_required(VERSION 3.28)
22

33
project(json_test CXX)
44

5-
add_executable(json_test)
5+
set(NLOHMANN_JSON_BUILD_MODULES ON CACHE BOOL "Enable nlohmann.json module support")
66

7-
target_sources(json_test
8-
PRIVATE main.cpp
9-
PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES json.cpp)
7+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/tests)
8+
9+
add_executable(json_test main.cpp)
10+
target_link_libraries(json_test
11+
PRIVATE
12+
nlohmann_json_modules
13+
)
14+
15+
target_compile_definitions(json_test
16+
PRIVATE NLOHMANN_JSON_BUILD_MODULES
17+
)
1018

1119
target_compile_features(json_test PUBLIC cxx_std_20)
12-
target_include_directories(json_test PRIVATE ../../include)

tests/module_cpp20/json.cpp

Lines changed: 0 additions & 17 deletions
This file was deleted.

tests/module_cpp20/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import json;
1+
import nlohmann.json;
22

33
int main()
44
{

0 commit comments

Comments
 (0)