• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# number of parallel jobs for CTest
2set(N 10)
3
4###############################################################################
5# Needed tools.
6###############################################################################
7
8include(FindPython3)
9find_package(Python3 COMPONENTS Interpreter)
10
11find_program(ASTYLE_TOOL NAMES astyle)
12execute_process(COMMAND ${ASTYLE_TOOL} --version OUTPUT_VARIABLE ASTYLE_TOOL_VERSION ERROR_VARIABLE ASTYLE_TOOL_VERSION)
13string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" ASTYLE_TOOL_VERSION "${ASTYLE_TOOL_VERSION}")
14message(STATUS "�� Artistic Style ${ASTYLE_TOOL_VERSION} (${ASTYLE_TOOL})")
15
16find_program(CLANG_TOOL NAMES clang++-HEAD clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
17execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
18string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
19message(STATUS "�� Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
20
21find_program(CLANG_TIDY_TOOL NAMES clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
22execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
23string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
24message(STATUS "�� Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
25
26message(STATUS "�� CMake ${CMAKE_VERSION} (${CMAKE_COMMAND})")
27
28find_program(CPPCHECK_TOOL NAMES cppcheck)
29execute_process(COMMAND ${CPPCHECK_TOOL} --version OUTPUT_VARIABLE CPPCHECK_TOOL_VERSION ERROR_VARIABLE CPPCHECK_TOOL_VERSION)
30string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CPPCHECK_TOOL_VERSION "${CPPCHECK_TOOL_VERSION}")
31message(STATUS "�� Cppcheck ${CPPCHECK_TOOL_VERSION} (${CPPCHECK_TOOL})")
32
33find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++-11 g++-10)
34execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
35string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
36message(STATUS "�� GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
37
38find_program(GCOV_TOOL NAMES gcov-HEAD gcov-11 gcov-10 gcov)
39execute_process(COMMAND ${GCOV_TOOL} --version OUTPUT_VARIABLE GCOV_TOOL_VERSION ERROR_VARIABLE GCOV_TOOL_VERSION)
40string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCOV_TOOL_VERSION "${GCOV_TOOL_VERSION}")
41message(STATUS "�� GCOV ${GCOV_TOOL_VERSION} (${GCOV_TOOL})")
42
43find_program(GIT_TOOL NAMES git)
44execute_process(COMMAND ${GIT_TOOL} --version OUTPUT_VARIABLE GIT_TOOL_VERSION ERROR_VARIABLE GIT_TOOL_VERSION)
45string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GIT_TOOL_VERSION "${GIT_TOOL_VERSION}")
46message(STATUS "�� Git ${GIT_TOOL_VERSION} (${GIT_TOOL})")
47
48find_program(IWYU_TOOL NAMES include-what-you-use iwyu)
49execute_process(COMMAND ${IWYU_TOOL} --version OUTPUT_VARIABLE IWYU_TOOL_VERSION ERROR_VARIABLE IWYU_TOOL_VERSION)
50string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
51message(STATUS "�� include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
52
53find_program(INFER_TOOL NAMES infer)
54execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
55string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
56message(STATUS "�� Infer ${INFER_TOOL_VERSION} (${INFER_TOOL})")
57
58find_program(LCOV_TOOL NAMES lcov)
59execute_process(COMMAND ${LCOV_TOOL} --version OUTPUT_VARIABLE LCOV_TOOL_VERSION ERROR_VARIABLE LCOV_TOOL_VERSION)
60string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" LCOV_TOOL_VERSION "${LCOV_TOOL_VERSION}")
61message(STATUS "�� LCOV ${LCOV_TOOL_VERSION} (${LCOV_TOOL})")
62
63find_program(NINJA_TOOL NAMES ninja)
64execute_process(COMMAND ${NINJA_TOOL} --version OUTPUT_VARIABLE NINJA_TOOL_VERSION ERROR_VARIABLE NINJA_TOOL_VERSION)
65string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
66message(STATUS "�� Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
67
68find_program(OCLINT_TOOL NAMES oclint-json-compilation-database)
69find_program(OCLINT_VERSION_TOOL NAMES oclint)
70execute_process(COMMAND ${OCLINT_VERSION_TOOL} --version OUTPUT_VARIABLE OCLINT_TOOL_VERSION ERROR_VARIABLE OCLINT_TOOL_VERSION)
71string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" OCLINT_TOOL_VERSION "${OCLINT_TOOL_VERSION}")
72message(STATUS "�� OCLint ${OCLINT_TOOL_VERSION} (${OCLINT_TOOL})")
73
74find_program(VALGRIND_TOOL NAMES valgrind)
75execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
76string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
77message(STATUS "�� Valgrind ${VALGRIND_TOOL_VERSION} (${VALGRIND_TOOL})")
78
79find_program(GENHTML_TOOL NAMES genhtml)
80find_program(PLOG_CONVERTER_TOOL NAMES plog-converter)
81find_program(PVS_STUDIO_ANALYZER_TOOL NAMES pvs-studio-analyzer)
82find_program(SCAN_BUILD_TOOL NAMES scan-build-15 scan-build-14 scan-build-13 scan-build-12 scan-build-11 scan-build)
83
84# the individual source files
85file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp)
86
87###############################################################################
88# Thorough check with recent compilers
89###############################################################################
90
91# Ignored Clang warnings:
92# -Wno-c++98-compat               The library targets C++11.
93# -Wno-c++98-compat-pedantic      The library targets C++11.
94# -Wno-deprecated-declarations    The library contains annotations for deprecated functions.
95# -Wno-extra-semi-stmt            The library uses std::assert which triggers this warning.
96# -Wno-padded                     We do not care about padding warnings.
97# -Wno-covered-switch-default     All switches list all cases and a default case.
98# -Wno-weak-vtables               The library is header-only.
99# -Wreserved-identifier           See https://github.com/onqtam/doctest/issues/536.
100
101set(CLANG_CXXFLAGS
102    -Werror
103    -Weverything
104    -Wno-c++98-compat
105    -Wno-c++98-compat-pedantic
106    -Wno-deprecated-declarations
107    -Wno-extra-semi-stmt
108    -Wno-padded
109    -Wno-covered-switch-default
110    -Wno-weak-vtables
111    -Wno-reserved-identifier
112)
113
114# Warning flags determined for GCC 13.0 (experimental) with https://github.com/nlohmann/gcc_flags:
115# Ignored GCC warnings:
116# -Wno-abi-tag                    We do not care about ABI tags.
117# -Wno-aggregate-return           The library uses aggregate returns.
118# -Wno-long-long                  The library uses the long long type to interface with system functions.
119# -Wno-namespaces                 The library uses namespaces.
120# -Wno-padded                     We do not care about padding warnings.
121# -Wno-system-headers             We do not care about warnings in system headers.
122# -Wno-templates                  The library uses templates.
123
124set(GCC_CXXFLAGS
125    -pedantic
126    -Werror
127    --all-warnings
128    --extra-warnings
129    -W
130    -WNSObject-attribute
131    -Wno-abi-tag
132    -Waddress
133    -Waddress-of-packed-member
134    -Wno-aggregate-return
135    -Waggressive-loop-optimizations
136    -Waligned-new=all
137    -Wall
138    -Walloc-zero
139    -Walloca
140    -Wanalyzer-double-fclose
141    -Wanalyzer-double-free
142    -Wanalyzer-exposure-through-output-file
143    -Wanalyzer-file-leak
144    -Wanalyzer-free-of-non-heap
145    -Wanalyzer-malloc-leak
146    -Wanalyzer-mismatching-deallocation
147    -Wanalyzer-null-argument
148    -Wanalyzer-null-dereference
149    -Wanalyzer-possible-null-argument
150    -Wanalyzer-possible-null-dereference
151    -Wanalyzer-shift-count-negative
152    -Wanalyzer-shift-count-overflow
153    -Wanalyzer-stale-setjmp-buffer
154    -Wanalyzer-tainted-allocation-size
155    -Wanalyzer-tainted-array-index
156    -Wanalyzer-tainted-divisor
157    -Wanalyzer-tainted-offset
158    -Wanalyzer-tainted-size
159    -Wanalyzer-too-complex
160    -Wanalyzer-unsafe-call-within-signal-handler
161    -Wanalyzer-use-after-free
162    -Wanalyzer-use-of-pointer-in-stale-stack-frame
163    -Wanalyzer-use-of-uninitialized-value
164    -Wanalyzer-va-arg-type-mismatch
165    -Wanalyzer-va-list-exhausted
166    -Wanalyzer-va-list-leak
167    -Wanalyzer-va-list-use-after-va-end
168    -Wanalyzer-write-to-const
169    -Wanalyzer-write-to-string-literal
170    -Warith-conversion
171    -Warray-bounds=2
172    -Warray-compare
173    -Warray-parameter=2
174    -Wattribute-alias=2
175    -Wattribute-warning
176    -Wattributes
177    -Wbool-compare
178    -Wbool-operation
179    -Wbuiltin-declaration-mismatch
180    -Wbuiltin-macro-redefined
181    -Wc++0x-compat
182    -Wc++11-compat
183    -Wc++11-extensions
184    -Wc++14-compat
185    -Wc++14-extensions
186    -Wc++17-compat
187    -Wc++17-extensions
188    -Wc++1z-compat
189    -Wc++20-compat
190    -Wc++20-extensions
191    -Wc++23-extensions
192    -Wc++2a-compat
193    -Wcannot-profile
194    -Wcast-align
195    -Wcast-align=strict
196    -Wcast-function-type
197    -Wcast-qual
198    -Wcatch-value=3
199    -Wchar-subscripts
200    -Wclass-conversion
201    -Wclass-memaccess
202    -Wclobbered
203    -Wcomma-subscript
204    -Wcomment
205    -Wcomments
206    -Wconditionally-supported
207    -Wconversion
208    -Wconversion-null
209    -Wcoverage-invalid-line-number
210    -Wcoverage-mismatch
211    -Wcpp
212    -Wctad-maybe-unsupported
213    -Wctor-dtor-privacy
214    -Wdangling-else
215    -Wdangling-pointer=2
216    -Wdate-time
217    -Wdelete-incomplete
218    -Wdelete-non-virtual-dtor
219    -Wdeprecated
220    -Wdeprecated-copy
221    -Wdeprecated-copy-dtor
222    -Wdeprecated-declarations
223    -Wdeprecated-enum-enum-conversion
224    -Wdeprecated-enum-float-conversion
225    -Wdisabled-optimization
226    -Wdiv-by-zero
227    -Wdouble-promotion
228    -Wduplicated-branches
229    -Wduplicated-cond
230    -Weffc++
231    -Wempty-body
232    -Wendif-labels
233    -Wenum-compare
234    -Wenum-conversion
235    -Wexceptions
236    -Wexpansion-to-defined
237    -Wextra
238    -Wextra-semi
239    -Wfloat-conversion
240    -Wfloat-equal
241    -Wformat-diag
242    -Wformat-overflow=2
243    -Wformat-signedness
244    -Wformat-truncation=2
245    -Wformat=2
246    -Wframe-address
247    -Wfree-nonheap-object
248    -Whsa
249    -Wif-not-aligned
250    -Wignored-attributes
251    -Wignored-qualifiers
252    -Wimplicit-fallthrough=5
253    -Winaccessible-base
254    -Winfinite-recursion
255    -Winherited-variadic-ctor
256    -Winit-list-lifetime
257    -Winit-self
258    -Winline
259    -Wint-in-bool-context
260    -Wint-to-pointer-cast
261    -Winterference-size
262    -Winvalid-imported-macros
263    -Winvalid-memory-model
264    -Winvalid-offsetof
265    -Winvalid-pch
266    -Wliteral-suffix
267    -Wlogical-not-parentheses
268    -Wlogical-op
269    -Wno-long-long
270    -Wlto-type-mismatch
271    -Wmain
272    -Wmaybe-uninitialized
273    -Wmemset-elt-size
274    -Wmemset-transposed-args
275    -Wmisleading-indentation
276    -Wmismatched-dealloc
277    -Wmismatched-new-delete
278    -Wmismatched-tags
279    -Wmissing-attributes
280    -Wmissing-braces
281    -Wmissing-declarations
282    -Wmissing-field-initializers
283    -Wmissing-include-dirs
284    -Wmissing-profile
285    -Wmissing-requires
286    -Wmissing-template-keyword
287    -Wmultichar
288    -Wmultiple-inheritance
289    -Wmultistatement-macros
290    -Wno-namespaces
291    -Wnarrowing
292    -Wnoexcept
293    -Wnoexcept-type
294    -Wnon-template-friend
295    -Wnon-virtual-dtor
296    -Wnonnull
297    -Wnonnull-compare
298    -Wnormalized=nfkc
299    -Wnull-dereference
300    -Wodr
301    -Wold-style-cast
302    -Wopenacc-parallelism
303    -Wopenmp-simd
304    -Woverflow
305    -Woverlength-strings
306    -Woverloaded-virtual
307    -Wpacked
308    -Wpacked-bitfield-compat
309    -Wpacked-not-aligned
310    -Wno-padded
311    -Wparentheses
312    -Wpedantic
313    -Wpessimizing-move
314    -Wplacement-new=2
315    -Wpmf-conversions
316    -Wpointer-arith
317    -Wpointer-compare
318    -Wpragmas
319    -Wprio-ctor-dtor
320    -Wpsabi
321    -Wrange-loop-construct
322    -Wredundant-decls
323    -Wredundant-move
324    -Wredundant-tags
325    -Wregister
326    -Wreorder
327    -Wrestrict
328    -Wreturn-local-addr
329    -Wreturn-type
330    -Wscalar-storage-order
331    -Wsequence-point
332    -Wshadow=compatible-local
333    -Wshadow=global
334    -Wshadow=local
335    -Wshift-count-negative
336    -Wshift-count-overflow
337    -Wshift-negative-value
338    -Wshift-overflow=2
339    -Wsign-compare
340    -Wsign-conversion
341    -Wsign-promo
342    -Wsized-deallocation
343    -Wsizeof-array-argument
344    -Wsizeof-array-div
345    -Wsizeof-pointer-div
346    -Wsizeof-pointer-memaccess
347    -Wstack-protector
348    -Wstrict-aliasing=3
349    -Wstrict-null-sentinel
350    -Wno-strict-overflow
351    -Wstring-compare
352    -Wstringop-overflow=4
353    -Wstringop-overread
354    -Wstringop-truncation
355    -Wsubobject-linkage
356    -Wsuggest-attribute=cold
357    -Wsuggest-attribute=const
358    -Wsuggest-attribute=format
359    -Wsuggest-attribute=malloc
360    -Wsuggest-attribute=noreturn
361    -Wsuggest-attribute=pure
362    -Wsuggest-final-methods
363    -Wsuggest-final-types
364    -Wsuggest-override
365    -Wswitch
366    -Wswitch-bool
367    -Wswitch-default
368    -Wswitch-enum
369    -Wswitch-outside-range
370    -Wswitch-unreachable
371    -Wsync-nand
372    -Wsynth
373    -Wno-system-headers
374    -Wtautological-compare
375    -Wno-templates
376    -Wterminate
377    -Wtrampolines
378    -Wtrigraphs
379    -Wtrivial-auto-var-init
380    -Wtsan
381    -Wtype-limits
382    -Wundef
383    -Wuninitialized
384    -Wunknown-pragmas
385    -Wunreachable-code
386    -Wunsafe-loop-optimizations
387    -Wunused
388    -Wunused-but-set-parameter
389    -Wunused-but-set-variable
390    -Wunused-const-variable=2
391    -Wunused-function
392    -Wunused-label
393    -Wunused-local-typedefs
394    -Wunused-macros
395    -Wunused-parameter
396    -Wunused-result
397    -Wunused-value
398    -Wunused-variable
399    -Wuse-after-free=3
400    -Wuseless-cast
401    -Wvarargs
402    -Wvariadic-macros
403    -Wvector-operation-performance
404    -Wvexing-parse
405    -Wvirtual-inheritance
406    -Wvirtual-move-assign
407    -Wvla
408    -Wvla-parameter
409    -Wvolatile
410    -Wvolatile-register-var
411    -Wwrite-strings
412    -Wzero-as-null-pointer-constant
413    -Wzero-length-bounds
414)
415
416add_custom_target(ci_test_gcc
417    COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
418        -DCMAKE_BUILD_TYPE=Debug -GNinja
419        -DJSON_BuildTests=ON
420        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc
421    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc
422    COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
423    COMMENT "Compile and test with GCC using maximal warning flags"
424)
425
426add_custom_target(ci_test_clang
427    COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
428        -DCMAKE_BUILD_TYPE=Debug -GNinja
429        -DJSON_BuildTests=ON
430        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang
431    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang
432    COMMAND cd ${PROJECT_BINARY_DIR}/build_clang && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
433    COMMENT "Compile and test with Clang using maximal warning flags"
434)
435
436###############################################################################
437# Different C++ Standards.
438###############################################################################
439
440foreach(CXX_STANDARD 11 14 17 20)
441    add_custom_target(ci_test_gcc_cxx${CXX_STANDARD}
442        COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
443            -DCMAKE_BUILD_TYPE=Debug -GNinja
444            -DJSON_BuildTests=ON -DJSON_FastTests=ON
445            -DJSON_TestStandards=${CXX_STANDARD}
446            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
447        COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
448        COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
449        COMMENT "Compile and test with GCC for C++${CXX_STANDARD}"
450    )
451
452    add_custom_target(ci_test_clang_cxx${CXX_STANDARD}
453        COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
454            -DCMAKE_BUILD_TYPE=Debug -GNinja
455            -DJSON_BuildTests=ON -DJSON_FastTests=ON
456            -DJSON_TestStandards=${CXX_STANDARD}
457            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
458        COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
459        COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
460        COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
461    )
462endforeach()
463
464###############################################################################
465# Disable exceptions.
466###############################################################################
467
468add_custom_target(ci_test_noexceptions
469    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
470    -DCMAKE_BUILD_TYPE=Debug -GNinja
471    -DJSON_BuildTests=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw
472    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noexceptions
473    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noexceptions
474    COMMAND cd ${PROJECT_BINARY_DIR}/build_noexceptions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
475    COMMENT "Compile and test with exceptions switched off"
476)
477
478###############################################################################
479# Disable implicit conversions.
480###############################################################################
481
482add_custom_target(ci_test_noimplicitconversions
483    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
484    -DCMAKE_BUILD_TYPE=Debug -GNinja
485    -DJSON_BuildTests=ON -DJSON_ImplicitConversions=OFF
486    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noimplicitconversions
487    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noimplicitconversions
488    COMMAND cd ${PROJECT_BINARY_DIR}/build_noimplicitconversions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
489    COMMENT "Compile and test with implicit conversions switched off"
490)
491
492###############################################################################
493# Enable improved diagnostics.
494###############################################################################
495
496add_custom_target(ci_test_diagnostics
497    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
498    -DCMAKE_BUILD_TYPE=Debug -GNinja
499    -DJSON_BuildTests=ON -DJSON_Diagnostics=ON
500    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostics
501    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostics
502    COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostics && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
503    COMMENT "Compile and test with improved diagnostics enabled"
504)
505
506###############################################################################
507# Enable legacy discarded value comparison.
508###############################################################################
509
510add_custom_target(ci_test_legacycomparison
511    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
512    -DCMAKE_BUILD_TYPE=Debug -GNinja
513    -DJSON_BuildTests=ON -DJSON_LegacyDiscardedValueComparison=ON
514    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_legacycomparison
515    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_legacycomparison
516    COMMAND cd ${PROJECT_BINARY_DIR}/build_legacycomparison && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
517    COMMENT "Compile and test with legacy discarded value comparison enabled"
518)
519
520###############################################################################
521# Disable global UDLs.
522###############################################################################
523
524add_custom_target(ci_test_noglobaludls
525    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
526    -DCMAKE_BUILD_TYPE=Debug -GNinja
527    -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_GlobalUDLs=OFF
528    -DCMAKE_CXX_FLAGS=-DJSON_TEST_NO_GLOBAL_UDLS
529    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noglobaludls
530    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noglobaludls
531    COMMAND cd ${PROJECT_BINARY_DIR}/build_noglobaludls && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
532    COMMENT "Compile and test with global UDLs disabled"
533)
534
535###############################################################################
536# Coverage.
537###############################################################################
538
539add_custom_target(ci_test_coverage
540    COMMAND CXX=g++ ${CMAKE_COMMAND}
541        -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage"
542        -DJSON_BuildTests=ON
543        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage
544    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage
545    COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
546
547    COMMAND CXX=g++ ${CMAKE_COMMAND}
548        -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="-m32;--coverage;-fprofile-arcs;-ftest-coverage"
549        -DJSON_BuildTests=ON -DJSON_32bitTest=ONLY
550        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage32
551    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage32
552    COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage32 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
553
554    COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc lcov_branch_coverage=1
555    COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc lcov_branch_coverage=1
556    COMMAND ${CMAKE_SOURCE_DIR}/tests/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept
557    COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept
558
559    COMMENT "Compile and test with coverage"
560)
561
562###############################################################################
563# Sanitizers.
564###############################################################################
565
566set(CLANG_CXX_FLAGS_SANITIZER "-g -O1 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer -fno-sanitize-recover=all -fno-sanitize=unsigned-integer-overflow -fno-sanitize=unsigned-shift-base")
567
568add_custom_target(ci_test_clang_sanitizer
569    COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXX_FLAGS_SANITIZER} ${CMAKE_COMMAND}
570        -DCMAKE_BUILD_TYPE=Debug -GNinja
571        -DJSON_BuildTests=ON
572        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_sanitizer
573    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_sanitizer
574    COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_sanitizer && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
575    COMMENT "Compile and test with sanitizers"
576)
577
578###############################################################################
579# Check if header is amalgamated and sources are properly indented.
580###############################################################################
581
582set(ASTYLE_FLAGS --style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type --align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date --formatted)
583
584file(GLOB_RECURSE INDENT_FILES
585    ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
586        ${PROJECT_SOURCE_DIR}/tests/src/*.cpp
587        ${PROJECT_SOURCE_DIR}/tests/src/*.hpp
588        ${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
589    ${PROJECT_SOURCE_DIR}/docs/examples/*.cpp
590)
591
592set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
593set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
594add_custom_target(ci_test_amalgamation
595    COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~
596    COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
597    COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
598
599    COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
600    COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
601    COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
602
603    COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
604    COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
605
606    COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} ${INDENT_FILES}
607    COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
608
609    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
610    COMMENT "Check amalgamation and indentation"
611)
612
613###############################################################################
614# Build and test using the amalgamated header
615###############################################################################
616
617add_custom_target(ci_test_single_header
618    COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
619        -DCMAKE_BUILD_TYPE=Debug -GNinja
620        -DJSON_BuildTests=ON -DJSON_MultipleHeaders=OFF -DJSON_FastTests=ON
621        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_single_header
622    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_single_header
623    COMMAND cd ${PROJECT_BINARY_DIR}/build_single_header && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
624    COMMENT "Compile and test single-header version"
625)
626
627###############################################################################
628# Valgrind.
629###############################################################################
630
631add_custom_target(ci_test_valgrind
632    COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND}
633        -DCMAKE_BUILD_TYPE=Debug -GNinja
634        -DJSON_BuildTests=ON -DJSON_Valgrind=ON
635        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_valgrind
636    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_valgrind
637    COMMAND cd ${PROJECT_BINARY_DIR}/build_valgrind && ${CMAKE_CTEST_COMMAND} -L valgrind --parallel ${N} --output-on-failure
638    COMMENT "Compile and test with Valgrind"
639)
640
641###############################################################################
642# Check code with Clang Static Analyzer.
643###############################################################################
644
645set(CLANG_ANALYZER_CHECKS "fuchsia.HandleChecker,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.mpi.MPI-Checker,optin.osx.OSObjectCStyleCast,optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,optin.osx.cocoa.localizability.NonLocalizedStringChecker,optin.performance.GCDAntipattern,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,osx.API,osx.MIG,osx.NumberObjectConversion,osx.OSObjectRetainCount,osx.ObjCProperty,osx.SecKeychainAPI,osx.cocoa.AtSync,osx.cocoa.AutoreleaseWrite,osx.cocoa.ClassRelease,osx.cocoa.Dealloc,osx.cocoa.IncompatibleMethodTypes,osx.cocoa.Loops,osx.cocoa.MissingSuperCall,osx.cocoa.NSAutoreleasePool,osx.cocoa.NSError,osx.cocoa.NilArg,osx.cocoa.NonNilReturnValue,osx.cocoa.ObjCGenerics,osx.cocoa.RetainCount,osx.cocoa.RunLoopAutoreleaseLeak,osx.cocoa.SelfInit,osx.cocoa.SuperDealloc,osx.cocoa.UnusedIvars,osx.cocoa.VariadicMethodTypes,osx.coreFoundation.CFError,osx.coreFoundation.CFNumber,osx.coreFoundation.CFRetainRelease,osx.coreFoundation.containers.OutOfBounds,osx.coreFoundation.containers.PointerSizedValues,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
646
647add_custom_target(ci_clang_analyze
648    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
649        -DCMAKE_BUILD_TYPE=Debug -GNinja
650        -DJSON_BuildTests=ON
651        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
652    COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} -analyze-headers -o ${PROJECT_BINARY_DIR}/report ninja
653    COMMENT "Check code with Clang Analyzer"
654)
655
656###############################################################################
657# Check code with Cppcheck.
658###############################################################################
659
660add_custom_target(ci_cppcheck
661    COMMAND ${CPPCHECK_TOOL} --enable=warning --suppress=missingReturn --inline-suppr --inconclusive --force --std=c++11 ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp --error-exitcode=1
662    COMMENT "Check code with Cppcheck"
663)
664
665###############################################################################
666# Check code with cpplint.
667###############################################################################
668
669add_custom_target(ci_cpplint
670    COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/cpplint/cpplint.py --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES}
671    COMMENT "Check code with cpplint"
672)
673
674###############################################################################
675# Check code with OCLint.
676###############################################################################
677
678file(COPY ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp DESTINATION ${PROJECT_BINARY_DIR}/src_single)
679file(RENAME ${PROJECT_BINARY_DIR}/src_single/json.hpp ${PROJECT_BINARY_DIR}/src_single/all.cpp)
680file(APPEND "${PROJECT_BINARY_DIR}/src_single/all.cpp" "\n\nint main()\n{}\n")
681
682add_executable(single_all ${PROJECT_BINARY_DIR}/src_single/all.cpp)
683target_compile_features(single_all PRIVATE cxx_std_11)
684
685add_custom_target(ci_oclint
686    COMMAND ${CMAKE_COMMAND}
687        -DCMAKE_BUILD_TYPE=Debug
688        -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
689        -DJSON_BuildTests=OFF -DJSON_CI=ON
690        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_oclint
691    COMMAND ${OCLINT_TOOL} -i ${PROJECT_BINARY_DIR}/build_oclint/src_single/all.cpp -p ${PROJECT_BINARY_DIR}/build_oclint --
692        -report-type html -enable-global-analysis --max-priority-1=0 --max-priority-2=1000 --max-priority-3=2000
693        --disable-rule=MultipleUnaryOperator
694        --disable-rule=DoubleNegative
695        --disable-rule=ShortVariableName
696        --disable-rule=GotoStatement
697        --disable-rule=LongLine
698        -o ${PROJECT_BINARY_DIR}/build_oclint/oclint_report.html
699    COMMENT "Check code with OCLint"
700)
701
702###############################################################################
703# Check code with Clang-Tidy.
704###############################################################################
705
706add_custom_target(ci_clang_tidy
707    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
708        -DCMAKE_BUILD_TYPE=Debug -GNinja
709        -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_CLANG_TIDY=${CLANG_TIDY_TOOL}
710        -DJSON_BuildTests=ON
711        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_tidy
712    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_tidy
713    COMMENT "Check code with Clang-Tidy"
714)
715
716###############################################################################
717# Check code with PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>.
718###############################################################################
719
720add_custom_target(ci_pvs_studio
721    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
722        -DCMAKE_BUILD_TYPE=Debug
723        -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
724        -DJSON_BuildTests=ON
725        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_pvs_studio
726    COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PVS_STUDIO_ANALYZER_TOOL} analyze -j 10
727    COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PLOG_CONVERTER_TOOL} -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
728    COMMENT "Check code with PVS Studio"
729)
730
731###############################################################################
732# Check code with Infer <https://fbinfer.com> static analyzer.
733###############################################################################
734
735add_custom_target(ci_infer
736    COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
737    COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
738    COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make
739    COMMENT "Check code with Infer"
740)
741
742###############################################################################
743# Run test suite with previously downloaded test data.
744###############################################################################
745
746add_custom_target(ci_offline_testdata
747    COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data
748    COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.1.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1
749    COMMAND ${CMAKE_COMMAND}
750        -DCMAKE_BUILD_TYPE=Debug -GNinja
751        -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_TestDataDirectory=${PROJECT_BINARY_DIR}/build_offline_testdata/test_data/json_test_data
752        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_offline_testdata
753    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_offline_testdata
754    COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
755    COMMENT "Check code with previously downloaded test data"
756)
757
758###############################################################################
759# Run test suite when project was not checked out from Git
760###############################################################################
761
762add_custom_target(ci_non_git_tests
763    COMMAND git config --global --add safe.directory ${PROJECT_SOURCE_DIR}
764    COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_non_git_tests/sources
765    COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `${GIT_TOOL} ls-tree --name-only HEAD`\; do cp -r $$FILE ${PROJECT_BINARY_DIR}/build_non_git_tests/sources \; done
766    COMMAND ${CMAKE_COMMAND}
767        -DCMAKE_BUILD_TYPE=Debug -GNinja
768        -DJSON_BuildTests=ON -DJSON_FastTests=ON
769        -S${PROJECT_BINARY_DIR}/build_non_git_tests/sources -B${PROJECT_BINARY_DIR}/build_non_git_tests
770    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_non_git_tests
771    COMMAND cd ${PROJECT_BINARY_DIR}/build_non_git_tests && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE git_required --output-on-failure
772    COMMENT "Check code when project was not checked out from Git"
773)
774
775###############################################################################
776# Run test suite and exclude tests that change installed files
777###############################################################################
778
779add_custom_target(ci_reproducible_tests
780    COMMAND ${CMAKE_COMMAND}
781        -DCMAKE_BUILD_TYPE=Debug -GNinja
782        -DJSON_BuildTests=ON -DJSON_FastTests=ON
783        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_reproducible_tests
784    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_reproducible_tests
785    COMMAND cd ${PROJECT_BINARY_DIR}/build_reproducible_tests && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE not_reproducible --output-on-failure
786    COMMENT "Check code and exclude tests that change installed files"
787)
788
789###############################################################################
790# Check if every header in the include folder includes sufficient headers to
791# be compiled individually.
792###############################################################################
793
794set(iwyu_path_and_options ${IWYU_TOOL} -Xiwyu --max_line_length=300)
795
796foreach(SRC_FILE ${SRC_FILES})
797    # get relative path of the header file
798    file(RELATIVE_PATH RELATIVE_SRC_FILE "${PROJECT_SOURCE_DIR}/include/nlohmann" "${SRC_FILE}")
799    # replace slashes and strip suffix
800    string(REPLACE "/" "_" RELATIVE_SRC_FILE "${RELATIVE_SRC_FILE}")
801    string(REPLACE ".hpp" "" RELATIVE_SRC_FILE "${RELATIVE_SRC_FILE}")
802    # create code file
803    file(WRITE "${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp" "#include \"${SRC_FILE}\" // IWYU pragma: keep\n\nint main()\n{}\n")
804    # create executable
805    add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp)
806    target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
807    target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
808    set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
809    # remember binary for ci_single_binaries target
810    list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
811endforeach()
812
813add_custom_target(ci_single_binaries
814    DEPENDS ${single_binaries}
815    COMMENT "Check if headers are self-contained"
816)
817
818###############################################################################
819# Benchmarks
820###############################################################################
821
822add_custom_target(ci_benchmarks
823    COMMAND ${CMAKE_COMMAND}
824        -DCMAKE_BUILD_TYPE=Release -GNinja
825        -S${PROJECT_SOURCE_DIR}/benchmarks -B${PROJECT_BINARY_DIR}/build_benchmarks
826    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_benchmarks --target json_benchmarks
827    COMMAND cd ${PROJECT_BINARY_DIR}/build_benchmarks && ./json_benchmarks
828    COMMENT "Run benchmarks"
829)
830
831###############################################################################
832# CMake flags
833###############################################################################
834
835function(ci_get_cmake version var)
836    if (APPLE)
837        set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}-Darwin64/CMake.app/Contents/bin/cmake)
838        add_custom_command(
839            OUTPUT ${${var}}
840            COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-Darwin64.tar.gz
841            COMMAND tar xfz cmake-${version}-Darwin64.tar.gz
842            COMMAND rm cmake-${version}-Darwin64.tar.gz
843            WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
844            COMMENT "Download CMake ${version}"
845        )
846    else()
847        set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}-Linux-x86_64/bin/cmake)
848        add_custom_command(
849            OUTPUT ${${var}}
850            COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-Linux-x86_64.tar.gz
851            COMMAND tar xfz cmake-${version}-Linux-x86_64.tar.gz
852            COMMAND rm cmake-${version}-Linux-x86_64.tar.gz
853            WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
854            COMMENT "Download CMake ${version}"
855        )
856    endif()
857    set(${var} ${${var}} PARENT_SCOPE)
858endfunction()
859
860ci_get_cmake(3.1.0 CMAKE_3_1_0_BINARY)
861ci_get_cmake(3.13.0 CMAKE_3_13_0_BINARY)
862
863set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
864    JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind)
865set(JSON_CMAKE_FLAGS_3_13_0 JSON_BuildTests)
866
867function(ci_add_cmake_flags_targets flag min_version)
868    string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
869    string(REPLACE . _ min_version_var ${min_version})
870    set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
871    add_custom_target(${flag_target}
872        COMMENT "Check CMake flag ${flag} (CMake ${CMAKE_VERSION})"
873        COMMAND ${CMAKE_COMMAND}
874            -Werror=dev
875            -D${flag}=ON
876            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
877    )
878    add_custom_target(${flag_target}_${min_version_var}
879        COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${min_version})"
880        COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
881        COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
882            && ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
883        DEPENDS ${cmake_binary}
884    )
885    list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${flag_target}_${min_version_var})
886    list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target} ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
887    set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
888    set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
889endfunction()
890
891foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_1_0})
892    ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.1.0)
893endforeach()
894
895foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_13_0})
896    ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.13.0)
897endforeach()
898
899add_custom_target(ci_cmake_flags
900    DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
901    COMMENT "Check CMake flags"
902)
903
904###############################################################################
905# Use more installed compilers.
906###############################################################################
907
908foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14)
909    find_program(COMPILER_TOOL NAMES ${COMPILER})
910    if (COMPILER_TOOL)
911        if ("${COMPILER}" STREQUAL "clang++-9")
912            # fix for https://github.com/nlohmann/json/pull/3101#issuecomment-998788786 / https://stackoverflow.com/a/64051725/266378
913            set(ADDITIONAL_FLAGS "-DCMAKE_CXX_FLAGS=--gcc-toolchain=/root/gcc/9")
914        else()
915            unset(ADDITIONAL_FLAGS)
916        endif()
917
918        add_custom_target(ci_test_compiler_${COMPILER}
919            COMMAND CXX=${COMPILER} ${CMAKE_COMMAND}
920                -DCMAKE_BUILD_TYPE=Debug -GNinja
921                -DJSON_BuildTests=ON -DJSON_FastTests=ON
922                -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
923                ${ADDITIONAL_FLAGS}
924            COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
925            COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
926            COMMENT "Compile and test with ${COMPILER}"
927        )
928    endif()
929    unset(COMPILER_TOOL CACHE)
930endforeach()
931
932###############################################################################
933# CUDA example
934###############################################################################
935
936add_custom_target(ci_cuda_example
937    COMMAND ${CMAKE_COMMAND}
938        -DCMAKE_BUILD_TYPE=Debug -GNinja
939        -DCMAKE_CUDA_HOST_COMPILER=g++-8
940        -S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example
941    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example
942)
943
944###############################################################################
945# Intel C++ Compiler
946###############################################################################
947
948add_custom_target(ci_icpc
949    COMMAND ${CMAKE_COMMAND}
950        -DCMAKE_BUILD_TYPE=Debug -GNinja
951        -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc
952        -DJSON_BuildTests=ON -DJSON_FastTests=ON
953        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpc
954    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpc
955    COMMAND cd ${PROJECT_BINARY_DIR}/build_icpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
956    COMMENT "Compile and test with ICPC"
957)
958
959###############################################################################
960# test documentation
961###############################################################################
962
963add_custom_target(ci_test_examples
964    COMMAND make CXX="${GCC_TOOL}" check_output_portable -j8
965    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/docs
966    COMMENT "Check that all examples compile and create the desired output"
967)
968
969add_custom_target(ci_test_api_documentation
970    COMMAND ${Python3_EXECUTABLE} scripts/check_structure.py
971    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/docs/mkdocs
972    COMMENT "Lint the API documentation"
973)
974
975###############################################################################
976# Clean up all generated files.
977###############################################################################
978
979add_custom_target(ci_clean
980    COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* cmake-3.1.0-Darwin64 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
981    COMMENT "Clean generated directories"
982)
983