# ASAN and friends
option(WITH_ASAN "build with ASAN" OFF)
-option(WITH_ASAN_LEAK "explicitly enable ASAN leak detection" OFF)
-
if(WITH_ASAN)
- list(APPEND SANITIZE_FLAGS "address")
- if(WITH_ASAN_LEAK)
- list(APPEND SANITIZE_FLAGS "leak")
- endif()
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan")
- if(HAVE_JEMALLOC)
- message(FATAL "ASAN does not work well with JeMalloc")
- endif()
+ list(APPEND sanitizers "address")
+endif()
+
+option(WITH_ASAN_LEAK "explicitly enable ASAN leak detection" OFF)
+if(WITH_ASAN_LEAK)
+ list(APPEND sanitizers "leak")
endif()
option(WITH_TSAN "build with TSAN" OFF)
if(WITH_TSAN)
- if(WITH_ASAN AND WITH_ASAN_LEAK)
- message(FATAL_ERROR "Cannot combine -fsanitize-leak w/-fsanitize-thread")
- elseif(HAVE_JEMALLOC)
- message(FATAL "TSAN does not work well with JeMalloc")
- endif()
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -ltsan")
- list(APPEND SANITIZE_FLAGS "thread")
+ list(APPEND sanitizers "thread")
endif()
option(WITH_UBSAN "build with UBSAN" OFF)
if(WITH_UBSAN)
- if(HAVE_JEMALLOC)
- message(FATAL "UBSAN does not work well with JeMalloc")
- endif()
- list(APPEND SANITIZE_FLAGS "undefined")
+ list(APPEND sanitizers "undefined-behavior")
endif()
-if(SANITIZE_FLAGS)
- string(REPLACE ";" "," SANITIZE_FLAGS "${SANITIZE_FLAGS}")
- set(SANITIZE_CFLAGS "-fsanitize=${SANITIZE_FLAGS} -fno-omit-frame-pointer")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_CFLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_CFLAGS}")
+if(sanitizers)
+ find_package(Sanitizers REQUIRED ${sanitizers})
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${Sanitizers_COMPILE_OPTIONS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Sanitizers_COMPILE_OPTIONS}")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${Sanitizers_COMPILE_OPTIONS}")
endif()
# Rocksdb
--- /dev/null
+if(NOT Sanitizers_FIND_COMPONENTS)
+ set(Sanitizers_FIND_COMPONENTS
+ address undefined-behavior)
+endif()
+if(HAVE_JEMALLOC)
+ message(WARNING "JeMalloc does not work well with sanitizers")
+endif()
+
+set(Sanitizers_OPTIONS)
+
+foreach(component ${Sanitizers_FIND_COMPONENTS})
+ if(component STREQUAL "address")
+ set(Sanitizers_Address_COMPILE_OPTIONS "address")
+ list(APPEND Sanitizers_OPTIONS "address")
+ elseif(component STREQUAL "leak")
+ set(Sanitizers_Leak_COMPILE_OPTIONS "leak")
+ list(APPEND Sanitizers_OPTIONS "leak")
+ elseif(component STREQUAL "thread")
+ if ("Address" IN_LIST ${Sanitizers_FIND_COMPONENTS} OR
+ "Leak" IN_LIST ${Sanitizers_FIND_COMPONENTS})
+ message(SEND_ERROR "Cannot combine -fsanitize-leak w/ -fsanitize-thread")
+ elseif(NOT CMAKE_POSITION_INDEPENDENT_CODE)
+ message(SEND_ERROR "TSan requires all code to be position independent")
+ endif()
+ set(Sanitizers_Thread_COMPILE_OPTIONS "thread")
+ list(APPEND Sanitizers_OPTIONS "thread")
+ elseif(component STREQUAL "undefined-behavior")
+ set(Sanitizers_Undefined-Behavior_COMPILE_OPTIONS "undefined")
+ list(APPEND Sanitizers_OPTIONS "undefined")
+ else()
+ message(SEND_ERROR "Unsupported sanitizer: ${component}")
+ endif()
+endforeach()
+
+if(Sanitizers_OPTIONS)
+ string(REPLACE ";" ","
+ Sanitizers_COMPILE_OPTIONS
+ "${Sanitizers_OPTIONS}")
+ set(Sanitizers_COMPILE_OPTIONS
+ "-fsanitize=${Sanitizers_COMPILE_OPTIONS} -fno-omit-frame-pointer")
+endif()
+
+include(CheckCXXSourceCompiles)
+set(CMAKE_REQUIRED_FLAGS ${Sanitizers_COMPILE_OPTIONS})
+set(CMAKE_REQUIRED_LIBRARIES ${Sanitizers_COMPILE_OPTIONS})
+check_cxx_source_compiles("int main() {}"
+ Sanitizers_ARE_SUPPORTED)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Sanitizers
+ REQUIRED_VARS
+ Sanitizers_ARE_SUPPORTED
+ Sanitizers_COMPILE_OPTIONS)
+
+if(Sanitizers_FOUND)
+ if(NOT TARGET Sanitizers::Sanitizers)
+ add_library(Sanitizers::Sanitizers INTERFACE IMPORTED)
+ set_target_properties(Sanitizers::Sanitizers PROPERTIES
+ INTERFACE_COMPILE_OPTIONS ${Sanitizers_COMPILE_OPTIONS}
+ INTERFACE_LINK_LIBRARIES ${Sanitizers_COMPILE_OPTIONS})
+ endif()
+ foreach(component ${Sanitizers_FIND_COMPONENTS})
+ if(NOT TARGET Sanitizers::${component})
+ set(target Sanitizers::${component})
+ set(compile_option "-fsanitize=${Sanitizers_${component}_COMPILE_OPTIONS}")
+ add_library(${target} INTERFACE IMPORTED)
+ set_target_properties(${target} PROPERTIES
+ INTERFACE_COMPILE_OPTIONS ${compile_option}
+ INTERFACE_LINK_LIBRARIES ${compile_option})
+ endif()
+ endforeach()
+endif()