get_cmake_property(ENABLED_LANGUAGES ENABLED_LANGUAGES)
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
function(list_append var)
foreach(arg ${ARGN})
list(FIND ${var} ${arg} found)
if(${found} EQUAL -1)
list(APPEND ${var} ${arg})
endif()
endforeach()
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
macro(sanitize_flag_cx)
foreach(arg ${ARGN})
string(REPLACE "+" "x" var ${arg})
string(REGEX REPLACE "[^A-Za-z0-9_-]+" "-" var ${var})
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${SANITIZE_CX} ${arg}")
list(FIND ENABLED_LANGUAGES C found)
if(${found} GREATER -1)
check_c_compiler_flag(${arg} cx${var})
if(cx${var})
list_append(SANITIZE_CX ${arg})
endif()
endif()
list(FIND ENABLED_LANGUAGES CXX found)
if(${found} GREATER -1)
check_cxx_compiler_flag(${arg} cx${var})
if(cx${var})
list_append(SANITIZE_CX ${arg})
endif()
endif()
set(CMAKE_REQUIRED_FLAGS)
endforeach()
endmacro()
macro(sanitize_flag_ld)
foreach(arg ${ARGN})
string(REPLACE "+" "x" var ${arg})
string(REGEX REPLACE "[^A-Za-z0-9_-]+" "-" var ${var})
string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${SANITIZE_CX} ${SANITIZE_LD} ${arg}")
list(FIND ENABLED_LANGUAGES C found)
if(${found} GREATER -1)
check_c_compiler_flag(${arg} ld${var})
if(ld${var})
list_append(SANITIZE_LD ${arg})
endif()
endif()
list(FIND ENABLED_LANGUAGES CXX found)
if(${found} GREATER -1)
check_cxx_compiler_flag(${arg} ld${var})
if(ld${var})
list_append(SANITIZE_LD ${arg})
endif()
endif()
set(CMAKE_REQUIRED_FLAGS)
endforeach()
endmacro()
if(
CMAKE_C_COMPILER_ID MATCHES "GNU|[Cc]lang|LLVM" OR
CMAKE_CXX_COMPILER_ID MATCHES "GNU|[Cc]lang|LLVM"
)
sanitize_flag_cx(-fsanitize=address)
sanitize_flag_cx(-fsanitize=leak)
sanitize_flag_cx(-fsanitize=undefined)
sanitize_flag_cx(-fsanitize-recover=all)
sanitize_flag_cx(-fno-omit-frame-pointer)
if(
CMAKE_C_COMPILER_ID MATCHES "GNU" OR
CMAKE_CXX_COMPILER_ID MATCHES "GNU"
)
sanitize_flag_ld(-static-libasan)
sanitize_flag_ld(-static-liblsan)
sanitize_flag_ld(-static-libubsan)
else()
sanitize_flag_ld(-static-libsan)
endif()
elseif(
CMAKE_C_COMPILER_ID MATCHES "MSVC" OR
CMAKE_CXX_COMPILER_ID MATCHES "MSVC"
)
list_append(SANITIZE_LD /INCREMENTAL:NO)
sanitize_flag_cx(/fsanitize=address)
endif()
function(target_compile_sanitize)
set(scope PRIVATE)
foreach(target ${ARGN})
if(target MATCHES "^INTERFACE|PUBLIC|PRIVATE")
set(scope ${target})
else()
target_compile_options(${target} ${scope} ${SANITIZE_CX})
endif()
endforeach()
endfunction()
function(target_link_sanitize_3_13)
function(string_append var)
foreach(arg ${ARGN})
string(FIND "${${var}}" "${arg}" found)
if(${found} EQUAL -1)
string(STRIP "${${var}} ${arg}" ${var})
endif()
endforeach()
set(${var} "${${var}}" PARENT_SCOPE)
endfunction()
foreach(target ${ARGN})
if(TARGET ${target})
get_property(LINK_FLAGS TARGET ${target} PROPERTY LINK_FLAGS)
if(MSVC)
string_append(LINK_FLAGS ${SANITIZE_LD})
else()
string_append(LINK_FLAGS ${SANITIZE_CX} ${SANITIZE_LD})
endif()
set_property(TARGET ${target} PROPERTY LINK_FLAGS "${LINK_FLAGS}")
endif()
endforeach()
endfunction()
function(target_link_sanitize)
if(CMAKE_VERSION VERSION_LESS 3.13)
target_link_sanitize_3_13(${ARGN})
return()
endif()
set(scope PRIVATE)
foreach(target ${ARGN})
if(target MATCHES "^INTERFACE|PUBLIC|PRIVATE")
set(scope ${target})
elseif(MSVC)
target_link_options(${target} ${scope} ${SANITIZE_LD})
else()
target_link_options(${target} ${scope} ${SANITIZE_CX} ${SANITIZE_LD})
endif()
endforeach()
endfunction()