Warning, /frameworks/extra-cmake-modules/modules/ECMEnableSanitizers.cmake is written in an unsupported language. File is not indexed.

0001 # SPDX-FileCopyrightText: 2014 Mathieu Tarral <mathieu.tarral@gmail.com>
0002 #
0003 # SPDX-License-Identifier: BSD-3-Clause
0004 
0005 #[=======================================================================[.rst:
0006 ECMEnableSanitizers
0007 -------------------
0008 
0009 Enable compiler sanitizer flags.
0010 
0011 The following sanitizers are supported:
0012 
0013 - Address Sanitizer
0014 - Memory Sanitizer
0015 - Thread Sanitizer
0016 - Leak Sanitizer
0017 - Undefined Behaviour Sanitizer
0018 
0019 All of them are implemented in Clang, depending on your version, and
0020 there is an work in progress in GCC, where some of them are currently
0021 implemented.
0022 
0023 This module will check your current compiler version to see if it
0024 supports the sanitizers that you want to enable
0025 
0026 Usage
0027 =====
0028 
0029 Simply add::
0030 
0031    include(ECMEnableSanitizers)
0032 
0033 to your ``CMakeLists.txt``. Note that this module is included in
0034 :kde-module:`KDECompilerSettings`, so projects using that module do not need to also
0035 include this one.
0036 
0037 The sanitizers are not enabled by default. Instead, you must set
0038 ``ECM_ENABLE_SANITIZERS`` (either in your ``CMakeLists.txt`` or on the
0039 command line) to a semicolon-separated list of sanitizers you wish to enable.
0040 The options are:
0041 
0042 - address
0043 - memory
0044 - thread
0045 - leak
0046 - undefined
0047 - fuzzer
0048 
0049 The sanitizers "address", "memory" and "thread" are mutually exclusive.  You
0050 cannot enable two of them in the same build.
0051 
0052 "leak" requires the  "address" sanitizer.
0053 
0054 .. note::
0055 
0056   To reduce the overhead induced by the instrumentation of the sanitizers, it
0057   is advised to enable compiler optimizations (``-O1`` or higher).
0058 
0059 Example
0060 =======
0061 
0062 This is an example of usage::
0063 
0064   mkdir build
0065   cd build
0066   cmake -DECM_ENABLE_SANITIZERS='address;leak;undefined' ..
0067 
0068 .. note::
0069 
0070   Most of the sanitizers will require Clang. To enable it, use::
0071 
0072     -DCMAKE_CXX_COMPILER=clang++
0073 
0074 Since 1.3.0.
0075 #]=======================================================================]
0076 
0077 # MACRO check_compiler_version
0078 #-----------------------------
0079 macro (check_compiler_version gcc_required_version clang_required_version msvc_required_version)
0080     if (
0081         (
0082             CMAKE_CXX_COMPILER_ID MATCHES "GNU"
0083             AND
0084             CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${gcc_required_version}
0085         )
0086         OR
0087         (
0088             CMAKE_CXX_COMPILER_ID MATCHES "Clang"
0089             AND
0090             CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${clang_required_version}
0091         )
0092         OR
0093         (
0094             CMAKE_CXX_COMPILER_ID MATCHES "MSVC"
0095             AND
0096             CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${msvc_required_version}
0097         )
0098     )
0099         # error !
0100         message(FATAL_ERROR "You ask to enable the sanitizer ${CUR_SANITIZER},
0101         but your compiler ${CMAKE_CXX_COMPILER_ID} version ${CMAKE_CXX_COMPILER_VERSION}
0102         does not support it !
0103         You should use at least GCC ${gcc_required_version}, Clang ${clang_required_version}
0104         or MSVC ${msvc_required_version}
0105         (99.99 means not implemented yet)")
0106     endif ()
0107 endmacro ()
0108 
0109 # MACRO check_compiler_support
0110 #------------------------------
0111 macro (enable_sanitizer_flags sanitize_option)
0112     if (${sanitize_option} MATCHES "address")
0113         check_compiler_version("4.8" "3.1" "19.28")
0114         if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
0115             set(XSAN_COMPILE_FLAGS "-fsanitize=address")
0116         else()
0117             set(XSAN_COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls")
0118             set(XSAN_LINKER_FLAGS "asan")
0119         endif()
0120     elseif (${sanitize_option} MATCHES "thread")
0121         check_compiler_version("4.8" "3.1" "99.99")
0122         set(XSAN_COMPILE_FLAGS "-fsanitize=thread")
0123         set(XSAN_LINKER_FLAGS "tsan")
0124     elseif (${sanitize_option} MATCHES "memory")
0125         check_compiler_version("99.99" "3.1" "99.99")
0126         set(XSAN_COMPILE_FLAGS "-fsanitize=memory")
0127     elseif (${sanitize_option} MATCHES "leak")
0128         check_compiler_version("4.9" "3.4" "99.99")
0129         set(XSAN_COMPILE_FLAGS "-fsanitize=leak")
0130         set(XSAN_LINKER_FLAGS "lsan")
0131     elseif (${sanitize_option} MATCHES "undefined")
0132         check_compiler_version("4.9" "3.1" "99.99")
0133         set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls")
0134     elseif (${sanitize_option} MATCHES "fuzzer")
0135         check_compiler_version("99.99" "6.0" "99.99")
0136         set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer")
0137     else ()
0138         message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.")
0139     endif ()
0140 endmacro ()
0141 
0142 if (ECM_ENABLE_SANITIZERS)
0143     if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
0144         # for each element of the ECM_ENABLE_SANITIZERS list
0145         foreach ( CUR_SANITIZER ${ECM_ENABLE_SANITIZERS} )
0146             # lowercase filter
0147             string(TOLOWER ${CUR_SANITIZER} CUR_SANITIZER)
0148             # check option and enable appropriate flags
0149             enable_sanitizer_flags ( ${CUR_SANITIZER} )
0150             # TODO: GCC will not link pthread library if enabled ASan
0151             if(CMAKE_C_COMPILER_ID MATCHES "Clang")
0152               set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XSAN_COMPILE_FLAGS}" )
0153             endif()
0154             set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" )
0155             if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
0156               link_libraries(${XSAN_LINKER_FLAGS})
0157             endif()
0158             if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
0159                 string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
0160                 string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
0161             endif ()
0162         endforeach()
0163     else()
0164         message(STATUS "Tried to enable sanitizers (-DECM_ENABLE_SANITIZERS=${ECM_ENABLE_SANITIZERS}), \
0165 but compiler (${CMAKE_CXX_COMPILER_ID}) does not have sanitizer support")
0166     endif()
0167 endif()