| 1 | 1 | new file mode 100644 | 
| ... | ... | @@ -0,0 +1,57 @@ | 
| 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 | + | |
| 35 | + # -Weffc++, | |
| 36 | + -*-redundant-member-init, | |
| 37 | + | |
| 38 | + # Interaction with C, | |
| 39 | + -*-cast*, | |
| 40 | + -*-vararg, | |
| 41 | + -*array-*decay, | |
| 42 | + | |
| 43 | + # Backwards compatibility, | |
| 44 | + -*-union-access, | |
| 45 | + | |
| 46 | + # Static storage duration throwing constructors, | |
| 47 | + -cert-err58-cpp, | |
| 48 | + | |
| 49 | + # Complex functions, | |
| 50 | + -*readability-function-cognitive-complexity, | |
| 51 | + | |
| 52 | + # Macro magic, | |
| 53 | + -*bugprone-macro-parentheses, | |
| 54 | + -*bugprone-lambda-function-name, | |
| 55 | + | |
| 56 | + # Exceptions, | |
| 57 | + -*bugprone-exception-escape, | 
| ... | ... | @@ -8,6 +8,95 @@ A [C++11][]/[OpenGL][] \>=[1.0][] [testing][] library. | 
| 8 | 8 | [1.0]: https://en.wikipedia.org/wiki/OpenGL#Version_history | 
| 9 | 9 | [testing]: https://en.wikipedia.org/wiki/Software_testing | 
| 10 | 10 |  | 
| 11 | +## Build system | |
| 12 | + | |
| 13 | +This project supports [CMake][] and uses [`cmake-common`][]. There are several | |
| 14 | +ways to use it in other CMake-based projects: | |
| 15 | + | |
| 16 | +- With [`find_package`][]: ([Package][] and) [install][] it on the system. | |
| 17 | + | |
| 18 | +- With [`add_subdirectory`][]: Bundle it. | |
| 19 | + | |
| 20 | +- With [`FetchContent`][]: Download it as part of the CMake configure step. | |
| 21 | + | |
| 22 | +- With [`cmake-common`][]: Use any of the above methods through a simplified | |
| 23 | + interface. | |
| 24 | + | |
| 25 | +As usual, use [`add_dependencies`][] or [`target_link_libraries`][] (or | |
| 26 | +`cmake-common`'s `DEPENDENCIES_*`) to declare the dependency. | |
| 27 | + | |
| 28 | +[CMake]: https://cmake.org | |
| 29 | +[`cmake-common`]: https://git.rcrnstn.net/rcrnstn/cmake-common | |
| 30 | +[`FetchContent`]: https://cmake.org/cmake/help/v3.14/module/FetchContent.html | |
| 31 | +[`add_subdirectory`]: https://cmake.org/cmake/help/v3.14/command/add_subdirectory.html | |
| 32 | +[`find_package`]: https://cmake.org/cmake/help/v3.14/command/find_package.html | |
| 33 | +[Package]: #Package | |
| 34 | +[Install]: #Install | |
| 35 | +[`add_dependencies`]: https://cmake.org/cmake/help/v3.14/command/add_dependencies.html | |
| 36 | +[`target_link_libraries`]: https://cmake.org/cmake/help/v3.14/command/target_link_libraries.html | |
| 37 | + | |
| 38 | +### Configure and generate | |
| 39 | + | |
| 40 | +To configure and generate a build tree, use `cmake`: | |
| 41 | + | |
| 42 | +```sh | |
| 43 | +cmake -B _build | |
| 44 | +``` | |
| 45 | + | |
| 46 | +To set the build type, pass e.g. `-D`[`CMAKE_BUILD_TYPE`][]`=Release`. | |
| 47 | + | |
| 48 | +[`cmake`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#generate-a-project-buildsystem | |
| 49 | +[`CMAKE_BUILD_TYPE`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_BUILD_TYPE.html | |
| 50 | + | |
| 51 | +### Build | |
| 52 | + | |
| 53 | +To build, use [`cmake --build`][]: | |
| 54 | + | |
| 55 | +```sh | |
| 56 | +cmake --build _build | |
| 57 | +``` | |
| 58 | + | |
| 59 | +To disable building tests, pass `-D`[`BUILD_TESTING`][]`=OFF`. | |
| 60 | + | |
| 61 | +[`cmake --build`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#build-a-project | |
| 62 | +[`BUILD_TESTING`]: https://cmake.org/cmake/help/v3.14/module/CTest.html | |
| 63 | + | |
| 64 | +### Test | |
| 65 | + | |
| 66 | +To run tests, use [`ctest`][]: | |
| 67 | + | |
| 68 | +```sh | |
| 69 | +(cd _build && ctest) | |
| 70 | +``` | |
| 71 | + | |
| 72 | +To show output from failing tests, pass `--output-on-failure`. To show output | |
| 73 | +from all tests, pass `--verbose`. | |
| 74 | + | |
| 75 | +[`ctest`]: https://cmake.org/cmake/help/v3.14/manual/ctest.1.html | |
| 76 | + | |
| 77 | +### Package | |
| 78 | + | |
| 79 | +To package, use [`cpack`][]: | |
| 80 | + | |
| 81 | +```sh | |
| 82 | +(cd _build && cpack) | |
| 83 | +``` | |
| 84 | + | |
| 85 | +[`cpack`]: https://cmake.org/cmake/help/v3.14/manual/cpack.1.html | |
| 86 | + | |
| 87 | +### Install | |
| 88 | + | |
| 89 | +To install onto the current system, use [`cmake --install`][]: | |
| 90 | + | |
| 91 | +```sh | |
| 92 | +cmake --install _build | |
| 93 | +``` | |
| 94 | + | |
| 95 | +To set the prefix, pass e.g. `-D`[`CMAKE_INSTALL_PREFIX`][]`="$HOME/.local"`. | |
| 96 | + | |
| 97 | +[`cmake --install`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#install-a-project | |
| 98 | +[`CMAKE_INSTALL_PREFIX`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_INSTALL_PREFIX.html | |
| 99 | + | |
| 11 | 100 | ## License | 
| 12 | 101 |  | 
| 13 | 102 | Licensed under the [ISC License][] unless otherwise noted, see the | 
| 14 | 103 | new file mode 100644 | 
| ... | ... | @@ -0,0 +1,407 @@ | 
| 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} REQUIRED) | |
| 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(COMPILE_OPTIONS | |
| 289 | + /permissive- | |
| 290 | + /WX | |
| 291 | + /W4 | |
| 292 | + ) | |
| 293 | +        elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|.*Clang") | |
| 294 | + set(SANITIZE_OPTIONS) | |
| 295 | + if(PROJECT_IS_DEBUG AND NOT ARG_DISABLE_SANITIZERS) | |
| 296 | + set(SANITIZE_OPTIONS | |
| 297 | + $<$<CONFIG:Debug>: | |
| 298 | + -g -fno-omit-frame-pointer | |
| 299 | + -fsanitize=address,leak,undefined | |
| 300 | + -fsanitize=float-divide-by-zero | |
| 301 | + -fsanitize=float-cast-overflow | |
| 302 | + # -fsanitize=pointer-compare | |
| 303 | + # -fsanitize=pointer-subtract | |
| 304 | + # -fsanitize=implicit-conversion | |
| 305 | + -fno-sanitize-recover=all | |
| 306 | + > | |
| 307 | + ) | |
| 308 | + endif() | |
| 309 | + set(WSHADOW_OPTION) | |
| 310 | + if(NOT ARG_DISABLE_WSHADOW) | |
| 311 | + set(WSHADOW_OPTION -Wshadow=local) | |
| 312 | + endif() | |
| 313 | + set(COMPILE_OPTIONS | |
| 314 | + -pedantic | |
| 315 | + -Werror # -Wfatal-errors | |
| 316 | + -Wall -Wextra | |
| 317 | + -Wno-missing-braces -Wmissing-field-initializers | |
| 318 | + -Wconversion -Wsign-conversion | |
| 319 | + -Wdouble-promotion | |
| 320 | + -Wimplicit-fallthrough | |
| 321 | + -Wvla | |
| 322 | + -Wzero-as-null-pointer-constant | |
| 323 | + -Weffc++ | |
| 324 | +                ${WSHADOW_OPTION} | |
| 325 | +                ${SANITIZE_OPTIONS} | |
| 326 | + ) | |
| 327 | + set(LINK_OPTIONS | |
| 328 | +                ${SANITIZE_OPTIONS} | |
| 329 | + ) | |
| 330 | + check_ipo_supported(RESULT INTERPROCEDURAL_OPTIMIZATION) | |
| 331 | + endif() | |
| 332 | +        set_property(TARGET ${BUILD_TARGETS} APPEND PROPERTY | |
| 333 | +            COMPILE_OPTIONS "${COMPILE_OPTIONS}" | |
| 334 | + ) | |
| 335 | +        set_property(TARGET ${BUILD_TARGETS} APPEND PROPERTY | |
| 336 | +            LINK_OPTIONS "${LINK_OPTIONS}" | |
| 337 | + ) | |
| 338 | +        set_property(TARGET ${BUILD_TARGETS} APPEND PROPERTY | |
| 339 | +            INTERPROCEDURAL_OPTIMIZATION "${INTERPROCEDURAL_OPTIMIZATION}" | |
| 340 | + ) | |
| 341 | + endif() | |
| 342 | + | |
| 343 | + ## Sanitizer environment variables | |
| 344 | +    set(SAN_STRIP_PATH_PREFIX strip_path_prefix=${PROJECT_BINARY_DIR}) | |
| 345 | +    set(ASAN_OPTIONS  "${SAN_STRIP_PATH_PREFIX}") | |
| 346 | +    set(LSAN_OPTIONS  "${SAN_STRIP_PATH_PREFIX}") | |
| 347 | +    set(UBSAN_OPTIONS "${SAN_STRIP_PATH_PREFIX}") | |
| 348 | + file(GLOB ASAN_SUPP CONFIGURE_DEPENDS | |
| 349 | + .asan.supp | |
| 350 | + ) | |
| 351 | + file(GLOB LSAN_SUPP CONFIGURE_DEPENDS | |
| 352 | + .lsan.supp | |
| 353 | + ) | |
| 354 | + file(GLOB UBSAN_SUPP CONFIGURE_DEPENDS | |
| 355 | + .ubsan.supp | |
| 356 | + ) | |
| 357 | +    if(NOT "${ASAN_SUPP}" STREQUAL "") | |
| 358 | +        set(ASAN_OPTIONS "${ASAN_OPTIONS},suppressions=${ASAN_SUPP}") | |
| 359 | + endif() | |
| 360 | +    if(NOT "${LSAN_SUPP}" STREQUAL "") | |
| 361 | +        set(LSAN_OPTIONS "${LSAN_OPTIONS},suppressions=${LSAN_SUPP}") | |
| 362 | + endif() | |
| 363 | +    if(NOT "${UBSAN_SUPP}" STREQUAL "") | |
| 364 | +        set(UBSAN_OPTIONS "${UBSAN_OPTIONS},suppressions=${UBSAN_SUPP}") | |
| 365 | + endif() | |
| 366 | +    # set(ASAN_OPTIONS "${ASAN_OPTIONS},detect_leaks=1") | |
| 367 | +    # set(UBSAN_OPTIONS "${UBSAN_OPTIONS},print_stacktrace=1") | |
| 368 | +    set_property(TEST ${TEST_TARGETS} APPEND PROPERTY | |
| 369 | + ENVIRONMENT | |
| 370 | +            ASAN_OPTIONS=${ASAN_OPTIONS} | |
| 371 | +            LSAN_OPTIONS=${LSAN_OPTIONS} | |
| 372 | +            UBSAN_OPTIONS=${UBSAN_OPTIONS} | |
| 373 | + ) | |
| 374 | + | |
| 375 | + ## Tools | |
| 376 | + if(PROJECT_IS_TOP_LEVEL AND PROJECT_IS_DEBUG) | |
| 377 | + find_program(CPPCHECK cppcheck) | |
| 378 | + find_program(CLANG_TIDY clang-tidy) | |
| 379 | + find_program(INCLUDE_WHAT_YOU_USE include-what-you-use) | |
| 380 | + if(CPPCHECK AND NOT ARG_DISABLE_CPPCHECK) | |
| 381 | +            set(CXX_CPPCHECK ${CPPCHECK} | |
| 382 | + --error-exitcode=1 | |
| 383 | + --enable=warning,style | |
| 384 | + --inline-suppr | |
| 385 | +                --template "{file}:{line}: ({severity} {id}) {message}" | |
| 386 | + ) | |
| 387 | + endif() | |
| 388 | + if(CLANG_TIDY AND NOT ARG_DISABLE_CLANG_TIDY) | |
| 389 | +            set(CXX_CLANG_TIDY ${CLANG_TIDY} | |
| 390 | + --extra-arg=-Wno-unknown-warning-option | |
| 391 | + --extra-arg=-Wno-ignored-optimization-argument | |
| 392 | + ) | |
| 393 | + endif() | |
| 394 | + if(INCLUDE_WHAT_YOU_USE AND NOT ARG_DISABLE_INCLUDE_WHAT_YOU_USE) | |
| 395 | +            set(CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE} | |
| 396 | + -Wno-unknown-warning-option | |
| 397 | + -Wno-ignored-optimization-argument | |
| 398 | + ) | |
| 399 | + endif() | |
| 400 | +        set_target_properties(${BUILD_TARGETS} PROPERTIES | |
| 401 | + EXPORT_COMPILE_COMMANDS ON | |
| 402 | +            CXX_CPPCHECK             "${CXX_CPPCHECK}" | |
| 403 | +            CXX_CLANG_TIDY           "${CXX_CLANG_TIDY}" | |
| 404 | +            CXX_INCLUDE_WHAT_YOU_USE "${CXX_INCLUDE_WHAT_YOU_USE}" | |
| 405 | + ) | |
| 406 | + endif() | |
| 407 | +endfunction() |