From a7326ee0f4cf5fae5db28c13e8728bc1b66bcac5 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Thu, 2 Aug 2018 13:59:31 +0800 Subject: [PATCH] cmake: extract sanitizer detection out also, we don't need to pass '-lasan' or '-ltsan' to linker. it's suggested to use the "-fsanitize=${sanitizer}". please note, this module is compatible with the one used in seastar on purpose, as seastar is included in ceph using add_subdirectory(), and it in turn add its own cmake modules directory using list(APPEND ...), so cmake/modules/FindSantitizers.cmake is prefered over src/seastar/cmake/FindSantitizers.cmake. Signed-off-by: Kefu Chai --- CMakeLists.txt | 39 ++++++---------- cmake/modules/FindSanitizers.cmake | 72 ++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 26 deletions(-) create mode 100644 cmake/modules/FindSanitizers.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 2afb8dba084..ba65aa9f318 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -558,43 +558,30 @@ endif(LINUX) # 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 diff --git a/cmake/modules/FindSanitizers.cmake b/cmake/modules/FindSanitizers.cmake new file mode 100644 index 00000000000..31f1ed3d4aa --- /dev/null +++ b/cmake/modules/FindSanitizers.cmake @@ -0,0 +1,72 @@ +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() -- 2.39.5