Browse code

Add project

Robert Cranston authored on 14/10/2022 21:57:18
Showing 6 changed files

1 1
new file mode 100644
... ...
@@ -0,0 +1,59 @@
1
+---
2
+
3
+WarningsAsErrors: >
4
+    # All,
5
+    *,
6
+
7
+Checks: >
8
+    # All,
9
+    *,
10
+
11
+    # Company/project-specific,
12
+    -google-*,
13
+    -llvm-*,
14
+    -llvmlibc-*,
15
+    -fuchsia-*,
16
+    -altera-*,
17
+
18
+    # Extra command line arguments,
19
+    -clang-diagnostic-unknown-warning-option,
20
+    -clang-diagnostic-ignored-optimization-argument,
21
+
22
+    # "Consider",
23
+    -cppcoreguidelines-avoid-non-const-global-variables,
24
+
25
+    # Style,
26
+    -*-use-trailing-return-type,
27
+    -*-container-size-empty,
28
+    -*-easily-swappable-parameters,
29
+
30
+    # Verbosity,
31
+    -*-braces-around-statements,
32
+    -*-implicit-bool-conversion,
33
+    -*-static-accessed-through-instance,
34
+    -*-named-parameter,
35
+
36
+    # -Weffc++,
37
+    -*-redundant-member-init,
38
+
39
+    # Interaction with C,
40
+    -*-cast*,
41
+    -*-vararg,
42
+    -*array-*decay,
43
+
44
+    # Backwards compatibility,
45
+    -*-union-access,
46
+
47
+    # Static storage duration throwing constructors,
48
+    -cert-err58-cpp,
49
+
50
+    # Complex functions,
51
+    -*readability-function-cognitive-complexity,
52
+
53
+    # Macro magic,
54
+    -*-macro-usage,
55
+    -*bugprone-macro-parentheses,
56
+    -*bugprone-lambda-function-name,
57
+
58
+    # Exceptions,
59
+    -*bugprone-exception-escape,
0 60
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+/_build
0 2
new file mode 100644
... ...
@@ -0,0 +1,94 @@
1
+# Building
2
+
3
+This project supports [CMake][] and uses [`cmake-common`][]. There are several
4
+ways to use it in other CMake-based projects:
5
+
6
+-   With [`find_package`][]: ([Package][] and) [install][] it on the system.
7
+
8
+-   With [`add_subdirectory`][]: Bundle it.
9
+
10
+-   With [`FetchContent`][]: Download it as part of the CMake configure step.
11
+
12
+-   With [`cmake-common`][]: Use any of the above methods through a simplified
13
+    interface.
14
+
15
+As usual, use [`add_dependencies`][] or [`target_link_libraries`][] (or
16
+`cmake-common`'s `DEPENDENCIES_*`) to declare the dependency.
17
+
18
+[CMake]: https://cmake.org
19
+[`cmake-common`]: https://git.rcrnstn.net/rcrnstn/cmake-common
20
+[`FetchContent`]: https://cmake.org/cmake/help/v3.14/module/FetchContent.html
21
+[`add_subdirectory`]: https://cmake.org/cmake/help/v3.14/command/add_subdirectory.html
22
+[`find_package`]: https://cmake.org/cmake/help/v3.14/command/find_package.html
23
+[Package]: #Package
24
+[Install]: #Install
25
+[`add_dependencies`]: https://cmake.org/cmake/help/v3.14/command/add_dependencies.html
26
+[`target_link_libraries`]: https://cmake.org/cmake/help/v3.14/command/target_link_libraries.html
27
+
28
+## Configure and generate
29
+
30
+To configure and generate a build tree, use [`cmake`][]:
31
+
32
+```sh
33
+cmake -B _build
34
+```
35
+
36
+To set the build type, pass e.g. `-D`[`CMAKE_BUILD_TYPE`][]`=Release`.
37
+
38
+To disable building tests, pass `-D`[`BUILD_TESTING`][]`=OFF`.
39
+
40
+[`cmake`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#generate-a-project-buildsystem
41
+[`CMAKE_BUILD_TYPE`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_BUILD_TYPE.html
42
+[`BUILD_TESTING`]: https://cmake.org/cmake/help/v3.14/module/CTest.html
43
+
44
+## Build
45
+
46
+To build, use [`cmake --build`][]:
47
+
48
+```sh
49
+cmake --build _build
50
+```
51
+
52
+To build in parallel with native build tools that do not do this by default
53
+(such as [GNU Make][]), pass `--parallel` followed by the number of concurrent
54
+processes to use, e.g. `$(`[`nproc`][]`)`.
55
+
56
+[`cmake --build`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#build-a-project
57
+[GNU Make]: https://www.gnu.org/software/make/
58
+[`nproc`]: https://www.gnu.org/software/coreutils/manual/html_node/nproc-invocation.html
59
+
60
+## Test
61
+
62
+To run tests, use [`ctest`][]:
63
+
64
+```sh
65
+(cd _build && ctest)
66
+```
67
+
68
+To show output from failing tests, pass `--output-on-failure`. To show output
69
+from all tests, pass `--verbose`.
70
+
71
+[`ctest`]: https://cmake.org/cmake/help/v3.14/manual/ctest.1.html
72
+
73
+## Package
74
+
75
+To package, use [`cpack`][]:
76
+
77
+```sh
78
+(cd _build && cpack)
79
+```
80
+
81
+[`cpack`]: https://cmake.org/cmake/help/v3.14/manual/cpack.1.html
82
+
83
+## Install
84
+
85
+To install onto the current system, use [`cmake --install`][]:
86
+
87
+```sh
88
+cmake --install _build
89
+```
90
+
91
+To set the prefix, pass e.g. `-D`[`CMAKE_INSTALL_PREFIX`][]`="$HOME/.local"`.
92
+
93
+[`cmake --install`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#install-a-project
94
+[`CMAKE_INSTALL_PREFIX`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_INSTALL_PREFIX.html
0 95
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+## CMake
2
+cmake_minimum_required(VERSION 3.14)
3
+if(NOT CMAKE_BUILD_TYPE)
4
+    set(CMAKE_BUILD_TYPE Debug)
5
+endif()
6
+
7
+## Project
8
+project(gltraits
9
+    VERSION 1.0.0
10
+    LANGUAGES CXX
11
+)
... ...
@@ -27,6 +27,12 @@ language features).
27 27
 [extension]: https://www.khronos.org/opengl/wiki/OpenGL_Extension
28 28
 [GLSL]: https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language
29 29
 
30
+## Building
31
+
32
+See [`BUILDING.md`][].
33
+
34
+[`BUILDING.md`]: BUILDING.md
35
+
30 36
 ## License
31 37
 
32 38
 Licensed under the [ISC License][] unless otherwise noted, see the
33 39
new file mode 100644
... ...
@@ -0,0 +1,412 @@
1
+# https://git.rcrnstn.net/rcrnstn/cmake-common
2
+
3
+## CMake modules
4
+include(FetchContent)
5
+include(CMakePackageConfigHelpers)
6
+include(CheckIPOSupported)
7
+include(GNUInstallDirs)
8
+include(CTest)
9
+if(NOT CPack_CMake_INCLUDED)
10
+    include(CPack)
11
+endif()
12
+
13
+function(common)
14
+    ## Arguments
15
+    set(OPTIONS
16
+        DISABLE_WSHADOW
17
+        DISABLE_SANITIZERS
18
+        DISABLE_CPPCHECK
19
+        DISABLE_CLANG_TIDY
20
+        DISABLE_INCLUDE_WHAT_YOU_USE
21
+    )
22
+    set(ONE_VALUE_ARGS
23
+        CXX_STANDARD
24
+    )
25
+    set(MULTI_VALUE_ARGS
26
+        PACKAGES
27
+        EXTERNAL
28
+        FETCHCONTENT
29
+        DEPENDENCIES_PUBLIC
30
+        DEPENDENCIES_PRIVATE
31
+        DEPENDENCIES_TESTS
32
+        DEFINITIONS
33
+    )
34
+    cmake_parse_arguments(PARSE_ARGV 0 ARG
35
+        "${OPTIONS}"
36
+        "${ONE_VALUE_ARGS}"
37
+        "${MULTI_VALUE_ARGS}"
38
+    )
39
+
40
+    ## Variables
41
+    set(PROJECT_IS_TOP_LEVEL)
42
+    set(PROJECT_IS_INTERFACE_LIBRARY)
43
+    set(PROJECT_IS_DEBUG)
44
+    get_target_property(PROJECT_TYPE ${PROJECT_NAME} TYPE)
45
+    string(TOLOWER "${CMAKE_BUILD_TYPE}" PROJECT_BUILD_TYPE)
46
+    if("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}")
47
+        set(PROJECT_IS_TOP_LEVEL TRUE)
48
+    endif()
49
+    if("${PROJECT_TYPE}" STREQUAL "INTERFACE_LIBRARY")
50
+        set(PROJECT_IS_INTERFACE_LIBRARY TRUE)
51
+    endif()
52
+    if("${PROJECT_BUILD_TYPE}" STREQUAL "debug")
53
+        set(PROJECT_IS_DEBUG TRUE)
54
+    endif()
55
+
56
+    ## Packages
57
+    foreach(PACKAGE ${ARG_PACKAGES})
58
+        find_package(${PACKAGE})
59
+    endforeach()
60
+
61
+    ## External
62
+    foreach(EXTERNAL ${ARG_EXTERNAL})
63
+        add_subdirectory(external/${EXTERNAL} EXCLUDE_FROM_ALL)
64
+    endforeach()
65
+
66
+    ## FetchContent
67
+    foreach(FETCHCONTENT ${ARG_FETCHCONTENT})
68
+        get_filename_component(FETCHCONTENT_NAME ${FETCHCONTENT} NAME)
69
+        FetchContent_Declare(${FETCHCONTENT_NAME}
70
+            GIT_REPOSITORY ${FETCHCONTENT}
71
+            GIT_SHALLOW TRUE
72
+            GIT_PROGRESS TRUE
73
+        )
74
+        FetchContent_MakeAvailable(${FETCHCONTENT_NAME})
75
+    endforeach()
76
+
77
+    ## Main target
78
+    target_compile_definitions(${PROJECT_NAME} PUBLIC ${ARG_DEFINITIONS})
79
+    file(GLOB_RECURSE SRC CONFIGURE_DEPENDS
80
+        RELATIVE "${PROJECT_SOURCE_DIR}"
81
+        src/*
82
+    )
83
+    file(GLOB_RECURSE INCLUDE CONFIGURE_DEPENDS
84
+        RELATIVE "${PROJECT_SOURCE_DIR}"
85
+        include/*
86
+    )
87
+    if(NOT ("${SRC}" STREQUAL "" AND "${INCLUDE}" STREQUAL ""))
88
+        if(PROJECT_IS_INTERFACE_LIBRARY)
89
+            target_include_directories(${PROJECT_NAME}
90
+                INTERFACE
91
+                    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
92
+                    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
93
+            )
94
+        else()
95
+            target_sources(${PROJECT_NAME}
96
+                PRIVATE
97
+                    ${SRC}
98
+                    ${INCLUDE}
99
+            )
100
+            target_include_directories(${PROJECT_NAME}
101
+                PUBLIC
102
+                    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
103
+                    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
104
+                PRIVATE
105
+                    src
106
+            )
107
+            target_link_libraries(${PROJECT_NAME}
108
+                PUBLIC
109
+                    ${ARG_DEPENDENCIES_PUBLIC}
110
+                PRIVATE
111
+                    "$<BUILD_INTERFACE:${ARG_DEPENDENCIES_PRIVATE}>"
112
+            )
113
+        endif()
114
+        if(PROJECT_IS_TOP_LEVEL)
115
+            install(
116
+                DIRECTORY
117
+                    include/
118
+                DESTINATION
119
+                    ${CMAKE_INSTALL_INCLUDEDIR}
120
+            )
121
+            install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME})
122
+            install(EXPORT ${PROJECT_NAME}
123
+                FILE ${PROJECT_NAME}Config.cmake
124
+                DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
125
+            )
126
+            write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
127
+                COMPATIBILITY SameMajorVersion
128
+            )
129
+            install(
130
+                FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
131
+                DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
132
+            )
133
+        endif()
134
+    endif()
135
+
136
+    ## Test targets
137
+    set(TEST_TARGETS)
138
+    if(PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
139
+        file(GLOB_RECURSE TESTS_COMMON CONFIGURE_DEPENDS
140
+            tests/common/*
141
+        )
142
+        file(GLOB TESTS CONFIGURE_DEPENDS
143
+            LIST_DIRECTORIES FALSE
144
+            tests/*
145
+        )
146
+        foreach(TEST ${TESTS})
147
+            get_filename_component(TEST_NAME "${TEST}" NAME_WE)
148
+            set(TEST_TARGET "${PROJECT_NAME}-test-${TEST_NAME}")
149
+            add_executable(${TEST_TARGET}
150
+                ${TEST}
151
+                ${TESTS_COMMON}
152
+            )
153
+            target_include_directories(${TEST_TARGET}
154
+                PRIVATE
155
+                    tests
156
+            )
157
+            target_link_libraries(${TEST_TARGET}
158
+                PRIVATE
159
+                    ${PROJECT_NAME}
160
+                    ${ARG_DEPENDENCIES_TESTS}
161
+            )
162
+            add_test(
163
+                NAME    ${TEST_TARGET}
164
+                COMMAND ${TEST_TARGET}
165
+            )
166
+            list(APPEND TEST_TARGETS ${TEST_TARGET})
167
+        endforeach()
168
+    endif()
169
+
170
+    ## Build targets
171
+    set(BUILD_TARGETS ${TEST_TARGETS})
172
+    if(NOT PROJECT_IS_INTERFACE_LIBRARY)
173
+        list(APPEND BUILD_TARGETS ${PROJECT_NAME})
174
+    endif()
175
+
176
+    ## Assets
177
+    file(REMOVE_RECURSE
178
+        ${CMAKE_BINARY_DIR}/assets
179
+    )
180
+    file(GLOB_RECURSE ASSETS CONFIGURE_DEPENDS
181
+        RELATIVE "${PROJECT_SOURCE_DIR}"
182
+        assets/*
183
+    )
184
+    if(NOT "${ASSETS}" STREQUAL "")
185
+        add_custom_target(${PROJECT_NAME}-assets)
186
+        add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-assets)
187
+    endif()
188
+    foreach(ASSET ${ASSETS})
189
+        get_filename_component(ASSET_DIR ${ASSET} DIRECTORY)
190
+        if("${ASSET}" MATCHES "/tests/")
191
+            set(ASSET_TEST TRUE)
192
+        else()
193
+            set(ASSET_TEST FALSE)
194
+        endif()
195
+        if(ASSET_TEST AND NOT PROJECT_IS_TOP_LEVEL)
196
+            continue()
197
+        endif()
198
+        add_custom_command(
199
+            DEPENDS
200
+                ${PROJECT_SOURCE_DIR}/${ASSET}
201
+            OUTPUT
202
+                ${CMAKE_BINARY_DIR}/${ASSET}
203
+            COMMAND
204
+                ${CMAKE_COMMAND} -E make_directory
205
+                    ${CMAKE_BINARY_DIR}/${ASSET_DIR}
206
+            COMMAND
207
+                ${CMAKE_COMMAND} -E create_symlink
208
+                    ${PROJECT_SOURCE_DIR}/${ASSET}
209
+                    ${CMAKE_BINARY_DIR}/${ASSET}
210
+            VERBATIM
211
+        )
212
+        set_property(TARGET ${PROJECT_NAME}-assets APPEND PROPERTY
213
+            SOURCES ${CMAKE_BINARY_DIR}/${ASSET}
214
+        )
215
+        if(NOT ASSET_TEST)
216
+            install(
217
+                FILES
218
+                    ${PROJECT_SOURCE_DIR}/${ASSET}
219
+                DESTINATION
220
+                    ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/${ASSET_DIR}
221
+            )
222
+        endif()
223
+    endforeach()
224
+
225
+    ## Documentation
226
+    if(PROJECT_IS_TOP_LEVEL)
227
+        file(GLOB_RECURSE DOCS CONFIGURE_DEPENDS
228
+            RELATIVE "${PROJECT_SOURCE_DIR}"
229
+            doc/*
230
+        )
231
+        file(GLOB DOCS_ROOT CONFIGURE_DEPENDS
232
+            RELATIVE "${PROJECT_SOURCE_DIR}"
233
+            README*
234
+            LICENSE*
235
+            COPYING*
236
+            CHANGELOG*
237
+            CHANGES*
238
+            HISTORY*
239
+            NEWS*
240
+            RELEASES*
241
+            AUTHORS*
242
+            ACKNOWLEDGMENTS*
243
+            CONTRIBUTORS*
244
+            CONTRIBUTING*
245
+            CODE_OF_CONDUCT*
246
+            SECURITY*
247
+            SUPPORT*
248
+        )
249
+        list(APPEND DOCS ${DOCS_ROOT})
250
+        foreach(DOC ${DOCS})
251
+            get_filename_component(DOC_DIR ${DOC} DIRECTORY)
252
+            install(
253
+                FILES
254
+                    ${PROJECT_SOURCE_DIR}/${DOC}
255
+                DESTINATION
256
+                    ${CMAKE_INSTALL_DOCDIR}/${DOC_DIR}
257
+            )
258
+        endforeach()
259
+    endif()
260
+
261
+    ## Man pages
262
+    if(PROJECT_IS_TOP_LEVEL)
263
+        file(GLOB_RECURSE MANS CONFIGURE_DEPENDS
264
+            RELATIVE "${PROJECT_SOURCE_DIR}"
265
+            man/*
266
+        )
267
+        foreach(MAN ${MANS})
268
+            get_filename_component(MAN_DIR ${MAN} DIRECTORY)
269
+            install(
270
+                FILES
271
+                    ${PROJECT_SOURCE_DIR}/${MAN}
272
+                DESTINATION
273
+                    ${CMAKE_INSTALL_MANDIR}/${MAN_DIR}
274
+            )
275
+        endforeach()
276
+    endif()
277
+
278
+    ## Language version
279
+    set_target_properties(${BUILD_TARGETS} PROPERTIES
280
+        CXX_STANDARD          "${ARG_CXX_STANDARD}"
281
+        CXX_STANDARD_REQUIRED ON
282
+        CXX_EXTENSIONS        OFF
283
+    )
284
+
285
+    ## Build options
286
+    if(PROJECT_IS_TOP_LEVEL)
287
+        if(MSVC)
288
+            set(CPLUSPLUS_OPTION)
289
+            if(MSVC_VERSION GREATER_EQUAL 1914)
290
+                set(CPLUSPLUS_OPTION /Zc:__cplusplus)
291
+            endif()
292
+            set(COMPILE_OPTIONS
293
+                ${CPLUSPLUS_OPTION}
294
+                /permissive-
295
+                /WX
296
+                /W4
297
+            )
298
+        elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|.*Clang")
299
+            set(SANITIZE_OPTIONS)
300
+            if(PROJECT_IS_DEBUG AND NOT ARG_DISABLE_SANITIZERS)
301
+                set(SANITIZE_OPTIONS
302
+                    $<$<CONFIG:Debug>:
303
+                        -fno-omit-frame-pointer
304
+                        -fsanitize=address,leak,undefined
305
+                        -fsanitize=float-divide-by-zero
306
+                        -fsanitize=float-cast-overflow
307
+                        # -fsanitize=pointer-compare
308
+                        # -fsanitize=pointer-subtract
309
+                        # -fsanitize=implicit-conversion
310
+                        -fno-sanitize-recover=all
311
+                    >
312
+                )
313
+            endif()
314
+            set(WSHADOW_OPTION)
315
+            if(NOT ARG_DISABLE_WSHADOW)
316
+                set(WSHADOW_OPTION -Wshadow)
317
+            endif()
318
+            set(COMPILE_OPTIONS
319
+                -pedantic
320
+                -Werror -Wfatal-errors
321
+                -Wall -Wextra
322
+                -Wno-missing-braces -Wmissing-field-initializers
323
+                -Wconversion -Wsign-conversion
324
+                -Wdouble-promotion
325
+                -Wimplicit-fallthrough
326
+                -Wvla
327
+                -Wzero-as-null-pointer-constant
328
+                -Weffc++
329
+                ${WSHADOW_OPTION}
330
+                ${SANITIZE_OPTIONS}
331
+            )
332
+            set(LINK_OPTIONS
333
+                ${SANITIZE_OPTIONS}
334
+            )
335
+            check_ipo_supported(RESULT INTERPROCEDURAL_OPTIMIZATION)
336
+        endif()
337
+        set_property(TARGET ${BUILD_TARGETS} APPEND PROPERTY
338
+            COMPILE_OPTIONS "${COMPILE_OPTIONS}"
339
+        )
340
+        set_property(TARGET ${BUILD_TARGETS} APPEND PROPERTY
341
+            LINK_OPTIONS "${LINK_OPTIONS}"
342
+        )
343
+        set_property(TARGET ${BUILD_TARGETS} APPEND PROPERTY
344
+            INTERPROCEDURAL_OPTIMIZATION "${INTERPROCEDURAL_OPTIMIZATION}"
345
+        )
346
+    endif()
347
+
348
+    ## Sanitizer environment variables
349
+    set(SAN_STRIP_PATH_PREFIX strip_path_prefix=${PROJECT_BINARY_DIR})
350
+    set(ASAN_OPTIONS  "${SAN_STRIP_PATH_PREFIX}")
351
+    set(LSAN_OPTIONS  "${SAN_STRIP_PATH_PREFIX}")
352
+    set(UBSAN_OPTIONS "${SAN_STRIP_PATH_PREFIX}")
353
+    file(GLOB ASAN_SUPP CONFIGURE_DEPENDS
354
+        .asan.supp
355
+    )
356
+    file(GLOB LSAN_SUPP CONFIGURE_DEPENDS
357
+        .lsan.supp
358
+    )
359
+    file(GLOB UBSAN_SUPP CONFIGURE_DEPENDS
360
+        .ubsan.supp
361
+    )
362
+    if(NOT "${ASAN_SUPP}" STREQUAL "")
363
+        set(ASAN_OPTIONS "${ASAN_OPTIONS},suppressions=${ASAN_SUPP}")
364
+    endif()
365
+    if(NOT "${LSAN_SUPP}" STREQUAL "")
366
+        set(LSAN_OPTIONS "${LSAN_OPTIONS},suppressions=${LSAN_SUPP}")
367
+    endif()
368
+    if(NOT "${UBSAN_SUPP}" STREQUAL "")
369
+        set(UBSAN_OPTIONS "${UBSAN_OPTIONS},suppressions=${UBSAN_SUPP}")
370
+    endif()
371
+    # set(ASAN_OPTIONS "${ASAN_OPTIONS},detect_leaks=1")
372
+    # set(UBSAN_OPTIONS "${UBSAN_OPTIONS},print_stacktrace=1")
373
+    set_property(TEST ${TEST_TARGETS} APPEND PROPERTY
374
+        ENVIRONMENT
375
+            ASAN_OPTIONS=${ASAN_OPTIONS}
376
+            LSAN_OPTIONS=${LSAN_OPTIONS}
377
+            UBSAN_OPTIONS=${UBSAN_OPTIONS}
378
+    )
379
+
380
+    ## Tools
381
+    if(PROJECT_IS_TOP_LEVEL AND PROJECT_IS_DEBUG)
382
+        find_program(CPPCHECK             cppcheck)
383
+        find_program(CLANG_TIDY           clang-tidy)
384
+        find_program(INCLUDE_WHAT_YOU_USE include-what-you-use)
385
+        if(CPPCHECK AND NOT ARG_DISABLE_CPPCHECK)
386
+            set(CXX_CPPCHECK ${CPPCHECK}
387
+                --error-exitcode=1
388
+                --enable=warning,style
389
+                --inline-suppr
390
+                --template "{file}:{line}: ({severity} {id}) {message}"
391
+            )
392
+        endif()
393
+        if(CLANG_TIDY AND NOT ARG_DISABLE_CLANG_TIDY)
394
+            set(CXX_CLANG_TIDY ${CLANG_TIDY}
395
+                --extra-arg=-Wno-unknown-warning-option
396
+                --extra-arg=-Wno-ignored-optimization-argument
397
+            )
398
+        endif()
399
+        if(INCLUDE_WHAT_YOU_USE AND NOT ARG_DISABLE_INCLUDE_WHAT_YOU_USE)
400
+            set(CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE}
401
+                -Wno-unknown-warning-option
402
+                -Wno-ignored-optimization-argument
403
+            )
404
+        endif()
405
+        set_target_properties(${BUILD_TARGETS} PROPERTIES
406
+            EXPORT_COMPILE_COMMANDS  ON
407
+            CXX_CPPCHECK             "${CXX_CPPCHECK}"
408
+            CXX_CLANG_TIDY           "${CXX_CLANG_TIDY}"
409
+            CXX_INCLUDE_WHAT_YOU_USE "${CXX_INCLUDE_WHAT_YOU_USE}"
410
+        )
411
+    endif()
412
+endfunction()