1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
# Find sanitizers
#
# This module sets the following targets:
# Sanitizer::address
# Sanitizer::thread
# Sanitizer::undefined
# Sanitizer::leak
# Sanitizer::memory
include_guard(GLOBAL)
option(UBSAN_FLAGS "additional UBSAN flags" OFF)
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
set(_source_code
[==[
#include <stdio.h>
int main() {
printf("hello world!");
return 0;
}
]==])
include(CMakePushCheckState)
cmake_push_check_state(RESET)
foreach(sanitizer_name IN ITEMS address thread undefined leak memory)
if(TARGET Sanitizer::${sanitizer_name})
continue()
endif()
set(CMAKE_REQUIRED_FLAGS
"-fsanitize=${sanitizer_name};-fno-omit-frame-pointer")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL
"MSVC")
if(sanitizer_name STREQUAL "address")
set(CMAKE_REQUIRED_FLAGS "/fsanitize=${sanitizer_name}")
else()
continue()
endif()
endif()
if(sanitizer_name STREQUAL "address")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL
"Clang")
list(APPEND CMAKE_REQUIRED_FLAGS "-shared-libasan")
endif()
endif()
if(sanitizer_name STREQUAL "undefined" AND UBSAN_FLAGS)
list(APPEND CMAKE_REQUIRED_FLAGS "${UBSAN_FLAGS}")
endif()
if(sanitizer_name STREQUAL "memory")
list(APPEND CMAKE_REQUIRED_FLAGS "-fsanitize-memory-track-origins=2")
endif()
set(CMAKE_REQUIRED_QUIET ON)
set(_run_res 0)
include(CheckCSourceRuns)
include(CheckCXXSourceRuns)
foreach(lang IN LISTS languages)
if(lang STREQUAL C)
check_c_source_runs("${_source_code}"
__${lang}_${sanitizer_name}_res)
if(__${lang}_${sanitizer_name}_res)
set(_run_res 1)
endif()
endif()
if(lang STREQUAL CXX)
check_cxx_source_runs("${_source_code}"
__${lang}_${sanitizer_name}_res)
if(__${lang}_${sanitizer_name}_res)
set(_run_res 1)
endif()
endif()
endforeach()
if(_run_res)
add_library(Sanitizer::${sanitizer_name} INTERFACE IMPORTED GLOBAL)
target_compile_options(
Sanitizer::${sanitizer_name}
INTERFACE
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>>:${CMAKE_REQUIRED_FLAGS}>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:$__C_${sanitizer_name}_res>>:${CMAKE_REQUIRED_FLAGS}>
)
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_C_COMPILER_ID
STREQUAL "MSVC")
target_link_options(
Sanitizer::${sanitizer_name}
INTERFACE
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>>:${CMAKE_REQUIRED_FLAGS}>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:$__C_${sanitizer_name}_res>>:${CMAKE_REQUIRED_FLAGS}>
)
else()
target_link_options(
Sanitizer::${sanitizer_name}
INTERFACE
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>>:/INCREMENTAL:NO>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:$__C_${sanitizer_name}_res>>:/INCREMENTAL:NO>
)
endif()
if(sanitizer_name STREQUAL "address")
target_compile_definitions(
Sanitizer::${sanitizer_name}
INTERFACE
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>>:_GLIBCXX_SANITIZE_VECTOR>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>>:_GLIBCXX_SANITIZE_STD_ALLOCATOR>
)
target_link_options(
Sanitizer::${sanitizer_name}
INTERFACE
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>,$<CXX_COMPILER_ID:GNU>>:-lasan>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:$__C_${sanitizer_name}_res>,$<C_COMPILER_ID:GNU>>:-lasan>
)
endif()
if(sanitizer_name STREQUAL "undefined")
target_link_options(
Sanitizer::${sanitizer_name}
INTERFACE
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<BOOL:$__CXX_${sanitizer_name}_res>,$<CXX_COMPILER_ID:GNU>>:-lubsan>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<BOOL:$__C_${sanitizer_name}_res>,$<C_COMPILER_ID:GNU>>:-lubsan>
)
endif()
endif()
endforeach()
cmake_pop_check_state()
|