Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion cmake/Sanitizers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ function(
endif()

if(${ENABLE_SANITIZER_LEAK})
list(APPEND SANITIZERS "leak")
# LeakSanitizer is unsupported on Apple platforms (the linker rejects
# -fsanitize=leak on macOS, including arm64). On Apple, leak detection
# is provided by AddressSanitizer with ASAN_OPTIONS=detect_leaks=1.
if(APPLE)
message(WARNING "Leak sanitizer is not supported on Apple platforms; ignoring myproject_ENABLE_SANITIZER_LEAK")
else()
list(APPEND SANITIZERS "leak")
endif()
endif()

if(${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR})
Expand Down
10 changes: 10 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ include(${Catch2_SOURCE_DIR}/extras/Catch.cmake)
# Provide a simple smoke test to make sure that the CLI works and can display a --help message
add_test(NAME cli.has_help COMMAND intro --help)

# CMake-script regression tests for cmake/Sanitizers.cmake (issue #141).
add_test(
NAME cmake.sanitizers.apple_excludes_leak
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_SOURCE_DIR}/cmake/test_sanitizers_apple_excludes_leak.cmake)
add_test(
NAME cmake.sanitizers.non_apple_includes_leak
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_SOURCE_DIR}/cmake/test_sanitizers_non_apple_includes_leak.cmake)

# Provide a test to verify that the version being reported from the application
# matches the version given to CMake. This will be important once you package
# your program. Real world shows that this is the kind of simple mistake that is easy
Expand Down
62 changes: 62 additions & 0 deletions test/cmake/test_sanitizers_apple_excludes_leak.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Regression test for #141: macOS ARM doesn't support leak sanitizer.
#
# Simulates an Apple toolchain by setting APPLE=TRUE before including
# Sanitizers.cmake, stubs the target_*_options commands so that the flags
# requested by myproject_enable_sanitizers can be inspected, then asserts
# that "leak" is not propagated to the compiler/linker even when the user
# enables the leak sanitizer option.

cmake_minimum_required(VERSION 3.21)

set(APPLE TRUE)
set(MSVC FALSE)
set(CMAKE_CXX_COMPILER_ID "Clang")

set_property(GLOBAL PROPERTY captured_compile_options "")
set_property(GLOBAL PROPERTY captured_link_options "")

function(target_compile_options)
set_property(GLOBAL PROPERTY captured_compile_options "${ARGN}")
endfunction()

function(target_link_options)
set_property(GLOBAL PROPERTY captured_link_options "${ARGN}")
endfunction()

include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/Sanitizers.cmake")

myproject_enable_sanitizers(
test_target
ON # ENABLE_SANITIZER_ADDRESS
ON # ENABLE_SANITIZER_LEAK (should be filtered out on Apple)
OFF # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
OFF # ENABLE_SANITIZER_THREAD
OFF # ENABLE_SANITIZER_MEMORY
)

get_property(compile_options GLOBAL PROPERTY captured_compile_options)
get_property(link_options GLOBAL PROPERTY captured_link_options)

message(STATUS "Captured compile options: ${compile_options}")
message(STATUS "Captured link options: ${link_options}")

if(compile_options MATCHES "leak")
message(
FATAL_ERROR
"Leak sanitizer must not be enabled on Apple platforms (#141), "
"but compile options contain 'leak': ${compile_options}")
endif()

if(link_options MATCHES "leak")
message(
FATAL_ERROR
"Leak sanitizer must not be enabled on Apple platforms (#141), "
"but link options contain 'leak': ${link_options}")
endif()

if(NOT compile_options MATCHES "address")
message(
FATAL_ERROR
"Address sanitizer should still be enabled when leak is filtered out, "
"but compile options were: ${compile_options}")
endif()
52 changes: 52 additions & 0 deletions test/cmake/test_sanitizers_non_apple_includes_leak.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Companion to test_sanitizers_apple_excludes_leak.cmake (#141).
# Verifies that on non-Apple platforms the leak sanitizer is still
# propagated to the compiler/linker, so the Apple-specific guard does
# not silently disable leak detection elsewhere.

cmake_minimum_required(VERSION 3.21)

set(APPLE FALSE)
set(MSVC FALSE)
set(CMAKE_CXX_COMPILER_ID "Clang")

set_property(GLOBAL PROPERTY captured_compile_options "")
set_property(GLOBAL PROPERTY captured_link_options "")

function(target_compile_options)
set_property(GLOBAL PROPERTY captured_compile_options "${ARGN}")
endfunction()

function(target_link_options)
set_property(GLOBAL PROPERTY captured_link_options "${ARGN}")
endfunction()

include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/Sanitizers.cmake")

myproject_enable_sanitizers(
test_target
OFF # ENABLE_SANITIZER_ADDRESS
ON # ENABLE_SANITIZER_LEAK
OFF # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
OFF # ENABLE_SANITIZER_THREAD
OFF # ENABLE_SANITIZER_MEMORY
)

get_property(compile_options GLOBAL PROPERTY captured_compile_options)
get_property(link_options GLOBAL PROPERTY captured_link_options)

message(STATUS "Captured compile options: ${compile_options}")
message(STATUS "Captured link options: ${link_options}")

if(NOT compile_options MATCHES "leak")
message(
FATAL_ERROR
"Leak sanitizer must still be enabled on non-Apple platforms, "
"but compile options were: ${compile_options}")
endif()

if(NOT link_options MATCHES "leak")
message(
FATAL_ERROR
"Leak sanitizer must still be enabled on non-Apple platforms, "
"but link options were: ${link_options}")
endif()
Loading