diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake new file mode 100644 index 0000000..64915ba --- /dev/null +++ b/cmake/CompilerWarnings.cmake @@ -0,0 +1,78 @@ +# from here: +# +# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md + +function(set_project_warnings) + option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" TRUE) + + set(MSVC_WARNINGS + /W4 # Baseline reasonable warnings + /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not + # be destructed correctly + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside + # the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /permissive- # standards conformance mode for MSVC compiler. + ) + + set(CLANG_WARNINGS + -Wall + -Wextra # reasonable and standard + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps + # catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + ) + + if (WARNINGS_AS_ERRORS) + set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) + set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) + endif () + + set(GCC_WARNINGS + ${CLANG_WARNINGS} + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + -Wduplicated-cond # warn if if / else chain has duplicated conditions + -Wduplicated-branches # warn if if / else branches have duplicated code + -Wlogical-op # warn about logical operations being used where bitwise were probably wanted + -Wuseless-cast # warn if you perform a cast to the same type + ) + + if (WIN32) + set(PROJECT_WARNINGS ${MSVC_WARNINGS}) + elseif (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + set(PROJECT_WARNINGS ${CLANG_WARNINGS}) + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(PROJECT_WARNINGS ${GCC_WARNINGS}) + else () + message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") + endif () + + add_compile_options(${PROJECT_WARNINGS}) + +endfunction() diff --git a/cmake/Sanitizers.cmake b/cmake/Sanitizers.cmake new file mode 100644 index 0000000..1f6beb0 --- /dev/null +++ b/cmake/Sanitizers.cmake @@ -0,0 +1,71 @@ +function(enable_sanitizers) + + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) + + if (ENABLE_COVERAGE) + add_compile_options("$<$:--coverage -O0 -g>") + add_link_options("$<$:--coverage>") + endif () + + set(SANITIZERS "") + + option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" FALSE) + if (ENABLE_SANITIZER_ADDRESS) + message(STATUS "${CMAKE_PROJECT_NAME}: Enabling address sanitizer") + list(APPEND SANITIZERS "address") + endif () + + option(ENABLE_SANITIZER_LEAK "Enable leak sanitizer" FALSE) + if (ENABLE_SANITIZER_LEAK) + list(APPEND SANITIZERS "leak") + endif () + + option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" FALSE) + if (ENABLE_SANITIZER_UNDEFINED_BEHAVIOR) + message(STATUS "${CMAKE_PROJECT_NAME}: Enabling undefined behavior sanitizer") + list(APPEND SANITIZERS "undefined") + endif () + + option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE) + if (ENABLE_SANITIZER_THREAD) + if ("address" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS) + message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled") + else () + list(APPEND SANITIZERS "thread") + endif () + endif () + + option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" FALSE) + if (ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + if ("address" IN_LIST SANITIZERS + OR "thread" IN_LIST SANITIZERS + OR "leak" IN_LIST SANITIZERS) + message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled") + else () + list(APPEND SANITIZERS "memory") + endif () + endif () + + list( + JOIN + SANITIZERS + "," + LIST_OF_SANITIZERS) + + endif () + + if (LIST_OF_SANITIZERS) + if (NOT + "${LIST_OF_SANITIZERS}" + STREQUAL + "") + add_compile_options("$<$:-fsanitize=${LIST_OF_SANITIZERS}>") + add_link_options("$<$:-fsanitize=${LIST_OF_SANITIZERS}>") + if(WIN32) + set_property(GLOBAL PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() + endif () + endif () + +endfunction() diff --git a/cmake/toolchain.cmake b/cmake/toolchain.cmake index c16fcee..3e2cbe9 100644 --- a/cmake/toolchain.cmake +++ b/cmake/toolchain.cmake @@ -1,23 +1,6 @@ -#compile with warnings -if(WIN32) - add_compile_options(/W4 /WX) - set_property(GLOBAL PROPERTY - MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -else() - add_compile_options(-Wall -Wextra -pedantic -Werror) -endif() +include(${CMAKE_CURRENT_LIST_DIR}/CompilerWarnings.cmake) +set_project_warnings() -#enable asan in debug -if(WIN32) - add_compile_options("$<$:-fsanitize=address>") -else() - add_compile_options("$<$:-fsanitize=address>") - add_link_options("$<$:-fsanitize=address>") -endif() - -#enable ubsan in debug -if(NOT WIN32) - add_compile_options("$<$:-fsanitize=undefined>" - "$<$:-fno-omit-frame-pointer>") - add_link_options("$<$:-fsanitize=undefined>") -endif() +include(${CMAKE_CURRENT_LIST_DIR}/Sanitizers.cmake) +set(ENABLE_SANITIZER_ADDRESS YES) +enable_sanitizers() \ No newline at end of file