[cosmetic] separate c-lang format commit
[xbmc.git] / cmake / modules / extra / ECMEnableSanitizers.cmake
blobaa7092df181d20193032fccc693529c59ea5fc35
1 #.rst:
2 # ECMEnableSanitizers
3 # -------------------
5 # Enable compiler sanitizer flags.
7 # The following sanitizers are supported:
9 # - Address Sanitizer
10 # - Memory Sanitizer
11 # - Thread Sanitizer
12 # - Leak Sanitizer
13 # - Undefined Behaviour Sanitizer
15 # All of them are implemented in Clang, depending on your version, and
16 # there is an work in progress in GCC, where some of them are currently
17 # implemented.
19 # This module will check your current compiler version to see if it
20 # supports the sanitizers that you want to enable
22 # Usage
23 # =====
25 # Simply add::
27 #    include(ECMEnableSanitizers)
29 # to your ``CMakeLists.txt``. Note that this module is included in
30 # KDECompilerSettings, so projects using that module do not need to also
31 # include this one.
33 # The sanitizers are not enabled by default. Instead, you must set
34 # ``ECM_ENABLE_SANITIZERS`` (either in your ``CMakeLists.txt`` or on the
35 # command line) to a semicolon-separated list of sanitizers you wish to enable.
36 # The options are:
38 # - address
39 # - memory
40 # - thread
41 # - leak
42 # - undefined
44 # The sanitizers "address", "memory" and "thread" are mutually exclusive.  You
45 # cannot enable two of them in the same build.
47 # "leak" requires the  "address" sanitizer.
49 # .. note::
51 #   To reduce the overhead induced by the instrumentation of the sanitizers, it
52 #   is advised to enable compiler optimizations (``-O1`` or higher).
54 # Example
55 # =======
57 # This is an example of usage::
59 #   mkdir build
60 #   cd build
61 #   cmake -DECM_ENABLE_SANITIZERS='address;leak;undefined' ..
63 # .. note::
65 #   Most of the sanitizers will require Clang. To enable it, use::
67 #     -DCMAKE_CXX_COMPILER=clang++
69 # Since 1.3.0.
71 #=============================================================================
72 # Copyright 2014 Mathieu Tarral <mathieu.tarral@gmail.com>
74 # Distributed under the OSI-approved BSD License (the "License");
75 # see accompanying file COPYING-CMAKE-SCRIPTS for details.
77 # This software is distributed WITHOUT ANY WARRANTY; without even the
78 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
79 # See the License for more information.
80 #=============================================================================
81 # (To distribute this file outside of extra-cmake-modules, substitute the full
82 #  License text for the above reference.)
84 # MACRO check_compiler_version
85 #-----------------------------
86 macro (check_compiler_version gcc_required_version clang_required_version)
87     if (
88         (
89             CMAKE_CXX_COMPILER_ID MATCHES "GNU"
90             AND
91             CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${gcc_required_version}
92         )
93         OR
94         (
95             CMAKE_CXX_COMPILER_ID MATCHES "Clang"
96             AND
97             CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${clang_required_version}
98         )
99     )
100         # error !
101         message(FATAL_ERROR "You ask to enable the sanitizer ${CUR_SANITIZER},
102         but your compiler ${CMAKE_CXX_COMPILER_ID} version ${CMAKE_CXX_COMPILER_VERSION}
103         does not support it !
104         You should use at least GCC ${gcc_required_version} or Clang ${clang_required_version}
105         (99.99 means not implemented yet)")
106     endif ()
107 endmacro ()
109 # MACRO check_compiler_support
110 #------------------------------
111 macro (enable_sanitizer_flags sanitize_option)
112     if (${sanitize_option} MATCHES "address")
113         check_compiler_version("4.8" "3.1")
114         set(XSAN_COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls")
115         set(XSAN_LINKER_FLAGS "asan")
116     elseif (${sanitize_option} MATCHES "thread")
117         check_compiler_version("4.8" "3.1")
118         set(XSAN_COMPILE_FLAGS "-fsanitize=thread")
119         set(XSAN_LINKER_FLAGS "tsan")
120     elseif (${sanitize_option} MATCHES "memory")
121         check_compiler_version("99.99" "3.1")
122         set(XSAN_COMPILE_FLAGS "-fsanitize=memory")
123     elseif (${sanitize_option} MATCHES "leak")
124         check_compiler_version("4.9" "3.4")
125         set(XSAN_COMPILE_FLAGS "-fsanitize=leak")
126         set(XSAN_LINKER_FLAGS "lsan")
127     elseif (${sanitize_option} MATCHES "undefined")
128         check_compiler_version("4.9" "3.1")
129         set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls")
130     else ()
131         message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.")
132     endif ()
133 endmacro ()
135 # for each element of the ECM_ENABLE_SANITIZERS list
136 foreach ( CUR_SANITIZER ${ECM_ENABLE_SANITIZERS} )
137     # lowercase filter
138     string(TOLOWER ${CUR_SANITIZER} CUR_SANITIZER)
139     # check option and enable appropriate flags
140     enable_sanitizer_flags ( ${CUR_SANITIZER} )
141     set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" )
142     if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
143       link_libraries(${XSAN_LINKER_FLAGS})
144     endif()
145     if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
146         string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
147         string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
148     endif ()
149 endforeach ()