]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cmake: extract sanitizer detection out
authorKefu Chai <kchai@redhat.com>
Thu, 2 Aug 2018 05:59:31 +0000 (13:59 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 2 Aug 2018 06:43:47 +0000 (14:43 +0800)
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 <kchai@redhat.com>
CMakeLists.txt
cmake/modules/FindSanitizers.cmake [new file with mode: 0644]

index 2afb8dba0846cafa1f574cc27bc2f0ce171e70d6..ba65aa9f3187d8e5134da3372ee566f0ea4c52b8 100644 (file)
@@ -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 (file)
index 0000000..31f1ed3
--- /dev/null
@@ -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()