looper/cmake/SanitizerBuildTypes.cmake
2024-09-06 10:06:32 -07:00

123 lines
6.4 KiB
CMake

#[=======================================================================[.rst:
SanitizerBuildTypes
--------
Add the compiler and linker flags for the sanitizer build types.
Currently, only Clang and GCC are supported.
Support for MSVC has yet to be added.
Arguments
~~~~~~~~
Provide the names for the build types through the following variables:
ASAN
LSAN
MSAN
TSAN
UBSAN
It is possible to only provide a subset of these variables to only create build types for specific sanitizers.
#]=======================================================================]
function(sanitizer_build_types)
if(ARGC EQUAL 0)
message(FATAL_ERROR "No arguments were given.")
endif()
set(prefix ARG)
set(no_values "")
set(single_values ASAN LSAN MSAN TSAN UBSAN)
set(multi_values "")
include(CMakeParseArguments)
cmake_parse_arguments(${prefix}
"${no_values}"
"${single_values}"
"${multi_values}"
${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unexpected arguments: ${ARG_UNPARSED_ARGUMENTS}")
endif()
if(ARG_KEYWORDS_MISSING_VALUES)
message(FATAL_ERROR "Keywords missing values: ${ARG_KEYWORDS_MISSING_VALUES}")
endif()
set(_bitness 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_bitness 64)
endif()
# todo Add support for the AddressSanitizer for MSVC / 32-bit builds.
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
foreach(arg IN LISTS single_values)
if(${prefix}_${arg})
set_property(GLOBAL APPEND PROPERTY DEBUG_CONFIGURATIONS ${${prefix}_${arg}})
endif()
endforeach()
set(_asan_platforms Darwin FreeBSD Linux NetBSD Windows)
if(ARG_ASAN)
if(CMAKE_SYSTEM_NAME IN_LIST _asan_platforms)
set(CMAKE_C_FLAGS_${ARG_ASAN} "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the C compiler during Address Sanitizer builds.")
set(CMAKE_CXX_FLAGS_${ARG_ASAN} "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the C++ compiler during Address Sanitizer builds.")
set(CMAKE_EXE_LINKER_FLAGS_${ARG_ASAN} "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the linker during Address Sanitizer builds.")
else()
message("The address sanitizer is only available on ${_asan_platforms}")
endif()
endif()
set(_lsan_platforms Darwin Linux)
if(ARG_LSAN)
if(_bitness EQUAL 32)
message("The leak sanitizer is only available for 64-bit systems")
elseif(CMAKE_SYSTEM_NAME IN_LIST _lsan_platforms)
set(CMAKE_C_FLAGS_${ARG_LSAN} "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fsanitize=leak -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the C compiler during Leak Sanitizer builds.")
set(CMAKE_CXX_FLAGS_${ARG_LSAN} "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fsanitize=leak -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the C++ compiler during Leak Sanitizer builds.")
set(CMAKE_EXE_LINKER_FLAGS_${ARG_LSAN} "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -fsanitize=leak -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the linker during Leak Sanitizer builds.")
else()
message("The leak sanitizer is only available on ${_lsan_platforms}")
endif()
endif()
set(_msan_platforms FreeBSD Linux NetBSD)
if(ARG_MSAN)
if(CMAKE_SYSTEM_NAME IN_LIST _msan_platforms)
set(CMAKE_C_FLAGS_${ARG_MSAN} "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the C compiler during Memory Sanitizer builds.")
set(CMAKE_CXX_FLAGS_${ARG_MSAN} "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the C++ compiler during Memory Sanitizer builds.")
set(CMAKE_EXE_LINKER_FLAGS_${ARG_MSAN} "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g" CACHE STRING "Flags used by the linker during Memory Sanitizer builds.")
else()
message("The memory sanitizer is only available on ${_msan_platforms}")
endif()
endif()
set(_tsan_platforms Darwin FreeBSD Linux NetBSD)
if(ARG_TSAN)
if(_bitness EQUAL 32)
message("The thread sanitizer is only available for 64-bit systems")
elseif(CMAKE_SYSTEM_NAME IN_LIST _tsan_platforms)
set(CMAKE_C_FLAGS_${ARG_TSAN} "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fsanitize=thread -g" CACHE STRING "Flags used by the C compiler during Thread Sanitizer builds.")
set(CMAKE_CXX_FLAGS_${ARG_TSAN} "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fsanitize=thread -g" CACHE STRING "Flags used by the C++ compiler during Thread Sanitizer builds.")
set(CMAKE_EXE_LINKER_FLAGS_${ARG_TSAN} "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -fsanitize=thread -g" CACHE STRING "Flags used by the linker during Thread Sanitizer builds.")
else()
message("The thread sanitizer is only available on ${_tsan_platforms}")
endif()
endif()
set(_ubsan_platforms Darwin FreeBSD Linux NetBSD OpenBSD Windows)
if(ARG_UBSAN)
if(CMAKE_SYSTEM_NAME IN_LIST _ubsan_platforms)
set(CMAKE_C_FLAGS_${UBSAN} "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fsanitize=undefined -g" CACHE STRING "Flags used by the C compiler during Undefined Behaviour Sanitizer builds.")
set(CMAKE_CXX_FLAGS_${UBSAN} "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fsanitize=undefined -g" CACHE STRING "Flags used by the C++ compiler during Undefined Behaviour Sanitizer builds.")
set(CMAKE_EXE_LINKER_FLAGS_${UBSAN} "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -fsanitize=undefined -g" CACHE STRING "Flags used by the linker during Undefined Behavior Sanitizer builds.")
else()
message("The undefined behavior sanitizer is only available on ${_ubsan_platforms}")
endif()
endif()
else()
message("Sanitizers not supported for the current compiler: ${CMAKE_CXX_COMPILER_ID}.")
endif()
endfunction()