if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
    set(sanitizers "")

    option(RTVAMP_ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" OFF)
    if(RTVAMP_ENABLE_SANITIZER_ADDRESS)
        list(APPEND sanitizers "address")
    endif()

    option(RTVAMP_ENABLE_SANITIZER_LEAK "Enable leak sanitizer" OFF)
    if(RTVAMP_ENABLE_SANITIZER_LEAK)
        list(APPEND sanitizers "leak")
    endif()

    option(RTVAMP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" OFF)
    if(RTVAMP_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR)
        list(APPEND sanitizers "undefined")
    endif()

    option(RTVAMP_ENABLE_SANITIZER_THREAD "Enable thread sanitizer" OFF)
    if(RTVAMP_ENABLE_SANITIZER_THREAD)
        if("address" IN_LIST sanitizers OR "leak" IN_LIST sanitizers)
            message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled")
        else()
            list(APPEND sanitizers "thread")
        endif()
    endif()

    option(RTVAMP_ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" OFF)
    if(RTVAMP_ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
        message(WARNING "Memory sanitizer requires all the code (including libc++) to be MSan-instrumented otherwise it reports false positives")
        if("address" IN_LIST sanitizers OR "thread" IN_LIST sanitizers OR "leak" IN_LIST sanitizers)
            message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled")
        else()
            list(APPEND sanitizers "memory")
        endif()
    endif()

    list(JOIN sanitizers "," list_of_sanitizers)
    
    if(list_of_sanitizers)
        if(NOT "${list_of_sanitizers}" STREQUAL "")
            target_compile_options(${project_options} INTERFACE -fsanitize=${list_of_sanitizers})
            target_link_options(${project_options} INTERFACE -fsanitize=${list_of_sanitizers})
        endif()
    endif()
endif()
