macro(libfuzz_check)
    if (NOT libfuzz_cheched)
        message(STATUS "Libfuzz was requested. Setting up...")
        enable_testing()
        include(${PROJECT_SOURCE_DIR}/cmake/tools/test_helper.cmake)
        set(libfuzz_cheched ON)

        if (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
            message(WARNING "Libfuzz was requested, but the compiler used is \"${CMAKE_CXX_COMPILER_ID}\" where as libfuzz requires Clang to be used. All Libfuzz calls will be ignored...")
            return()
        endif()
        if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
            message(WARNING "Libfuzz was requested, but the compiler used is Clang ${CMAKE_CXX_COMPILER_VERSION} where as libfuzz requires at least Clang 6.0.0 to be used. All Libfuzz calls will be ignored...")
            return()
        endif()

        message(STATUS "Using Libfuzz")

        set(libfuzz_valid ON)
    endif()
endmacro()

macro(libfuzz_add_test)
    set(oneValueArgs NAME)
    set(multiValueArgs SOURCES ARGS)
    cmake_parse_arguments(LIBFUZZ_ADD_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )

    libfuzz_check()

    if (NOT libfuzz_valid)
        message(STATUS "Libfuzz test: ${LIBFUZZ_ADD_TEST_NAME} was skipped.")
    else()
        message(STATUS "Added Libfuzz test: ${LIBFUZZ_ADD_TEST_NAME}")
        add_executable(${LIBFUZZ_ADD_TEST_NAME} EXCLUDE_FROM_ALL ${LIBFUZZ_ADD_TEST_SOURCES})
        add_dependencies(build_tests ${LIBFUZZ_ADD_TEST_NAME})
        target_link_libraries(${LIBFUZZ_ADD_TEST_NAME} PRIVATE -fsanitize=fuzzer,undefined,address)
        target_compile_options(${LIBFUZZ_ADD_TEST_NAME} PRIVATE -fsanitize=fuzzer,undefined,address)
        add_test(${LIBFUZZ_ADD_TEST_NAME} ${LIBFUZZ_ADD_TEST_NAME} ${LIBFUZZ_ADD_TEST_ARGS})
    endif()
endmacro()
