Skip to content

Commit 6d6061e

Browse files
committed
Fix #141: skip leak sanitizer on Apple platforms
LeakSanitizer is unsupported on macOS (clang rejects -fsanitize=leak on arm64-apple-darwin and other Apple targets); leak detection there is provided by AddressSanitizer with ASAN_OPTIONS=detect_leaks=1. When myproject_ENABLE_SANITIZER_LEAK is requested on an Apple host, myproject_enable_sanitizers now warns and drops it from the sanitizer list instead of producing an unsupported -fsanitize=leak compile flag. Adds two CMake-script regression tests that stub target_*_options to verify leak is filtered out on Apple and still propagated elsewhere.
1 parent ec01c73 commit 6d6061e

4 files changed

Lines changed: 132 additions & 1 deletion

File tree

cmake/Sanitizers.cmake

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ function(
1515
endif()
1616

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

2128
if(${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR})

test/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ include(${Catch2_SOURCE_DIR}/extras/Catch.cmake)
2424
# Provide a simple smoke test to make sure that the CLI works and can display a --help message
2525
add_test(NAME cli.has_help COMMAND intro --help)
2626

27+
# CMake-script regression tests for cmake/Sanitizers.cmake (issue #141).
28+
add_test(
29+
NAME cmake.sanitizers.apple_excludes_leak
30+
COMMAND ${CMAKE_COMMAND} -P
31+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/test_sanitizers_apple_excludes_leak.cmake)
32+
add_test(
33+
NAME cmake.sanitizers.non_apple_includes_leak
34+
COMMAND ${CMAKE_COMMAND} -P
35+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/test_sanitizers_non_apple_includes_leak.cmake)
36+
2737
# Provide a test to verify that the version being reported from the application
2838
# matches the version given to CMake. This will be important once you package
2939
# your program. Real world shows that this is the kind of simple mistake that is easy
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Regression test for #141: macOS ARM doesn't support leak sanitizer.
2+
#
3+
# Simulates an Apple toolchain by setting APPLE=TRUE before including
4+
# Sanitizers.cmake, stubs the target_*_options commands so that the flags
5+
# requested by myproject_enable_sanitizers can be inspected, then asserts
6+
# that "leak" is not propagated to the compiler/linker even when the user
7+
# enables the leak sanitizer option.
8+
9+
cmake_minimum_required(VERSION 3.21)
10+
11+
set(APPLE TRUE)
12+
set(MSVC FALSE)
13+
set(CMAKE_CXX_COMPILER_ID "Clang")
14+
15+
set_property(GLOBAL PROPERTY captured_compile_options "")
16+
set_property(GLOBAL PROPERTY captured_link_options "")
17+
18+
function(target_compile_options)
19+
set_property(GLOBAL PROPERTY captured_compile_options "${ARGN}")
20+
endfunction()
21+
22+
function(target_link_options)
23+
set_property(GLOBAL PROPERTY captured_link_options "${ARGN}")
24+
endfunction()
25+
26+
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/Sanitizers.cmake")
27+
28+
myproject_enable_sanitizers(
29+
test_target
30+
ON # ENABLE_SANITIZER_ADDRESS
31+
ON # ENABLE_SANITIZER_LEAK (should be filtered out on Apple)
32+
OFF # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
33+
OFF # ENABLE_SANITIZER_THREAD
34+
OFF # ENABLE_SANITIZER_MEMORY
35+
)
36+
37+
get_property(compile_options GLOBAL PROPERTY captured_compile_options)
38+
get_property(link_options GLOBAL PROPERTY captured_link_options)
39+
40+
message(STATUS "Captured compile options: ${compile_options}")
41+
message(STATUS "Captured link options: ${link_options}")
42+
43+
if(compile_options MATCHES "leak")
44+
message(
45+
FATAL_ERROR
46+
"Leak sanitizer must not be enabled on Apple platforms (#141), "
47+
"but compile options contain 'leak': ${compile_options}")
48+
endif()
49+
50+
if(link_options MATCHES "leak")
51+
message(
52+
FATAL_ERROR
53+
"Leak sanitizer must not be enabled on Apple platforms (#141), "
54+
"but link options contain 'leak': ${link_options}")
55+
endif()
56+
57+
if(NOT compile_options MATCHES "address")
58+
message(
59+
FATAL_ERROR
60+
"Address sanitizer should still be enabled when leak is filtered out, "
61+
"but compile options were: ${compile_options}")
62+
endif()
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Companion to test_sanitizers_apple_excludes_leak.cmake (#141).
2+
# Verifies that on non-Apple platforms the leak sanitizer is still
3+
# propagated to the compiler/linker, so the Apple-specific guard does
4+
# not silently disable leak detection elsewhere.
5+
6+
cmake_minimum_required(VERSION 3.21)
7+
8+
set(APPLE FALSE)
9+
set(MSVC FALSE)
10+
set(CMAKE_CXX_COMPILER_ID "Clang")
11+
12+
set_property(GLOBAL PROPERTY captured_compile_options "")
13+
set_property(GLOBAL PROPERTY captured_link_options "")
14+
15+
function(target_compile_options)
16+
set_property(GLOBAL PROPERTY captured_compile_options "${ARGN}")
17+
endfunction()
18+
19+
function(target_link_options)
20+
set_property(GLOBAL PROPERTY captured_link_options "${ARGN}")
21+
endfunction()
22+
23+
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/Sanitizers.cmake")
24+
25+
myproject_enable_sanitizers(
26+
test_target
27+
OFF # ENABLE_SANITIZER_ADDRESS
28+
ON # ENABLE_SANITIZER_LEAK
29+
OFF # ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
30+
OFF # ENABLE_SANITIZER_THREAD
31+
OFF # ENABLE_SANITIZER_MEMORY
32+
)
33+
34+
get_property(compile_options GLOBAL PROPERTY captured_compile_options)
35+
get_property(link_options GLOBAL PROPERTY captured_link_options)
36+
37+
message(STATUS "Captured compile options: ${compile_options}")
38+
message(STATUS "Captured link options: ${link_options}")
39+
40+
if(NOT compile_options MATCHES "leak")
41+
message(
42+
FATAL_ERROR
43+
"Leak sanitizer must still be enabled on non-Apple platforms, "
44+
"but compile options were: ${compile_options}")
45+
endif()
46+
47+
if(NOT link_options MATCHES "leak")
48+
message(
49+
FATAL_ERROR
50+
"Leak sanitizer must still be enabled on non-Apple platforms, "
51+
"but link options were: ${link_options}")
52+
endif()

0 commit comments

Comments
 (0)