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++-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-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++-HEAD g++-11 g++-latest)
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-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 "-std=c++11                        \
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# Ignored GCC warnings:
115# -Wno-abi-tag                    We do not care about ABI tags.
116# -Wno-aggregate-return           The library uses aggregate returns.
117# -Wno-long-long                  The library uses the long long type to interface with system functions.
118# -Wno-namespaces                 The library uses namespaces.
119# -Wno-padded                     We do not care about padding warnings.
120# -Wno-system-headers             We do not care about warnings in system headers.
121# -Wno-templates                  The library uses templates.
122
123set(GCC_CXXFLAGS "-std=c++11                          \
124    -pedantic                                         \
125    -Werror                                           \
126    --all-warnings                                    \
127    --extra-warnings                                  \
128    -W                                                \
129    -WNSObject-attribute                              \
130    -Wno-abi-tag                                         \
131    -Waddress                                         \
132    -Waddress-of-packed-member                        \
133    -Wno-aggregate-return                                \
134    -Waggressive-loop-optimizations                   \
135    -Waligned-new=all                                 \
136    -Wall                                             \
137    -Walloc-zero                                      \
138    -Walloca                                          \
139    -Wanalyzer-double-fclose                          \
140    -Wanalyzer-double-free                            \
141    -Wanalyzer-exposure-through-output-file           \
142    -Wanalyzer-file-leak                              \
143    -Wanalyzer-free-of-non-heap                       \
144    -Wanalyzer-malloc-leak                            \
145    -Wanalyzer-mismatching-deallocation               \
146    -Wanalyzer-null-argument                          \
147    -Wanalyzer-null-dereference                       \
148    -Wanalyzer-possible-null-argument                 \
149    -Wanalyzer-possible-null-dereference              \
150    -Wanalyzer-shift-count-negative                   \
151    -Wanalyzer-shift-count-overflow                   \
152    -Wanalyzer-stale-setjmp-buffer                    \
153    -Wanalyzer-tainted-array-index                    \
154    -Wanalyzer-too-complex                            \
155    -Wanalyzer-unsafe-call-within-signal-handler      \
156    -Wanalyzer-use-after-free                         \
157    -Wanalyzer-use-of-pointer-in-stale-stack-frame    \
158    -Wanalyzer-write-to-const                         \
159    -Wanalyzer-write-to-string-literal                \
160    -Warith-conversion                                \
161    -Warray-bounds                                    \
162    -Warray-bounds=2                                  \
163    -Warray-parameter=2                               \
164    -Wattribute-alias=2                               \
165    -Wattribute-warning                               \
166    -Wattributes                                      \
167    -Wbool-compare                                    \
168    -Wbool-operation                                  \
169    -Wbuiltin-declaration-mismatch                    \
170    -Wbuiltin-macro-redefined                         \
171    -Wc++0x-compat                                    \
172    -Wc++11-compat                                    \
173    -Wc++14-compat                                    \
174    -Wc++17-compat                                    \
175    -Wc++1z-compat                                    \
176    -Wc++20-compat                                    \
177    -Wc++2a-compat                                    \
178    -Wcannot-profile                                  \
179    -Wcast-align                                      \
180    -Wcast-align=strict                               \
181    -Wcast-function-type                              \
182    -Wcast-qual                                       \
183    -Wcatch-value=3                                   \
184    -Wchar-subscripts                                 \
185    -Wclass-conversion                                \
186    -Wclass-memaccess                                 \
187    -Wclobbered                                       \
188    -Wcomma-subscript                                 \
189    -Wcomment                                         \
190    -Wcomments                                        \
191    -Wconditionally-supported                         \
192    -Wconversion                                      \
193    -Wconversion-null                                 \
194    -Wcoverage-mismatch                               \
195    -Wcpp                                             \
196    -Wctad-maybe-unsupported                          \
197    -Wctor-dtor-privacy                               \
198    -Wdangling-else                                   \
199    -Wdate-time                                       \
200    -Wdelete-incomplete                               \
201    -Wdelete-non-virtual-dtor                         \
202    -Wdeprecated                                      \
203    -Wdeprecated-copy                                 \
204    -Wdeprecated-copy-dtor                            \
205    -Wdeprecated-declarations                         \
206    -Wdeprecated-enum-enum-conversion                 \
207    -Wdeprecated-enum-float-conversion                \
208    -Wdisabled-optimization                           \
209    -Wdiv-by-zero                                     \
210    -Wdouble-promotion                                \
211    -Wduplicated-branches                             \
212    -Wduplicated-cond                                 \
213    -Weffc++                                          \
214    -Wempty-body                                      \
215    -Wendif-labels                                    \
216    -Wenum-compare                                    \
217    -Wenum-conversion                                 \
218    -Wexpansion-to-defined                            \
219    -Wextra                                           \
220    -Wextra-semi                                      \
221    -Wfloat-conversion                                \
222    -Wfloat-equal                                     \
223    -Wformat-contains-nul                             \
224    -Wformat-diag                                     \
225    -Wformat-extra-args                               \
226    -Wformat-nonliteral                               \
227    -Wformat-overflow=2                               \
228    -Wformat-security                                 \
229    -Wformat-signedness                               \
230    -Wformat-truncation=2                             \
231    -Wformat-y2k                                      \
232    -Wformat-zero-length                              \
233    -Wformat=2                                        \
234    -Wframe-address                                   \
235    -Wfree-nonheap-object                             \
236    -Whsa                                             \
237    -Wif-not-aligned                                  \
238    -Wignored-attributes                              \
239    -Wignored-qualifiers                              \
240    -Wimplicit-fallthrough=5                          \
241    -Winaccessible-base                               \
242    -Winherited-variadic-ctor                         \
243    -Winit-list-lifetime                              \
244    -Winit-self                                       \
245    -Winline                                          \
246    -Wint-in-bool-context                             \
247    -Wint-to-pointer-cast                             \
248    -Winvalid-memory-model                            \
249    -Winvalid-offsetof                                \
250    -Winvalid-pch                                     \
251    -Wliteral-suffix                                  \
252    -Wlogical-not-parentheses                         \
253    -Wlogical-op                                      \
254    -Wno-long-long                                       \
255    -Wlto-type-mismatch                               \
256    -Wmain                                            \
257    -Wmaybe-uninitialized                             \
258    -Wmemset-elt-size                                 \
259    -Wmemset-transposed-args                          \
260    -Wmisleading-indentation                          \
261    -Wmismatched-dealloc                              \
262    -Wmismatched-new-delete                           \
263    -Wmismatched-tags                                 \
264    -Wmissing-attributes                              \
265    -Wmissing-braces                                  \
266    -Wmissing-declarations                            \
267    -Wmissing-field-initializers                      \
268    -Wmissing-include-dirs                            \
269    -Wmissing-profile                                 \
270    -Wmultichar                                       \
271    -Wmultiple-inheritance                            \
272    -Wmultistatement-macros                           \
273    -Wno-namespaces                                      \
274    -Wnarrowing                                       \
275    -Wnoexcept                                        \
276    -Wnoexcept-type                                   \
277    -Wnon-template-friend                             \
278    -Wnon-virtual-dtor                                \
279    -Wnonnull                                         \
280    -Wnonnull-compare                                 \
281    -Wnormalized=nfkc                                 \
282    -Wnull-dereference                                \
283    -Wodr                                             \
284    -Wold-style-cast                                  \
285    -Wopenmp-simd                                     \
286    -Woverflow                                        \
287    -Woverlength-strings                              \
288    -Woverloaded-virtual                              \
289    -Wpacked                                          \
290    -Wpacked-bitfield-compat                          \
291    -Wpacked-not-aligned                              \
292    -Wno-padded                                          \
293    -Wparentheses                                     \
294    -Wpedantic                                        \
295    -Wpessimizing-move                                \
296    -Wplacement-new=2                                 \
297    -Wpmf-conversions                                 \
298    -Wpointer-arith                                   \
299    -Wpointer-compare                                 \
300    -Wpragmas                                         \
301    -Wprio-ctor-dtor                                  \
302    -Wpsabi                                           \
303    -Wrange-loop-construct                            \
304    -Wredundant-decls                                 \
305    -Wredundant-move                                  \
306    -Wredundant-tags                                  \
307    -Wregister                                        \
308    -Wreorder                                         \
309    -Wrestrict                                        \
310    -Wreturn-local-addr                               \
311    -Wreturn-type                                     \
312    -Wscalar-storage-order                            \
313    -Wsequence-point                                  \
314    -Wshadow=compatible-local                         \
315    -Wshadow=global                                   \
316    -Wshadow=local                                    \
317    -Wshift-count-negative                            \
318    -Wshift-count-overflow                            \
319    -Wshift-negative-value                            \
320    -Wshift-overflow=2                                \
321    -Wsign-compare                                    \
322    -Wsign-conversion                                 \
323    -Wsign-promo                                      \
324    -Wsized-deallocation                              \
325    -Wsizeof-array-argument                           \
326    -Wsizeof-array-div                                \
327    -Wsizeof-pointer-div                              \
328    -Wsizeof-pointer-memaccess                        \
329    -Wstack-protector                                 \
330    -Wstrict-aliasing                                 \
331    -Wstrict-aliasing=3                               \
332    -Wstrict-null-sentinel                            \
333    -Wstrict-overflow                                 \
334    -Wstrict-overflow=5                               \
335    -Wstring-compare                                  \
336    -Wstringop-overflow=4                             \
337    -Wstringop-overread                               \
338    -Wstringop-truncation                             \
339    -Wsubobject-linkage                               \
340    -Wsuggest-attribute=cold                          \
341    -Wsuggest-attribute=const                         \
342    -Wsuggest-attribute=format                        \
343    -Wsuggest-attribute=malloc                        \
344    -Wsuggest-attribute=noreturn                      \
345    -Wsuggest-attribute=pure                          \
346    -Wsuggest-final-methods                           \
347    -Wsuggest-final-types                             \
348    -Wsuggest-override                                \
349    -Wswitch                                          \
350    -Wswitch-bool                                     \
351    -Wswitch-default                                  \
352    -Wswitch-enum                                     \
353    -Wswitch-outside-range                            \
354    -Wswitch-unreachable                              \
355    -Wsync-nand                                       \
356    -Wsynth                                           \
357    -Wno-system-headers                                  \
358    -Wtautological-compare                            \
359    -Wno-templates                                       \
360    -Wterminate                                       \
361    -Wtrampolines                                     \
362    -Wtrigraphs                                       \
363    -Wtsan                                            \
364    -Wtype-limits                                     \
365    -Wundef                                           \
366    -Wuninitialized                                   \
367    -Wunknown-pragmas                                 \
368    -Wunreachable-code                                \
369    -Wunsafe-loop-optimizations                       \
370    -Wunused                                          \
371    -Wunused-but-set-parameter                        \
372    -Wunused-but-set-variable                         \
373    -Wunused-const-variable=2                         \
374    -Wunused-function                                 \
375    -Wunused-label                                    \
376    -Wunused-local-typedefs                           \
377    -Wunused-macros                                   \
378    -Wunused-parameter                                \
379    -Wunused-result                                   \
380    -Wunused-value                                    \
381    -Wunused-variable                                 \
382    -Wuseless-cast                                    \
383    -Wvarargs                                         \
384    -Wvariadic-macros                                 \
385    -Wvector-operation-performance                    \
386    -Wvexing-parse                                    \
387    -Wvirtual-inheritance                             \
388    -Wvirtual-move-assign                             \
389    -Wvla                                             \
390    -Wvla-parameter                                   \
391    -Wvolatile                                        \
392    -Wvolatile-register-var                           \
393    -Wwrite-strings                                   \
394    -Wzero-as-null-pointer-constant                   \
395    -Wzero-length-bounds                              \
396")
397
398add_custom_target(ci_test_gcc
399    COMMAND CXX=${GCC_TOOL} CXXFLAGS=${GCC_CXXFLAGS} ${CMAKE_COMMAND}
400        -DCMAKE_BUILD_TYPE=Debug -GNinja
401        -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
402        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc
403    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc
404    COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
405    COMMENT "Compile and test with GCC using maximal warning flags"
406)
407
408add_custom_target(ci_test_clang
409    COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXXFLAGS} ${CMAKE_COMMAND}
410        -DCMAKE_BUILD_TYPE=Debug -GNinja
411        -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
412        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang
413    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang
414    COMMAND cd ${PROJECT_BINARY_DIR}/build_clang && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
415    COMMENT "Compile and test with Clang using maximal warning flags"
416)
417
418###############################################################################
419# Different C++ Standards.
420###############################################################################
421
422foreach(CXX_STANDARD 11 14 17 20)
423    add_custom_target(ci_test_gcc_cxx${CXX_STANDARD}
424        COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND}
425            -DCMAKE_BUILD_TYPE=Debug -GNinja
426            -DCMAKE_CXX_STANDARD=${CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON
427            -DJSON_BuildTests=ON -DJSON_FastTests=ON
428            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
429        COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
430        COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
431        COMMENT "Compile and test with GCC for C++${CXX_STANDARD}"
432    )
433
434    add_custom_target(ci_test_clang_cxx${CXX_STANDARD}
435        COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
436            -DCMAKE_BUILD_TYPE=Debug -GNinja
437            -DCMAKE_CXX_STANDARD=${CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON
438            -DJSON_BuildTests=ON
439            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
440        COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
441        COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
442        COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
443    )
444endforeach()
445
446###############################################################################
447# Disable exceptions.
448###############################################################################
449
450add_custom_target(ci_test_noexceptions
451    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
452    -DCMAKE_BUILD_TYPE=Debug -GNinja
453    -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw
454    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noexceptions
455    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noexceptions
456    COMMAND cd ${PROJECT_BINARY_DIR}/build_noexceptions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
457    COMMENT "Compile and test with exceptions switched off"
458)
459
460###############################################################################
461# Disable implicit conversions.
462###############################################################################
463
464add_custom_target(ci_test_noimplicitconversions
465    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
466    -DCMAKE_BUILD_TYPE=Debug -GNinja
467    -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_ImplicitConversions=OFF
468    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noimplicitconversions
469    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noimplicitconversions
470    COMMAND cd ${PROJECT_BINARY_DIR}/build_noimplicitconversions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
471    COMMENT "Compile and test with implicit conversions switched off"
472)
473
474###############################################################################
475# Enable improved diagnostics.
476###############################################################################
477
478add_custom_target(ci_test_diagnostics
479    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
480    -DCMAKE_BUILD_TYPE=Debug -GNinja
481    -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_Diagnostics=ON
482    -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostics
483    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostics
484    COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostics && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
485    COMMENT "Compile and test with improved diagnostics enabled"
486)
487
488###############################################################################
489# Coverage.
490###############################################################################
491
492add_custom_target(ci_test_coverage
493    COMMAND CXX=g++ ${CMAKE_COMMAND}
494        -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage"
495        -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
496        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage
497    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage
498    COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
499
500    COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc lcov_branch_coverage=1
501    COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc lcov_branch_coverage=1
502    COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept
503    COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept
504
505    COMMENT "Compile and test with coverage"
506)
507
508###############################################################################
509# Sanitizers.
510###############################################################################
511
512set(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")
513
514add_custom_target(ci_test_clang_sanitizer
515    COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXX_FLAGS_SANITIZER} ${CMAKE_COMMAND}
516        -DCMAKE_BUILD_TYPE=Debug -GNinja
517        -DJSON_BuildTests=ON
518        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_sanitizer
519    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_sanitizer
520    COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_sanitizer && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
521    COMMENT "Compile and test with sanitizers"
522)
523
524###############################################################################
525# Check if header is amalgamated and sources are properly indented.
526###############################################################################
527
528set(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)
529
530file(GLOB_RECURSE INDENT_FILES
531    ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
532    ${PROJECT_SOURCE_DIR}/test/src/*.cpp
533    ${PROJECT_SOURCE_DIR}/test/src/*.hpp
534    ${PROJECT_SOURCE_DIR}/benchmarks/src/benchmarks.cpp
535    ${PROJECT_SOURCE_DIR}/doc/examples/*.cpp
536)
537
538add_custom_target(ci_test_amalgamation
539    COMMAND rm -fr ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~
540    COMMAND cp ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~
541    COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/third_party/amalgamate/amalgamate.py -c ${PROJECT_SOURCE_DIR}/third_party/amalgamate/config.json -s .
542    COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp
543    COMMAND diff ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp
544
545    COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} ${INDENT_FILES}
546    COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `find . -name '*.orig'`\; do false \; done
547
548    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
549    COMMENT "Check amalagamation and indentation"
550)
551
552###############################################################################
553# Valgrind.
554###############################################################################
555
556add_custom_target(ci_test_valgrind
557    COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND}
558        -DCMAKE_BUILD_TYPE=Debug -GNinja
559        -DJSON_BuildTests=ON -DJSON_Valgrind=ON
560        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_valgrind
561    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_valgrind
562    COMMAND cd ${PROJECT_BINARY_DIR}/build_valgrind && ${CMAKE_CTEST_COMMAND} -L valgrind --parallel ${N} --output-on-failure
563    COMMENT "Compile and test with Valgrind"
564)
565
566###############################################################################
567# Check code with Clang Static Analyzer.
568###############################################################################
569
570set(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")
571
572add_custom_target(ci_clang_analyze
573    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
574        -DCMAKE_BUILD_TYPE=Debug -GNinja
575        -DJSON_BuildTests=ON
576        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
577    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
578    COMMENT "Check code with Clang Analyzer"
579)
580
581###############################################################################
582# Check code with Cppcheck.
583###############################################################################
584
585add_custom_target(ci_cppcheck
586    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
587    COMMENT "Check code with Cppcheck"
588)
589
590###############################################################################
591# Check code with cpplint.
592###############################################################################
593
594add_custom_target(ci_cpplint
595    COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/third_party/cpplint/cpplint.py --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES}
596    COMMENT "Check code with cpplint"
597)
598
599###############################################################################
600# Check code with OCLint.
601###############################################################################
602
603file(COPY ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp DESTINATION ${PROJECT_BINARY_DIR}/src_single)
604file(RENAME ${PROJECT_BINARY_DIR}/src_single/json.hpp ${PROJECT_BINARY_DIR}/src_single/all.cpp)
605file(APPEND "${PROJECT_BINARY_DIR}/src_single/all.cpp" "\n\nint main()\n{}\n")
606
607add_executable(single_all ${PROJECT_BINARY_DIR}/src_single/all.cpp)
608target_compile_features(single_all PRIVATE cxx_std_11)
609
610add_custom_target(ci_oclint
611    COMMAND ${CMAKE_COMMAND}
612        -DCMAKE_BUILD_TYPE=Debug
613        -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
614        -DJSON_BuildTests=OFF -DJSON_CI=ON
615        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_oclint
616    COMMAND ${OCLINT_TOOL} -i ${PROJECT_BINARY_DIR}/build_oclint/src_single/all.cpp -p ${PROJECT_BINARY_DIR}/build_oclint --
617        -report-type html -enable-global-analysis --max-priority-1=0 --max-priority-2=1000 --max-priority-3=2000
618        --disable-rule=MultipleUnaryOperator
619        --disable-rule=DoubleNegative
620        --disable-rule=ShortVariableName
621        --disable-rule=GotoStatement
622        --disable-rule=LongLine
623        -o ${PROJECT_BINARY_DIR}/build_oclint/oclint_report.html
624    COMMENT "Check code with OCLint"
625)
626
627###############################################################################
628# Check code with Clang-Tidy.
629###############################################################################
630
631add_custom_target(ci_clang_tidy
632    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
633        -DCMAKE_BUILD_TYPE=Debug -GNinja
634        -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_CLANG_TIDY=${CLANG_TIDY_TOOL}
635        -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
636        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_tidy
637    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_tidy
638    COMMENT "Check code with Clang-Tidy"
639)
640
641###############################################################################
642# Check code with PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>.
643###############################################################################
644
645add_custom_target(ci_pvs_studio
646    COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
647        -DCMAKE_BUILD_TYPE=Debug
648        -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
649        -DJSON_BuildTests=ON
650        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_pvs_studio
651    COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PVS_STUDIO_ANALYZER_TOOL} analyze -j 10
652    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
653    COMMENT "Check code with PVS Studio"
654)
655
656###############################################################################
657# Check code with Infer <https://fbinfer.com> static analyzer.
658###############################################################################
659
660add_custom_target(ci_infer
661    COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
662    COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
663    COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make
664    COMMENT "Check code with Infer"
665)
666
667###############################################################################
668# Run test suite with previously downloaded test data.
669###############################################################################
670
671add_custom_target(ci_offline_testdata
672    COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data
673    COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.0.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1
674    COMMAND ${CMAKE_COMMAND}
675        -DCMAKE_BUILD_TYPE=Debug -GNinja
676        -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_TestDataDirectory=${PROJECT_BINARY_DIR}/build_offline_testdata/test_data/json_test_data
677        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_offline_testdata
678    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_offline_testdata
679    COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
680    COMMENT "Check code with previously downloaded test data"
681)
682
683###############################################################################
684# Run test suite when project was not checked out from Git
685###############################################################################
686
687add_custom_target(ci_non_git_tests
688    COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_non_git_tests/sources
689    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
690    COMMAND ${CMAKE_COMMAND}
691        -DCMAKE_BUILD_TYPE=Debug -GNinja
692        -DJSON_BuildTests=ON -DJSON_FastTests=ON
693        -S${PROJECT_BINARY_DIR}/build_non_git_tests/sources -B${PROJECT_BINARY_DIR}/build_non_git_tests
694    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_non_git_tests
695    COMMAND cd ${PROJECT_BINARY_DIR}/build_non_git_tests && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE git_required --output-on-failure
696    COMMENT "Check code when project was not checked out from Git"
697)
698
699###############################################################################
700# Run test suite and exclude tests that change installed files
701###############################################################################
702
703add_custom_target(ci_reproducible_tests
704    COMMAND ${CMAKE_COMMAND}
705        -DCMAKE_BUILD_TYPE=Debug -GNinja
706        -DJSON_BuildTests=ON -DJSON_FastTests=ON
707        -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_reproducible_tests
708    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_reproducible_tests
709    COMMAND cd ${PROJECT_BINARY_DIR}/build_reproducible_tests && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE not_reproducible --output-on-failure
710    COMMENT "Check code and exclude tests that change installed files"
711)
712
713###############################################################################
714# Check if every header in the include folder includes sufficient headers to
715# be compiled individually.
716###############################################################################
717
718set(iwyu_path_and_options ${IWYU_TOOL} -Xiwyu --max_line_length=300)
719
720foreach(SRC_FILE ${SRC_FILES})
721    # get relative path of the header file
722    file(RELATIVE_PATH RELATIVE_SRC_FILE "${PROJECT_SOURCE_DIR}/include/nlohmann" "${SRC_FILE}")
723    # replace slashes and strip suffix
724    string(REPLACE "/" "_" RELATIVE_SRC_FILE "${RELATIVE_SRC_FILE}")
725    string(REPLACE ".hpp" "" RELATIVE_SRC_FILE "${RELATIVE_SRC_FILE}")
726    # create code file
727    file(WRITE "${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp" "#include \"${SRC_FILE}\" // IWYU pragma: keep\n\nint main()\n{}\n")
728    # create executable
729    add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp)
730    target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
731    target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
732    set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
733    # remember binary for ci_single_binaries target
734    list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
735endforeach()
736
737add_custom_target(ci_single_binaries
738    DEPENDS ${single_binaries}
739    COMMENT "Check if headers are self-contained"
740)
741
742###############################################################################
743# Benchmarks
744###############################################################################
745
746add_custom_target(ci_benchmarks
747    COMMAND ${CMAKE_COMMAND}
748        -DCMAKE_BUILD_TYPE=Release -GNinja
749        -S${PROJECT_SOURCE_DIR}/benchmarks -B${PROJECT_BINARY_DIR}/build_benchmarks
750    COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_benchmarks --target json_benchmarks
751    COMMAND cd ${PROJECT_BINARY_DIR}/build_benchmarks && ./json_benchmarks
752    COMMENT "Run benchmarks"
753)
754
755###############################################################################
756# CMake flags
757###############################################################################
758
759if (APPLE)
760    set(CMAKE_310_BINARY ${PROJECT_BINARY_DIR}/cmake-3.1.0-Darwin64/CMake.app/Contents/bin/cmake)
761    add_custom_command(
762        OUTPUT ${CMAKE_310_BINARY}
763        COMMAND wget https://github.com/Kitware/CMake/releases/download/v3.1.0/cmake-3.1.0-Darwin64.tar.gz
764        COMMAND tar xfz cmake-3.1.0-Darwin64.tar.gz
765        COMMAND rm cmake-3.1.0-Darwin64.tar.gz
766        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
767        COMMENT "Download CMake 3.1.0"
768    )
769else()
770    set(CMAKE_310_BINARY ${PROJECT_BINARY_DIR}/cmake-3.1.0-Linux-x86_64/bin/cmake)
771    add_custom_command(
772        OUTPUT ${CMAKE_310_BINARY}
773        COMMAND wget https://github.com/Kitware/CMake/releases/download/v3.1.0/cmake-3.1.0-Linux-x86_64.tar.gz
774        COMMAND tar xfz cmake-3.1.0-Linux-x86_64.tar.gz
775        COMMAND rm cmake-3.1.0-Linux-x86_64.tar.gz
776        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
777        COMMENT "Download CMake 3.1.0"
778    )
779endif()
780
781set(JSON_CMAKE_FLAGS "JSON_BuildTests;JSON_Install;JSON_MultipleHeaders;JSON_ImplicitConversions;JSON_Valgrind;JSON_Diagnostics;JSON_SystemInclude")
782
783foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS})
784    string(TOLOWER "ci_cmake_flag_${JSON_CMAKE_FLAG}" JSON_CMAKE_FLAG_TARGET)
785    add_custom_target("${JSON_CMAKE_FLAG_TARGET}"
786        COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${CMAKE_VERSION})"
787        COMMAND ${CMAKE_COMMAND}
788            -Werror=dev
789            -D${JSON_CMAKE_FLAG}=ON
790            -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}
791    )
792    add_custom_target("${JSON_CMAKE_FLAG_TARGET}_31"
793        COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake 3.1)"
794        COMMAND mkdir ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31
795        COMMAND cd ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31 && ${CMAKE_310_BINARY}
796            -Werror=dev ${PROJECT_SOURCE_DIR}
797            -D${JSON_CMAKE_FLAG}=ON
798            -DCMAKE_CXX_COMPILE_FEATURES="cxx_range_for" -DCMAKE_CXX_FLAGS="-std=gnu++11"
799        DEPENDS ${CMAKE_310_BINARY}
800    )
801    list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${JSON_CMAKE_FLAG_TARGET}_31)
802    list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET} ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31)
803endforeach()
804
805add_custom_target(ci_cmake_flags
806    DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
807    COMMENT "Check CMake flags"
808)
809
810###############################################################################
811# Use more installed compilers.
812###############################################################################
813
814foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-7 g++-8 g++-9 g++-10 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)
815    find_program(COMPILER_TOOL NAMES ${COMPILER})
816    if (COMPILER_TOOL)
817        add_custom_target(ci_test_compiler_${COMPILER}
818            COMMAND CXX=${COMPILER} ${CMAKE_COMMAND}
819                -DCMAKE_BUILD_TYPE=Debug -GNinja
820                -DJSON_BuildTests=ON -DJSON_FastTests=ON
821                -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
822            COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
823            COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
824            COMMENT "Compile and test with ${COMPILER}"
825        )
826    endif()
827    unset(COMPILER_TOOL CACHE)
828endforeach()
829
830###############################################################################
831# Clean up all generated files.
832###############################################################################
833
834add_custom_target(ci_clean
835    COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* cmake-3.1.0-Darwin64 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
836    COMMENT "Clean generated directories"
837)
838