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()