Compare commits

..
Author SHA1 Message Date
Niels Lohmann f9a4ea08ab Merge remote-tracking branch 'origin/develop' into HEAD
Signed-off-by: Niels Lohmann <mail@nlohmann.me>

# Conflicts:
#	nlohmann_json.natvis
2026-10-04 17:23:08 +02:00
Niels Lohmann a22140705f Merge branch 'develop' into natvis-json-default-base
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-27 20:58:18 +02:00
Niels Lohmann 1e50d65882 Match json_default_base in both its current and 3.12.0 namespace
Since #5238, json_default_base lives directly in the (inline, ABI-tagged)
library namespace, e.g. nlohmann::json_abi_v3_12_0::json_default_base, and
no longer in detail. The fallback entries only named
<ns>::detail::json_default_base, so they would not match anything built
from the current headers or any later release. Emit an entry for both
names: the non-detail one for current code, the detail one for users of
3.12.0 (the version in #4972).

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-27 18:21:00 +02:00
Niels Lohmann 63c212bf8e Merge branch 'develop' into natvis-json-default-base
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-27 16:39:00 +02:00
Niels Lohmann 055158bbfa Document the json_default_base natvis fallback and regenerate natvis
Explain why a visualizer on the empty base class works, fix the
indentation of the new entry, and regenerate nlohmann_json.natvis from
the template (now covering all ABI tag combinations on develop).

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-27 14:52:34 +02:00
Mihnea Magheru 1a5d52404e Add a type in the natvis template for detail::json_default_base
Signed-off-by: Mihnea Magheru <sakuntalle@yahoo.com>
2026-09-27 14:51:37 +02:00
13 changed files with 11353 additions and 477 deletions
-42
View File
@@ -31,48 +31,6 @@ jobs:
- name: Build - name: Build
run: cmake --build build --target ci_test_gcc run: cmake --build build --target ci_test_gcc
ci_meson_install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Check that Meson and pkg-config offer the CMake options
run: make check_build_options
- name: Install Meson
run: pip install meson
- name: Install with Meson
run: |
meson setup build-meson --prefix=${{ github.workspace }}/install
meson install -C build-meson
- name: Use the installed package with find_package
run: |
cmake -S tests/cmake_import/project -B build-import -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install
cmake --build build-import
- name: Install with Meson and non-default options
run: |
meson setup build-meson-options --prefix=${{ github.workspace }}/install-options -DMultipleHeaders=true -DDiagnostics=true -DGlobalUDLs=false -DDisableTupleReferenceConversion=true
meson install -C build-meson-options
- name: Check that the options reach the installed files
run: |
test -d install-options/include/nlohmann/detail
cflags=$(PKG_CONFIG_PATH=${{ github.workspace }}/install-options/share/pkgconfig pkg-config --cflags nlohmann_json)
echo "$cflags"
echo "$cflags" | grep -q -- '-DJSON_DIAGNOSTICS=1'
echo "$cflags" | grep -q -- '-DJSON_USE_GLOBAL_UDLS=0'
echo "$cflags" | grep -q -- '-DJSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1'
grep -q 'JSON_USE_GLOBAL_UDLS=0;JSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1;JSON_DIAGNOSTICS=1' install-options/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake
cmake -S tests/cmake_import/project -B build-import-options -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-options
cmake --build build-import-options
- name: Install with Meson and the include directory outside the prefix
run: |
meson setup build-meson-split --prefix=${{ github.workspace }}/install-split --includedir=${{ github.workspace }}/install-split-dev/include
meson install -C build-meson-split
cmake -S tests/cmake_import/project -B build-import-split -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-split
cmake --build build-import-split
ci_infer: ci_infer:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
+1 -27
View File
@@ -180,33 +180,7 @@ if (MSVC)
) )
endif() endif()
# Install a pkg-config file, so other tools can find this. It carries the same # Install a pkg-config file, so other tools can find this.
# compile definitions as the target above.
set(NLOHMANN_JSON_PKGCONFIG_CFLAGS "")
if (NOT JSON_GlobalUDLs)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_GLOBAL_UDLS=0")
endif()
if (NOT JSON_ImplicitConversions)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_IMPLICIT_CONVERSIONS=0")
endif()
if (JSON_DisableEnumSerialization)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DISABLE_ENUM_SERIALIZATION=1")
endif()
if (JSON_DisableTupleReferenceConversion)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1")
endif()
if (JSON_Diagnostics)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DIAGNOSTICS=1")
endif()
if (JSON_Diagnostic_Positions)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DIAGNOSTIC_POSITIONS=1")
endif()
if (JSON_LegacyDiscardedValueComparison)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1")
endif()
if (JSON_StrictNulHandling)
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_STRICT_NUL_HANDLING=1")
endif()
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
+2 -24
View File
@@ -249,31 +249,9 @@ make BUILD.bazel
The "Check amalgamation" workflow fails if the file is out of date. The "Check amalgamation" workflow fails if the file is out of date.
### `meson.build` and `meson_options.txt` ### `meson.build`
Meson build definitions suitable for use as a subproject ("wrap" in Meson terminology). The build definition for the [Meson](https://mesonbuild.com) build system.
Projects wishing to use the wrap can execute:
```sh
meson wrap install nlohmann_json
```
Which allows Meson to build from source when a system provided dependency isn't available.
To build directly:
```sh
meson setup builddir
ninja -C builddir
```
`meson_options.txt` defines the options, which mirror the CMake options that change the library's target (for example,
`-DDiagnostics=true`). Meson requires this file next to `meson.build`, so it is also part of `include.zip`. `make check_build_options`
([`tools/check_build_options`](tools/check_build_options/README.md)) checks in CI that both files and the pkg-config files
stay in sync with the CMake options.
When installing, `meson.build` installs the headers, a pkg-config file, and the CMake package config files, so that
`find_package(nlohmann_json)` works. As Meson cannot generate `nlohmann_jsonTargets.cmake` itself, it is created from
the template `cmake/nlohmann_jsonTargets.cmake.in`, which is only used by Meson.
### `Package.swift` ### `Package.swift`
+2 -6
View File
@@ -1,4 +1,4 @@
.PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check check_build_options .PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check
########################################################################## ##########################################################################
# configuration # configuration
@@ -124,10 +124,6 @@ macro_builder_check:
diff "$$TMPDIR/paste.hpp" "$$TMPDIR/paste_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_EXPAND..NLOHMANN_JSON_DOUBLE_PASTE63) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1); \ diff "$$TMPDIR/paste.hpp" "$$TMPDIR/paste_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_EXPAND..NLOHMANN_JSON_DOUBLE_PASTE63) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1); \
diff "$$TMPDIR/type_body.hpp" "$$TMPDIR/type_body_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_TYPE_BODY) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1) diff "$$TMPDIR/type_body.hpp" "$$TMPDIR/type_body_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_TYPE_BODY) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1)
# check that the Meson build and the pkg-config files offer the options of the CMake target
check_build_options:
python3 tools/check_build_options/check_build_options.py .
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources # check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
check-amalgamation: check-amalgamation:
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ @mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
@@ -185,7 +181,7 @@ json.tar.xz:
# We use `-X` to make the resulting ZIP file reproducible, see # We use `-X` to make the resulting ZIP file reproducible, see
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>. # <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
include.zip: BUILD.bazel include.zip: BUILD.bazel
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build meson_options.txt LICENSE.MIT zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
# Create the files for a release and add signatures and hashes. # Create the files for a release and add signatures and hashes.
release: include.zip json.tar.xz release: include.zip json.tar.xz
-42
View File
@@ -1,42 +0,0 @@
# Imported target for installations made with Meson (see meson.build).
#
# CMake installations generate this file with install(EXPORT ...). Meson cannot
# do that, but as the library is header-only, the target only needs an include
# directory, the C++ standard, and the compile definitions of the options that
# differ from their defaults. Paths are computed relative to this file so that
# the installation can be relocated (e.g., into a sysroot), unless includedir or
# datadir is outside the prefix.
if(TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
return()
endif()
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_CONFIG_TO_PREFIX@" ABSOLUTE)
# As in CMake's generated file: avoid "//include" for an installation to "/".
if(_IMPORT_PREFIX STREQUAL "/")
set(_IMPORT_PREFIX "")
endif()
add_library(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED)
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "@NLOHMANN_JSON_INCLUDE_DIR@"
)
if(CMAKE_VERSION VERSION_LESS 3.8)
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
INTERFACE_COMPILE_FEATURES cxx_range_for
)
else()
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
INTERFACE_COMPILE_FEATURES cxx_std_11
)
endif()
set(_NLOHMANN_JSON_COMPILE_DEFINITIONS "@NLOHMANN_JSON_COMPILE_DEFINITIONS@")
if(_NLOHMANN_JSON_COMPILE_DEFINITIONS)
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "${_NLOHMANN_JSON_COMPILE_DEFINITIONS}"
)
endif()
unset(_NLOHMANN_JSON_COMPILE_DEFINITIONS)
unset(_IMPORT_PREFIX)
+1 -1
View File
@@ -4,4 +4,4 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@ Name: @PROJECT_NAME@
Description: JSON for Modern C++ Description: JSON for Modern C++
Version: @PROJECT_VERSION@ Version: @PROJECT_VERSION@
Cflags: -I${includedir}@NLOHMANN_JSON_PKGCONFIG_CFLAGS@ Cflags: -I${includedir}
@@ -125,23 +125,10 @@ meson wrap install nlohmann_json
Please see the Meson project for any issues regarding the packaging. Please see the Meson project for any issues regarding the packaging.
The provided `meson.build` can also be used as an alternative to CMake for installing `nlohmann_json` system-wide in The provided `meson.build` can also be used as an alternative to CMake for installing `nlohmann_json` system-wide in
which case a [pkg-config](pkg-config.md) file and the CMake package config files are installed. To use it, have your build system require which case a [pkg-config](pkg-config.md) file is installed. To use it, have your build system require the
the `nlohmann_json` pkg-config dependency, or use [`find_package(nlohmann_json)`](cmake.md#external) in CMake. In Meson, `nlohmann_json` pkg-config dependency. In Meson, it is preferred to use the
it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than
subproject fallback, rather than using the subproject directly. using the subproject directly.
The options that change the library's configuration are available in Meson as well, named like the
[CMake options](cmake.md#cmake-options) without the `JSON_` prefix: `MultipleHeaders`, `GlobalUDLs`,
`ImplicitConversions`, `DisableEnumSerialization`, `DisableTupleReferenceConversion`, `Diagnostics`,
`Diagnostic_Positions`, `LegacyDiscardedValueComparison`, and `StrictNulHandling`. They have the same defaults as in CMake, except that
`MultipleHeaders` is `false`. Set them with `-D` when setting up the build, or with the subproject name as prefix when
the library is used as a subproject:
```shell
meson setup build -Dnlohmann_json:Diagnostics=true
```
The resulting compile definitions are part of the Meson dependency, the pkg-config file, and the CMake target.
??? example "Example: Wrap" ??? example "Example: Wrap"
+8 -98
View File
@@ -2,114 +2,24 @@ project('nlohmann_json',
'cpp', 'cpp',
version : '3.12.0', version : '3.12.0',
license : 'MIT', license : 'MIT',
meson_version : '>= 0.64',
default_options: ['cpp_std=c++11'],
) )
if get_option('MultipleHeaders')
incdir = 'include'
else
incdir = 'single_include'
endif
# The same compile definitions as the CMake target (see target_compile_definitions
# in CMakeLists.txt): only an option that differs from its default adds one.
json_defines = []
if not get_option('GlobalUDLs')
json_defines += 'JSON_USE_GLOBAL_UDLS=0'
endif
if not get_option('ImplicitConversions')
json_defines += 'JSON_USE_IMPLICIT_CONVERSIONS=0'
endif
if get_option('DisableEnumSerialization')
json_defines += 'JSON_DISABLE_ENUM_SERIALIZATION=1'
endif
if get_option('DisableTupleReferenceConversion')
json_defines += 'JSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1'
endif
if get_option('Diagnostics')
json_defines += 'JSON_DIAGNOSTICS=1'
endif
if get_option('Diagnostic_Positions')
json_defines += 'JSON_DIAGNOSTIC_POSITIONS=1'
endif
if get_option('LegacyDiscardedValueComparison')
json_defines += 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1'
endif
if get_option('StrictNulHandling')
json_defines += 'JSON_STRICT_NUL_HANDLING=1'
endif
cpp_args = []
foreach define : json_defines
cpp_args += '-D' + define
endforeach
nlohmann_json_dep = declare_dependency( nlohmann_json_dep = declare_dependency(
compile_args: cpp_args, include_directories: include_directories('single_include')
include_directories: include_directories(incdir)
) )
meson.override_dependency('nlohmann_json', nlohmann_json_dep)
# The multi-header version under the name earlier versions of this file used
nlohmann_json_multiple_headers = declare_dependency( nlohmann_json_multiple_headers = declare_dependency(
compile_args: cpp_args,
include_directories: include_directories('include') include_directories: include_directories('include')
) )
if not meson.is_subproject() if not meson.is_subproject()
install_subdir( install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
incdir / 'nlohmann', install_headers('single_include/nlohmann/json_fwd.hpp', subdir: 'nlohmann')
install_dir: get_option('includedir'), install_headers('single_include/nlohmann/json_literals.hpp', subdir: 'nlohmann')
install_tag: 'devel',
)
pkgc = import('pkgconfig') pkgc = import('pkgconfig')
pkgc.generate(name: 'nlohmann_json', pkgc.generate(name: 'nlohmann_json',
version: meson.project_version(), version: meson.project_version(),
description: 'JSON for Modern C++', description: 'JSON for Modern C++'
extra_cflags: cpp_args, )
install_dir: get_option('datadir') / 'pkgconfig',
)
# CMake package config files, so that find_package(nlohmann_json) works. The
# include directory is given relative to the config files, so that the
# installation can be relocated. This is not possible if includedir or datadir
# is an absolute path outside the prefix (e.g., with the separate outputs of
# Nix); then the absolute include directory is used, as CMake does.
fs = import('fs')
cmake_install_dir = get_option('datadir') / 'cmake' / meson.project_name()
cmake_to_prefix = []
if fs.is_absolute(get_option('includedir')) or fs.is_absolute(cmake_install_dir)
cmake_include_dir = (get_option('prefix') / get_option('includedir')).replace('\\', '/')
else
foreach component : cmake_install_dir.split('/')
cmake_to_prefix += '..'
endforeach
cmake_include_dir = '${_IMPORT_PREFIX}/' + get_option('includedir')
endif
cmake_conf = configuration_data()
cmake_conf.set('PROJECT_NAME', meson.project_name())
cmake_conf.set('PROJECT_VERSION', meson.project_version())
cmake_conf.set('PROJECT_VERSION_MAJOR', meson.project_version().split('.')[0])
cmake_conf.set('NLOHMANN_JSON_TARGET_NAME', meson.project_name())
cmake_conf.set('NLOHMANN_JSON_TARGETS_EXPORT_NAME', meson.project_name() + 'Targets')
cmake_conf.set('NLOHMANN_JSON_INCLUDE_DIR', cmake_include_dir)
cmake_conf.set('NLOHMANN_JSON_CONFIG_TO_PREFIX', '/'.join(cmake_to_prefix))
cmake_conf.set('NLOHMANN_JSON_COMPILE_DEFINITIONS', ';'.join(json_defines))
foreach cmake_file : [
['cmake/config.cmake.in', 'nlohmann_jsonConfig.cmake'],
['cmake/nlohmann_jsonConfigVersion.cmake.in', 'nlohmann_jsonConfigVersion.cmake'],
['cmake/nlohmann_jsonTargets.cmake.in', 'nlohmann_jsonTargets.cmake'],
]
configure_file(
input: cmake_file[0],
output: cmake_file[1],
configuration: cmake_conf,
format: 'cmake@',
install_dir: cmake_install_dir,
)
endforeach
endif endif
-54
View File
@@ -1,54 +0,0 @@
option(
'MultipleHeaders',
type: 'boolean',
value: false,
description: 'Use non-amalgamated version of the library',
)
option(
'GlobalUDLs',
type: 'boolean',
value: true,
description: 'Place user-defined string literals in the global namespace',
)
option(
'ImplicitConversions',
type: 'boolean',
value: true,
description: 'Enable implicit conversions',
)
option(
'DisableEnumSerialization',
type: 'boolean',
value: false,
description: 'Disable default integer enum serialization',
)
option(
'DisableTupleReferenceConversion',
type: 'boolean',
value: false,
description: 'Disable conversion from a one-element tuple of a JSON reference',
)
option(
'Diagnostics',
type: 'boolean',
value: false,
description: 'Use extended diagnostic messages',
)
option(
'Diagnostic_Positions',
type: 'boolean',
value: false,
description: 'Enable diagnostic positions',
)
option(
'LegacyDiscardedValueComparison',
type: 'boolean',
value: false,
description: 'Enable legacy discarded value comparison',
)
option(
'StrictNulHandling',
type: 'boolean',
value: false,
description: 'Enable strict NUL-byte handling',
)
+11308
View File
File diff suppressed because it is too large Load Diff
-21
View File
@@ -1,21 +0,0 @@
# check_build_options
Checks that the Meson build and the pkg-config files offer the same options as the CMake target, so that a new CMake
option is not forgotten in one of them.
The compile definitions of the CMake target (`target_compile_definitions` in [`CMakeLists.txt`](../../CMakeLists.txt))
are the reference. When you add an option there, also add it to
- the pkg-config block in `CMakeLists.txt` (`NLOHMANN_JSON_PKGCONFIG_CFLAGS`),
- [`meson_options.txt`](../../meson_options.txt), named without the `JSON_` prefix and with the same default,
- [`meson.build`](../../meson.build) (`json_defines`), and
- the list of Meson options in
[`docs/mkdocs/docs/integration/package_managers.md`](../../docs/mkdocs/docs/integration/package_managers.md).
Run the check with
```shell
make check_build_options
```
It needs only Python 3 and runs in the `ci_meson_install` CI job.
@@ -1,144 +0,0 @@
#!/usr/bin/env python3
"""Check that the Meson build and the pkg-config files offer the CMake options.
The compile definitions of the CMake target (target_compile_definitions in
CMakeLists.txt) are the reference. For every option used there, the script
checks that
- the CMake pkg-config file adds the same definition under the same condition,
- meson_options.txt has a boolean option of the same name without the "JSON_"
prefix and with the same default,
- meson.build adds the same definition under the same condition, and
- the Meson section of the package manager documentation lists the option.
Meson's MultipleHeaders option selects the include directory and adds no
definition; it is the only Meson option without a definition.
"""
import argparse
import os
import re
import sys
REPO_ROOT = os.path.normpath(os.path.join(sys.path[0], '..', '..'))
DOCS = os.path.join('docs', 'mkdocs', 'docs', 'integration', 'package_managers.md')
# Meson options that add no compile definition, with their default
MESON_ONLY = {'MultipleHeaders': 'false'}
def read(root, path):
with open(os.path.join(root, path), encoding='utf-8') as f:
return f.read()
def cmake_target_definitions(cmake):
"""Return {option: (definition, add_if_on)} from target_compile_definitions."""
block = re.search(r'target_compile_definitions\(\s*\$\{NLOHMANN_JSON_TARGET_NAME\}\s*INTERFACE(.*?)\n\)', cmake, re.S)
if not block:
sys.exit('CMakeLists.txt: target_compile_definitions of the target not found')
result = {}
for line in block.group(1).split('\n'):
line = line.strip()
if not line:
continue
m = re.fullmatch(r'\$<\$<NOT:\$<BOOL:\$\{JSON_(\w+)\}>>:(\w+=\w+)>', line)
if m:
result[m.group(1)] = (m.group(2), False)
continue
m = re.fullmatch(r'\$<\$<BOOL:\$\{JSON_(\w+)\}>:(\w+=\w+)>', line)
if m:
result[m.group(1)] = (m.group(2), True)
continue
sys.exit(f'CMakeLists.txt: unexpected line in target_compile_definitions: {line}')
return result
def cmake_defaults(cmake):
"""Return {option: 'true'/'false'} for the option() calls of the form JSON_<name>."""
return {m.group(1): 'true' if m.group(2) == 'ON' else 'false'
for m in re.finditer(r'^option\(JSON_(\w+)\s+"[^"]*"\s+(ON|OFF)\)', cmake, re.M)}
def cmake_pkgconfig_definitions(cmake):
"""Return {option: (definition, add_if_on)} from the pkg-config block."""
return {m.group(2): (m.group(3), m.group(1) is None)
for m in re.finditer(r'if \((NOT )?JSON_(\w+)\)\s*\n\s*string\(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -D(\w+=\w+)"\)', cmake)}
def meson_options(options):
"""Return {option: default} for the boolean options in meson_options.txt."""
result = {}
for block in re.findall(r'option\((.*?)\)', options, re.S):
name = re.search(r"'(\w+)'", block).group(1)
kind = re.search(r"type\s*:\s*'(\w+)'", block)
value = re.search(r'value\s*:\s*(\w+)', block)
result[name] = value.group(1) if kind and kind.group(1) == 'boolean' and value else None
return result
def meson_definitions(meson):
"""Return {option: (definition, add_if_on)} from meson.build."""
return {m.group(2): (m.group(3), m.group(1) is None)
for m in re.finditer(r"if (not )?get_option\('(\w+)'\)\s*\n\s*json_defines \+= '(\w+=\w+)'", meson)}
def describe(definition):
name, add_if_on = definition
return f'{name} if {"enabled" if add_if_on else "disabled"}'
def compare(errors, where, expected, actual):
for option, definition in expected.items():
if option not in actual:
errors.append(f'{where}: no definition for option {option} (expected {describe(definition)})')
elif actual[option] != definition:
errors.append(f'{where}: option {option} adds {describe(actual[option])}, expected {describe(definition)}')
for option in actual.keys() - expected.keys():
errors.append(f'{where}: definition for option {option}, which the CMake target does not have')
def main():
parser = argparse.ArgumentParser(description=__doc__.split('\n')[0])
parser.add_argument('root', nargs='?', default=REPO_ROOT, help='repository root (default: %(default)s)')
root = parser.parse_args().root
cmake = read(root, 'CMakeLists.txt')
reference = cmake_target_definitions(cmake)
defaults = cmake_defaults(cmake)
errors = []
compare(errors, 'CMakeLists.txt (pkg-config)', reference, cmake_pkgconfig_definitions(cmake))
compare(errors, 'meson.build', reference, meson_definitions(read(root, 'meson.build')))
options = meson_options(read(root, 'meson_options.txt'))
for option in reference:
if option not in defaults:
errors.append(f'CMakeLists.txt: no option(JSON_{option} ... ON|OFF)')
elif option not in options:
errors.append(f'meson_options.txt: option {option} missing')
elif options[option] != defaults[option]:
errors.append(f'meson_options.txt: option {option} must be boolean with value {defaults[option]} as in CMake')
for option, default in MESON_ONLY.items():
if options.get(option) != default:
errors.append(f'meson_options.txt: option {option} must be boolean with value {default}')
for option in options.keys() - reference.keys() - MESON_ONLY.keys():
errors.append(f'meson_options.txt: option {option} has no counterpart in the CMake target')
docs = read(root, DOCS)
for option in sorted(set(options) & (reference.keys() | MESON_ONLY.keys())):
if f'`{option}`' not in docs:
errors.append(f'{DOCS}: Meson option {option} not listed')
for error in errors:
print(error, file=sys.stderr)
if errors:
print('The Meson build and the pkg-config files must offer the options of the CMake target; see '
'tools/check_build_options/README.md.', file=sys.stderr)
return 1
print(f'OK: {len(reference)} options with compile definitions agree between CMake, pkg-config, and Meson.')
return 0
if __name__ == '__main__':
sys.exit(main())
@@ -36,5 +36,31 @@
</Expand> </Expand>
</Type> </Type>
<!-- Fallback for when the basic_json entry above does not match: json_default_base is the (empty) default
base class of basic_json, and base class visualizers are inherited by derived types and evaluated
against the derived object, so m_data is accessible here. The class lives in {{ ns }} after
3.12.0 (#5238) and in {{ ns }}::detail up to 3.12.0, so both names are listed. -->
{% for default_base in ['json_default_base', 'detail::json_default_base'] %}
<Type Name="{{ ns }}::{{ default_base }}">
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == {{ ns }}::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_data.m_type == {{ ns }}::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_data.m_type == {{ ns }}::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
{% endfor %}
{% endfor %} {% endfor %}
</AutoVisualizer> </AutoVisualizer>