]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Move compiler sanitizer checking to separate cmake file.
authorNathan Moinvaziri <nathan@solidstatenetworks.com>
Mon, 11 May 2020 23:25:01 +0000 (19:25 -0400)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Sun, 24 May 2020 12:49:30 +0000 (14:49 +0200)
CMakeLists.txt
cmake/detect-sanitizer.cmake [new file with mode: 0644]

index ee223e421e116ccfc0adf1c178e4226bc0e2d9ee..68d76c0acbf515f2d36be94bbe7dc41ecedae713 100644 (file)
@@ -54,6 +54,7 @@ include(CMakeDependentOption)
 include(FeatureSummary)
 
 include(cmake/archdetect.cmake)
+include(cmake/detect-sanitizer.cmake)
 
 if(CMAKE_TOOLCHAIN_FILE)
     message(STATUS "Using CMake toolchain: ${CMAKE_TOOLCHAIN_FILE}")
@@ -309,85 +310,13 @@ endif()
 #
 check_include_file(unistd.h Z_HAVE_UNISTD_H)
 
-if(WITH_SANITIZERS AND WITH_MSAN)
+if(WITH_MSAN AND WITH_SANITIZERS)
     message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
+elseif(WITH_MSAN)
+    add_memory_sanitizer_check()
+elseif(WITH_SANITIZERS)
+    add_sanitizer_checks()
 endif()
-
-if(WITH_MSAN)
-    set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
-    check_c_source_compiles("int main() { return 0; }"
-        HAS_MSAN FAIL_REGEX "not supported|unrecognized command")
-    if(HAS_MSAN)
-        set(SANITIZERS_FLAGS "-fsanitize=memory")
-        message(STATUS "Adding memory sanitizer flag: ${SANITIZERS_FLAGS}")
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
-    endif()
-    set(CMAKE_REQUIRED_FLAGS)
-endif()
-
-if(WITH_SANITIZERS)
-    set(_sanitize_flags
-        address
-        alignment
-        array-bounds
-        bool
-        bounds
-        builtin
-        enum
-        float-divide-by-zero
-        function
-        integer-divide-by-zero
-        leak
-        null
-        nonnull-attribute
-        object-size
-        pointer-compare             # Depends on 'address'
-        pointer-overflow
-        pointer-subtract            # Depends on 'address'
-        return
-        returns-nonnull-attribute
-        shift
-        shift-base
-        shift-exponent
-        signed-integer-overflow
-        undefined
-        unsigned-integer-overflow
-        vla-bound
-        vptr
-       )
-    if(NOT UNALIGNED_OK)
-        list(APPEND _sanitize_flags alignment)
-    endif()
-    set(SANITIZERS_FLAGS "")
-    foreach(_flag ${_sanitize_flags})
-        if(NOT (CMAKE_CROSSCOMPILING_EMULATOR AND ${_flag} STREQUAL "leak")) # LeakSanitizer crashes under qemu
-            set(CMAKE_REQUIRED_FLAGS "-fsanitize=${SANITIZERS_FLAGS},${_flag}")
-            check_c_source_compiles("int main() { return 0; }"
-              HAS_SANITIZER_${_flag} FAIL_REGEX "not supported|unrecognized command")
-            if(${HAS_SANITIZER_${_flag}})
-                if("${SANITIZERS_FLAGS}" STREQUAL "")
-                    set(SANITIZERS_FLAGS "${_flag}")
-                else()
-                    set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS},${_flag}")
-                endif()
-            endif()
-            set(CMAKE_REQUIRED_FLAGS)
-        endif()
-    endforeach()
-
-    if(NOT ${SANITIZERS_FLAGS} STREQUAL "")
-        set(SANITIZERS_FLAGS "-fsanitize=${SANITIZERS_FLAGS}")
-        # Group flag -fsanitize=undefined will automatically add alignment, even if it is not in our
-        # sanitize flag list, so we need to explicitly disable alignment sanitizing.
-        if(UNALIGNED_OK AND ${SANITIZERS_FLAGS} MATCHES "alignment")
-            set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS} -fno-sanitize=alignment")
-        endif()
-    endif()
-
-    message(STATUS "Adding sanitizers flags: ${SANITIZERS_FLAGS}")
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
-endif()
-
 #
 # Check if we can hide zlib internal symbols that are linked between separate source files using hidden
 #
diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake
new file mode 100644 (file)
index 0000000..82ad0fd
--- /dev/null
@@ -0,0 +1,94 @@
+# detect-sanitizer.cmake -- Detect supported compiler sanitizer flags
+# Licensed under the Zlib license, see LICENSE.md for details
+
+macro(check_sanitizer_support known_checks supported_checks)
+    set(available_checks "")
+
+    # Build list of supported sanitizer flags by incrementally trying compilation with
+    # known sanitizer checks
+
+    foreach(check ${known_checks})
+        if(available_checks STREQUAL "")
+            set(compile_checks "${check}")
+        else()
+            set(compile_checks "${available_checks},${check}")
+        endif()
+
+        set(CMAKE_REQUIRED_FLAGS "-fsanitize=${compile_checks}")
+
+        check_c_source_compiles("int main() { return 0; }" HAS_SANITIZER_${check}
+            FAIL_REGEX "not supported|unrecognized command|unknown option")
+
+        set(CMAKE_REQUIRED_FLAGS)
+
+        if(HAS_SANITIZER_${check})
+            set(available_checks ${compile_checks})
+        endif()
+    endforeach()
+
+    set(${supported_checks} ${available_checks})
+endmacro()
+
+macro(add_memory_sanitizer_check)
+    check_sanitizer_support("memory" supported_checks)
+    if(NOT ${supported_checks} STREQUAL "")
+        message(STATUS "Memory sanitizer is enabled")
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
+    else()
+        message(STATUS "Memory sanitizer is not supported")
+    endif()
+endmacro()
+
+macro(add_sanitizer_checks)
+    set(known_checks
+        address
+        array-bounds
+        bool
+        bounds
+        builtin
+        enum
+        float-divide-by-zero
+        function
+        integer-divide-by-zero
+        null
+        nonnull-attribute
+        object-size
+        pointer-compare             # Depends on 'address'
+        pointer-overflow
+        pointer-subtract            # Depends on 'address'
+        return
+        returns-nonnull-attribute
+        shift
+        shift-base
+        shift-exponent
+        signed-integer-overflow
+        undefined
+        unsigned-integer-overflow
+        vla-bound
+        vptr
+        )
+
+    # Only check for leak sanitizer if not cross-compiling due to qemu crash
+    if(NOT CMAKE_CROSSCOMPILING_EMULATOR)
+        list(APPEND known_checks leak)
+    endif()
+    # Only check for alignment sanitizer flag if unaligned access is not supported
+    if(NOT UNALIGNED_OK)
+        list(APPEND known_checks alignment)
+    endif()
+
+    check_sanitizer_support("${known_checks}" supported_checks)
+
+    if(NOT ${supported_checks} STREQUAL "")
+        message(STATUS "Supported sanitizers checks are enabled: ${supported_checks}")
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
+
+        # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if
+        # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing.
+        if(UNALIGNED_OK)
+            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment")
+        endif()
+    else()
+        message(STATUS "Sanitizer checks are not supported")
+    endif()
+endmacro()
\ No newline at end of file