1313# License for the specific language governing permissions and limitations under
1414# the License.
1515
16+ include (CheckCXXSourceCompiles)
17+
1618set (USE_SANITIZER
1719 ""
1820 CACHE
@@ -28,48 +30,109 @@ function(append value)
2830 endforeach (variable )
2931endfunction ()
3032
33+ function (test_san_flags return_var flags )
34+ set (QUIET_BACKUP ${CMAKE_REQUIRED_QUIET} )
35+ set (CMAKE_REQUIRED_QUIET TRUE )
36+ unset (${return_var} CACHE )
37+ set (FLAGS_BACKUP ${CMAKE_REQUIRED_FLAGS} )
38+ set (CMAKE_REQUIRED_FLAGS "${flags} " )
39+ check_cxx_source_compiles("int main() { return 0; }" ${return_var} )
40+ set (CMAKE_REQUIRED_FLAGS "${FLAGS_BACKUP} " )
41+ set (CMAKE_REQUIRED_QUIET "${QUIET_BACKUP} " )
42+ endfunction ()
43+
3144if (USE_SANITIZER)
3245 append ("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
3346
47+ unset (SANITIZER_SELECTED_FLAGS)
48+
3449 if (UNIX )
3550
3651 if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" )
3752 append ("-O1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
3853 endif ()
3954
40- if (USE_SANITIZER MATCHES "([Aa]ddress);([Uu]ndefined)"
41- OR USE_SANITIZER MATCHES "([Uu]ndefined);([Aa]ddress)" )
42- message (STATUS "Building with Address, Undefined sanitizers" )
43- append ("-fsanitize=address,undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
44- elseif (USE_SANITIZER MATCHES "([Aa]ddress)" )
55+ if (USE_SANITIZER MATCHES "([Aa]ddress)" )
4556 # Optional: -fno-optimize-sibling-calls -fsanitize-address-use-after-scope
46- message (STATUS "Building with Address sanitizer" )
47- append ("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
48- elseif (USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)" )
57+ message (STATUS "Testing with Address sanitizer" )
58+ set (SANITIZER_ADDR_FLAG "-fsanitize=address" )
59+ test_san_flags(SANITIZER_ADDR_AVAILABLE ${SANITIZER_ADDR_FLAG} )
60+ if (SANITIZER_ADDR_AVAILABLE)
61+ message (STATUS " Building with Address sanitizer" )
62+ append ("${SANITIZER_ADDR_FLAG} " SANITIZER_SELECTED_FLAGS)
63+ else ()
64+ message (FATAL_ERROR "Address sanitizer not available for ${CMAKE_CXX_COMPILER} " )
65+ endif ()
66+ endif ()
67+
68+ if (USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)" )
4969 # Optional: -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2
50- append ( "-fsanitize=memory" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
70+ set (SANITIZER_MEM_FLAG "-fsanitize=memory" )
5171 if (USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)" )
52- message (STATUS "Building with MemoryWithOrigins sanitizer" )
53- append ("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
72+ message (STATUS "Testing with MemoryWithOrigins sanitizer" )
73+ append ("-fsanitize-memory-track-origins" SANITIZER_MEM_FLAG )
5474 else ()
55- message (STATUS "Building with Memory sanitizer" )
75+ message (STATUS "Testing with Memory sanitizer" )
5676 endif ()
57- elseif (USE_SANITIZER MATCHES "([Uu]ndefined)" )
58- message (STATUS "Building with Undefined sanitizer" )
59- append ("-fsanitize=undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
77+ test_san_flags(SANITIZER_MEM_AVAILABLE ${SANITIZER_MEM_FLAG} )
78+ if (SANITIZER_MEM_AVAILABLE)
79+ if (USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)" )
80+ message (STATUS " Building with MemoryWithOrigins sanitizer" )
81+ else ()
82+ message (STATUS " Building with Memory sanitizer" )
83+ endif ()
84+ append ("${SANITIZER_MEM_FLAG} " SANITIZER_SELECTED_FLAGS)
85+ else ()
86+ message (FATAL_ERROR "Memory [With Origins] sanitizer not available for ${CMAKE_CXX_COMPILER} " )
87+ endif ()
88+ endif ()
89+
90+ if (USE_SANITIZER MATCHES "([Uu]ndefined)" )
91+ message (STATUS "Testing with Undefined Behaviour sanitizer" )
92+ set (SANITIZER_UB_FLAG "-fsanitize=undefined" )
6093 if (EXISTS "${BLACKLIST_FILE} " )
61- append ("-fsanitize-blacklist=${BLACKLIST_FILE} " CMAKE_C_FLAGS
62- CMAKE_CXX_FLAGS )
94+ append ("-fsanitize-blacklist=${BLACKLIST_FILE} " SANITIZER_UB_FLAG)
95+ endif ()
96+ test_san_flags(SANITIZER_UB_AVAILABLE ${SANITIZER_UB_FLAG} )
97+ if (SANITIZER_UB_AVAILABLE)
98+ message (STATUS " Building with Undefined Behaviour sanitizer" )
99+ append ("${SANITIZER_UB_FLAG} " SANITIZER_SELECTED_FLAGS)
100+ else ()
101+ message (FATAL_ERROR "Undefined Behaviour sanitizer not available for ${CMAKE_CXX_COMPILER} " )
102+ endif ()
103+ endif ()
104+
105+ if (USE_SANITIZER MATCHES "([Tt]hread)" )
106+ message (STATUS "Testing with Thread sanitizer" )
107+ set (SANITIZER_THREAD_FLAG "-fsanitize=thread" )
108+ test_san_flags(SANITIZER_THREAD_AVAILABLE ${SANITIZER_THREAD_FLAG} )
109+ if (SANITIZER_THREAD_AVAILABLE)
110+ message (STATUS " Building with Thread sanitizer" )
111+ append ("${SANITIZER_THREAD_FLAG} " SANITIZER_SELECTED_FLAGS)
112+ else ()
113+ message (FATAL_ERROR "Thread sanitizer not available for ${CMAKE_CXX_COMPILER} " )
63114 endif ()
64- elseif (USE_SANITIZER MATCHES "([Tt]hread)" )
65- message (STATUS "Building with Thread sanitizer" )
66- append ("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
67- elseif (USE_SANITIZER MATCHES "([Ll]eak)" )
68- message (STATUS "Building with Leak sanitizer" )
69- append ("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
115+ endif ()
116+
117+ if (USE_SANITIZER MATCHES "([Ll]eak)" )
118+ message (STATUS "Testing with Leak sanitizer" )
119+ set (SANITIZER_LEAK_FLAG "-fsanitize=leak" )
120+ test_san_flags(SANITIZER_LEAK_AVAILABLE ${SANITIZER_LEAK_FLAG} )
121+ if (SANITIZER_LEAK_AVAILABLE)
122+ message (STATUS " Building with Leak sanitizer" )
123+ append ("${SANITIZER_LEAK_FLAG} " SANITIZER_SELECTED_FLAGS)
124+ else ()
125+ message (FATAL_ERROR "Thread sanitizer not available for ${CMAKE_CXX_COMPILER} " )
126+ endif ()
127+ endif ()
128+
129+ message (STATUS "Sanitizer flags: ${SANITIZER_SELECTED_FLAGS} " )
130+ test_san_flags(SANITIZER_SELECTED_COMPATIBLE ${SANITIZER_SELECTED_FLAGS} )
131+ if (SANITIZER_SELECTED_COMPATIBLE)
132+ message (STATUS " Building with ${SANITIZER_SELECTED_FLAGS} " )
133+ append ("${SANITIZER_SELECTED_FLAGS} " CMAKE_C_FLAGS CMAKE_CXX_FLAGS )
70134 else ()
71- message (
72- FATAL_ERROR "Unsupported value of USE_SANITIZER: ${USE_SANITIZER} " )
135+ message (FATAL_ERROR " Sanitizer flags ${SANITIZER_SELECTED_FLAGS} are not compatible." )
73136 endif ()
74137 elseif (MSVC )
75138 if (USE_SANITIZER MATCHES "([Aa]ddress)" )
0 commit comments