2.0.2
This commit is contained in:
		@@ -7,9 +7,18 @@ if(NOT MyxCMake_DIR)
 | 
			
		||||
  message(FATAL_ERROR "MyxxCMake library required MyxCMake to work")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
			
		||||
set(MYXX_CMAKE_LIB_DIR "${MYXX_CMAKE_SOURCE_DIR}/lib" CACHE PATH "")
 | 
			
		||||
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/CodeAnalyzeClangTidy.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/Coverage.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/AnalyzeApplyReplacements.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/AnalyzeClangTidy.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/AnalyzeClangCheck.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/AnalyzeClazy.cmake)
 | 
			
		||||
 | 
			
		||||
include(${MYXX_CMAKE_SOURCE_DIR}/sanitizers/FindSanitizers.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_SOURCE_DIR}/pvs-studio/PVS-Studio.cmake)
 | 
			
		||||
include(${MYXX_CMAKE_LIB_DIR}/AnalyzePvsStudio.cmake)
 | 
			
		||||
 | 
			
		||||
function(myxx)
 | 
			
		||||
  get_property(targets DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} PROPERTY BUILDSYSTEM_TARGETS)
 | 
			
		||||
@@ -17,7 +26,11 @@ function(myxx)
 | 
			
		||||
 | 
			
		||||
    get_target_property(target_type ${iter} TYPE)
 | 
			
		||||
    if(NOT ${target_type} STREQUAL "UTILITY")
 | 
			
		||||
      myxx_code_coverage(${iter})
 | 
			
		||||
      myxx_analyze_clang_tidy(${iter})
 | 
			
		||||
      myxx_analyze_clang_check(${iter})
 | 
			
		||||
      myxx_analyze_clazy(${iter})
 | 
			
		||||
      myxx_analyze_pvs_studio(${iter})
 | 
			
		||||
    endif()
 | 
			
		||||
  endforeach()
 | 
			
		||||
endfunction(myxx)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								MyxxCMake/lib/AnalyzeApplyReplacements.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								MyxxCMake/lib/AnalyzeApplyReplacements.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
include_guard(GLOBAL)
 | 
			
		||||
 | 
			
		||||
if(NOT CLANG_APPLY_REPLACEMENTS_NAME)
 | 
			
		||||
  set(CLANG_APPLY_REPLACEMENTS_NAMES clang-apply-replacements)
 | 
			
		||||
  foreach(V RANGE 9 18)
 | 
			
		||||
    list(INSERT CLANG_APPLY_REPLACEMENTS_NAMES 0 "clang-apply-replacements-${V}")
 | 
			
		||||
  endforeach()
 | 
			
		||||
  unset(V)
 | 
			
		||||
else()
 | 
			
		||||
  set(CLANG_APPLY_REPLACEMENTS_NAMES ${CLANG_APPLY_REPLACEMENTS_NAME})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
find_program(CLANG_APPLY_REPLACEMENTS_EXE NAMES ${CLANG_APPLY_REPLACEMENTS_NAMES})
 | 
			
		||||
unset(CLANG_APPLY_REPLACEMENTS_NAMES)
 | 
			
		||||
							
								
								
									
										52
									
								
								MyxxCMake/lib/AnalyzeClangCheck.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								MyxxCMake/lib/AnalyzeClangCheck.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
include_guard(GLOBAL)
 | 
			
		||||
 | 
			
		||||
if(NOT CLANG_CHECK_NAME)
 | 
			
		||||
  set(CLANG_CHECK_NAMES clang-check)
 | 
			
		||||
  foreach(V RANGE 9 18)
 | 
			
		||||
    list(INSERT CLANG_CHECK_NAMES 0 "clang-check-${V}")
 | 
			
		||||
  endforeach()
 | 
			
		||||
  unset(V)
 | 
			
		||||
else()
 | 
			
		||||
  set(CLANG_CHECK_NAMES ${CLANG_CHECK_NAME})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
find_program(CLANG_CHECK_EXE NAMES ${CLANG_CHECK_NAMES})
 | 
			
		||||
unset(CLANG_CHECK_NAMES)
 | 
			
		||||
 | 
			
		||||
function(myxx_analyze_clang_check target)
 | 
			
		||||
  if(NOT CLANG_CHECK_EXE)
 | 
			
		||||
    message(STATUS "MyxCMake: Clang Check analyzer is not found")
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  if(TARGET ${target}-analyze-clang-check)
 | 
			
		||||
    message(STATUS "MyxxCMake: target ${target}-analyze-clang-check already exists")
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  set(options FIX)
 | 
			
		||||
  set(oneValueArgs)
 | 
			
		||||
  set(multiValueArgs EXTRA_ARGS)
 | 
			
		||||
  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 | 
			
		||||
 | 
			
		||||
  set(args --analyze --extra-arg=-Wno-unknown-warning-option ${EXTRA_ARGS})
 | 
			
		||||
  get_target_property(sources ${target} SOURCES)
 | 
			
		||||
  foreach(iter ${sources})
 | 
			
		||||
    string(FIND ${iter} ${CMAKE_BINARY_DIR} pos)
 | 
			
		||||
      if(pos EQUAL -1)
 | 
			
		||||
        list(APPEND srcs ${iter})
 | 
			
		||||
      endif()
 | 
			
		||||
  endforeach()
 | 
			
		||||
 | 
			
		||||
  if(ARG_FIX)
 | 
			
		||||
    list(APPEND args "--fixit")
 | 
			
		||||
  endif()
 | 
			
		||||
  if(NOT TARGET myxx-analyze-clang-check)
 | 
			
		||||
    add_custom_target(myxx-analyze-clang-check)
 | 
			
		||||
  endif()
 | 
			
		||||
  add_custom_target(${target}-analyze-clang-check
 | 
			
		||||
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 | 
			
		||||
    COMMAND ${CLANG_CHECK_EXE} ${args} -p ${CMAKE_BINARY_DIR} ${srcs})
 | 
			
		||||
  add_dependencies(${target}-analyze-clang-check ${target})
 | 
			
		||||
  add_dependencies(myxx-analyze-clang-check ${target}-analyze-clang-check)
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										56
									
								
								MyxxCMake/lib/AnalyzeClazy.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								MyxxCMake/lib/AnalyzeClazy.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
include_guard(GLOBAL)
 | 
			
		||||
 | 
			
		||||
find_program(CLAZY_EXE NAMES clazy-standalone)
 | 
			
		||||
 | 
			
		||||
if(CLAZY_EXE AND CLANG_APPLY_REPLACEMENTS_EXE)
 | 
			
		||||
  option(MYX_CMAKE_CLAZY_FIX "MyxCMake: perform fixes for Clazy" OFF)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
function(myxx_analyze_clazy target)
 | 
			
		||||
  if(NOT CLAZY_EXE)
 | 
			
		||||
    message(STATUS "MyxCMake: Clazy standalone analyzer is not found")
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  if(TARGET ${target}-analyze-clazy)
 | 
			
		||||
    message(STATUS "MyxxCMake: target ${target}-analyze-clazy already exists")
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  set(options FIX)
 | 
			
		||||
  set(oneValueArgs CHECKS)
 | 
			
		||||
  set(multiValueArgs)
 | 
			
		||||
  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 | 
			
		||||
 | 
			
		||||
  if(NOT ARG_CHECKS)
 | 
			
		||||
    set(ARG_CHECKS "level2,container-inside-loop,heap-allocated-small-trivial-type,inefficient-qlist,isempty-vs-count,qt-keywords,unneeded-cast")
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  set(args -checks=${ARG_CHECKS}
 | 
			
		||||
           -extra-arg=-Wno-unknown-warning-option
 | 
			
		||||
           -export-fixes=clazy-fixes-file.yaml)
 | 
			
		||||
  get_target_property(sources ${target} SOURCES)
 | 
			
		||||
  foreach(iter ${sources})
 | 
			
		||||
    string(FIND ${iter} ${CMAKE_BINARY_DIR} pos)
 | 
			
		||||
      if(pos EQUAL -1)
 | 
			
		||||
        list(APPEND srcs ${iter})
 | 
			
		||||
      endif()
 | 
			
		||||
  endforeach()
 | 
			
		||||
 | 
			
		||||
  if(NOT TARGET myxx-analyze-clazy)
 | 
			
		||||
    add_custom_target(myxx-analyze-clazy)
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  if(ARG_FIX)
 | 
			
		||||
    add_custom_target(${target}-analyze-clazy
 | 
			
		||||
      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 | 
			
		||||
      COMMAND ${CLAZY_EXE} ${args} -p ${CMAKE_BINARY_DIR} ${srcs}
 | 
			
		||||
      COMMAND ${CLANG_APPLY_REPLACEMENTS_EXE} ${CMAKE_BINARY_DIR})
 | 
			
		||||
  else()
 | 
			
		||||
    add_custom_target(${target}-analyze-clazy
 | 
			
		||||
      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 | 
			
		||||
      COMMAND ${CLAZY_EXE} ${args} -p ${CMAKE_BINARY_DIR} ${srcs})
 | 
			
		||||
  endif()
 | 
			
		||||
  add_dependencies(${target}-analyze-clazy ${target})
 | 
			
		||||
  add_dependencies(myxx-analyze-clazy ${target}-analyze-clazy)
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										54
									
								
								MyxxCMake/lib/AnalyzePvsStudio.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								MyxxCMake/lib/AnalyzePvsStudio.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
find_program(PVS_STUDIO_ANALYZER_EXE pvs-studio-analyzer)
 | 
			
		||||
find_program(PVS_STUDIO_CONVERTER_EXE plog-converter)
 | 
			
		||||
 | 
			
		||||
function(myxx_analyze_pvs_studio target)
 | 
			
		||||
  if(PVS_STUDIO_ANALYZER_EXE)
 | 
			
		||||
    message(STATUS "MyxxCMake: pvs-studio-analyzer not found.")
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
  if(PVS_STUDIO_CONVERTER_EXE)
 | 
			
		||||
    message(STATUS "MyxxCMake: pvs-studio-converter not found.")
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  if(TARGET myx-cmake-analyze-pvs-studio)
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  set(options)
 | 
			
		||||
  set(oneValueArgs CHECKS)
 | 
			
		||||
  set(multiValueArgs)
 | 
			
		||||
  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 | 
			
		||||
 | 
			
		||||
  set(PVS_STUDIO_HEADER "${CMAKE_BINARY_DIR}/include/myx_cmake_pvs_studio_header_p.hpp")
 | 
			
		||||
  file(WRITE ${PVS_STUDIO_HEADER}
 | 
			
		||||
    "#ifndef MYX_CMAKE_PVS_STUDIO_HEADER_HPP_\n"
 | 
			
		||||
    "#define MYX_CMAKE_PVS_STUDIO_HEADER_HPP_\n"
 | 
			
		||||
    "#pragma once\n"
 | 
			
		||||
    "//-V813_MINSIZE=33\n"
 | 
			
		||||
    "#endif // MYX_CMAKE_PVS_STUDIO_HEADER_HPP_\n")
 | 
			
		||||
 | 
			
		||||
  pvs_studio_add_target(TARGET myx-cmake-analyze-pvs-studio
 | 
			
		||||
    LOG
 | 
			
		||||
    COMPILE_COMMANDS
 | 
			
		||||
    HIDE_HELP
 | 
			
		||||
    OUTPUT FORMAT errorfile
 | 
			
		||||
    ARGS --exclude-path ${CMAKE_CURRENT_BINARY_DIR}/${target}_autogen
 | 
			
		||||
    MODE GA:1,2,3;64:1;OP:1,2;CS:1,2)
 | 
			
		||||
 | 
			
		||||
  get_target_property(__target_type ${target} TYPE)
 | 
			
		||||
  if(${__target_type} STREQUAL INTERFACE_LIBRARY)
 | 
			
		||||
    set(__target_type INTERFACE)
 | 
			
		||||
  else()
 | 
			
		||||
    set(__target_type PRIVATE)
 | 
			
		||||
  endif()
 | 
			
		||||
  if(MSVC)
 | 
			
		||||
    target_compile_options(${target} BEFORE ${__target_type} /FI ${PVS_STUDIO_HEADER})
 | 
			
		||||
  else() # GCC/Clang
 | 
			
		||||
    target_compile_options(${target} BEFORE ${__target_type} -include ${PVS_STUDIO_HEADER})
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  add_dependencies(myx-cmake-analyze-pvs-studio ${target})
 | 
			
		||||
  get_target_property(__target_source_dir "${target}" SOURCE_DIR)
 | 
			
		||||
  pvs_studio_analyze_target("${target}" "${__target_source_dir}")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										46
									
								
								MyxxCMake/lib/Coverage.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								MyxxCMake/lib/Coverage.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
option(MYXX_CODE_COVERAGE "MyxxCMake: enable code coverage" OFF)
 | 
			
		||||
 | 
			
		||||
if(MYXX_CODE_COVERAGE)
 | 
			
		||||
  find_program(LCOV_EXE NAMES lcov)
 | 
			
		||||
  find_program(GENHTML_EXE NAMES genhtml)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
function(myxx_code_coverage target)
 | 
			
		||||
  if(NOT MYXX_CODE_COVERAGE)
 | 
			
		||||
    return()
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  if(CMAKE_CXX_COMPILER_IS_GCC)
 | 
			
		||||
    target_compile_options(${target} PUBLIC "--coverage")
 | 
			
		||||
    set_property(
 | 
			
		||||
      TARGET ${target}
 | 
			
		||||
      APPEND_STRING
 | 
			
		||||
      PROPERTY LINK_FLAGS " --coverage")
 | 
			
		||||
  endif()
 | 
			
		||||
  if(CMAKE_CXX_COMPILER_IS_CLANG)
 | 
			
		||||
    target_compile_options(${target} PUBLIC "-fprofile-instr-generate -fcoverage-mapping")
 | 
			
		||||
    set_property(
 | 
			
		||||
      TARGET ${target}
 | 
			
		||||
      APPEND_STRING
 | 
			
		||||
      PROPERTY LINK_FLAGS " --coverage")
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  if(LCOV_EXE)
 | 
			
		||||
    add_custom_target(${target}-coverage
 | 
			
		||||
      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 | 
			
		||||
      COMMAND ${LCOV_EXE} --test-name ${target} --output "${target}.lcov" --capture
 | 
			
		||||
              --no-external
 | 
			
		||||
              --base-directory ${CMAKE_SOURCE_DIR}
 | 
			
		||||
              --directory ${CMAKE_BINARY_DIR})
 | 
			
		||||
              --exclude "/usr/\\\*"
 | 
			
		||||
              --exclude "${CMAKE_BINARY_DIR}/\\\*"
 | 
			
		||||
    add_dependencies(${target}-coverage ${target})
 | 
			
		||||
 | 
			
		||||
    if(GENHTML_EXE)
 | 
			
		||||
      add_custom_target(${target}-coverage-report
 | 
			
		||||
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
 | 
			
		||||
        COMMAND ${GENHTML_EXE} --output-directory "${target}-coverage-html" "${target}.lcov")
 | 
			
		||||
      add_dependencies(${target}-coverage-report ${target}-coverage)
 | 
			
		||||
    endif()
 | 
			
		||||
  endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										607
									
								
								MyxxCMake/pvs-studio/PVS-Studio.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								MyxxCMake/pvs-studio/PVS-Studio.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,607 @@
 | 
			
		||||
# 2006-2008 (c) Viva64.com Team
 | 
			
		||||
# 2008-2020 (c) OOO "Program Verification Systems"
 | 
			
		||||
# 2020-2022 (c) PVS-Studio LLC
 | 
			
		||||
# Version 12
 | 
			
		||||
 | 
			
		||||
cmake_minimum_required(VERSION 3.0.0)
 | 
			
		||||
cmake_policy(SET CMP0054 NEW)
 | 
			
		||||
 | 
			
		||||
if (PVS_STUDIO_AS_SCRIPT)
 | 
			
		||||
    # This code runs at build time.
 | 
			
		||||
    # It executes pvs-studio-analyzer and propagates its return value.
 | 
			
		||||
 | 
			
		||||
    set(in_cl_params FALSE)
 | 
			
		||||
    set(additional_args)
 | 
			
		||||
 | 
			
		||||
    foreach (arg ${PVS_STUDIO_COMMAND})
 | 
			
		||||
        if (NOT in_cl_params)
 | 
			
		||||
            if ("${arg}" STREQUAL "--cl-params")
 | 
			
		||||
                set(in_cl_params TRUE)
 | 
			
		||||
            endif()
 | 
			
		||||
        else()
 | 
			
		||||
            # A workaround for macOS frameworks (e.g. QtWidgets.framework)
 | 
			
		||||
            # You can test this workaround on this project: https://github.com/easyaspi314/MidiEditor/tree/gba
 | 
			
		||||
            if (APPLE AND "${arg}" MATCHES "^-I(.*)\\.framework$")
 | 
			
		||||
                STRING(REGEX REPLACE "^-I(.*)\\.framework$" "\\1.framework" framework "${arg}")
 | 
			
		||||
                if (IS_ABSOLUTE "${framework}")
 | 
			
		||||
                    get_filename_component(framework "${framework}" DIRECTORY)
 | 
			
		||||
                    list(APPEND additional_args "-iframework")
 | 
			
		||||
                    list(APPEND additional_args "${framework}")
 | 
			
		||||
                endif()
 | 
			
		||||
            endif()
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    file(REMOVE "${PVS_STUDIO_LOG_FILE}")
 | 
			
		||||
    execute_process(COMMAND ${PVS_STUDIO_COMMAND} ${additional_args}
 | 
			
		||||
                    RESULT_VARIABLE result
 | 
			
		||||
                    OUTPUT_VARIABLE output
 | 
			
		||||
                    ERROR_VARIABLE error)
 | 
			
		||||
 | 
			
		||||
    if (result AND NOT output MATCHES "^No compilation units were found\\.")
 | 
			
		||||
        message(FATAL_ERROR "PVS-Studio exited with non-zero code.\nStdout:\n${output}\nStderr:\n${error}\n")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    return()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if(__PVS_STUDIO_INCLUDED)
 | 
			
		||||
    return()
 | 
			
		||||
endif()
 | 
			
		||||
set(__PVS_STUDIO_INCLUDED TRUE)
 | 
			
		||||
 | 
			
		||||
set(PVS_STUDIO_SCRIPT "${CMAKE_CURRENT_LIST_FILE}")
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_log TEXT)
 | 
			
		||||
    if (PVS_STUDIO_DEBUG)
 | 
			
		||||
        message("PVS-Studio: ${TEXT}")
 | 
			
		||||
    endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_relative_path VAR ROOT FILEPATH)
 | 
			
		||||
    if (WIN32)
 | 
			
		||||
        STRING(REGEX REPLACE "\\\\" "/" ROOT ${ROOT})
 | 
			
		||||
        STRING(REGEX REPLACE "\\\\" "/" FILEPATH ${FILEPATH})
 | 
			
		||||
    endif()
 | 
			
		||||
    set("${VAR}" "${FILEPATH}" PARENT_SCOPE)
 | 
			
		||||
    if (IS_ABSOLUTE "${FILEPATH}")
 | 
			
		||||
        file(RELATIVE_PATH RPATH "${ROOT}" "${FILEPATH}")
 | 
			
		||||
        if (NOT IS_ABSOLUTE "${RPATH}")
 | 
			
		||||
            set("${VAR}" "${RPATH}" PARENT_SCOPE)
 | 
			
		||||
        endif()
 | 
			
		||||
    endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_join_path VAR DIR1 DIR2)
 | 
			
		||||
    if ("${DIR2}" MATCHES "^(/|~|.:/).*$" OR "${DIR1}" STREQUAL "")
 | 
			
		||||
        set("${VAR}" "${DIR2}" PARENT_SCOPE)
 | 
			
		||||
    else()
 | 
			
		||||
        set("${VAR}" "${DIR1}/${DIR2}" PARENT_SCOPE)
 | 
			
		||||
    endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
macro (pvs_studio_append_flags_from_property CXX C DIR PREFIX)
 | 
			
		||||
    if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND")
 | 
			
		||||
        foreach (PROP ${PROPERTY})
 | 
			
		||||
            pvs_studio_join_path(PROP "${DIR}" "${PROP}")
 | 
			
		||||
 | 
			
		||||
            if (APPLE AND "${PREFIX}" STREQUAL "-I" AND IS_ABSOLUTE "${PROP}" AND "${PROP}" MATCHES "\\.framework$")
 | 
			
		||||
                get_filename_component(FRAMEWORK "${PROP}" DIRECTORY)
 | 
			
		||||
                list(APPEND "${CXX}" "-iframework")
 | 
			
		||||
                list(APPEND "${CXX}" "${FRAMEWORK}")
 | 
			
		||||
                list(APPEND "${C}" "-iframework")
 | 
			
		||||
                list(APPEND "${C}" "${FRAMEWORK}")
 | 
			
		||||
                pvs_studio_log("framework: ${FRAMEWORK}")
 | 
			
		||||
            elseif (NOT "${PROP}" STREQUAL "")
 | 
			
		||||
                list(APPEND "${CXX}" "${PREFIX}${PROP}")
 | 
			
		||||
                list(APPEND "${C}" "${PREFIX}${PROP}")
 | 
			
		||||
            endif()
 | 
			
		||||
        endforeach()
 | 
			
		||||
    endif()
 | 
			
		||||
endmacro()
 | 
			
		||||
 | 
			
		||||
macro (pvs_studio_append_standard_flag FLAGS STANDARD)
 | 
			
		||||
    if ("${STANDARD}" MATCHES "^(99|11|14|17|20)$")
 | 
			
		||||
        if ("${PVS_STUDIO_PREPROCESSOR}" MATCHES "gcc|clang")
 | 
			
		||||
            list(APPEND "${FLAGS}" "-std=c++${STANDARD}")
 | 
			
		||||
        endif()
 | 
			
		||||
    endif()
 | 
			
		||||
endmacro()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_set_directory_flags DIRECTORY CXX C)
 | 
			
		||||
    set(CXX_FLAGS "${${CXX}}")
 | 
			
		||||
    set(C_FLAGS "${${C}}")
 | 
			
		||||
 | 
			
		||||
    get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" INCLUDE_DIRECTORIES)
 | 
			
		||||
    pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "${DIRECTORY}" "-I")
 | 
			
		||||
 | 
			
		||||
    get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" COMPILE_DEFINITIONS)
 | 
			
		||||
    pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "" "-D")
 | 
			
		||||
 | 
			
		||||
    set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE)
 | 
			
		||||
    set("${C}" "${C_FLAGS}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_set_target_flags TARGET CXX C)
 | 
			
		||||
    set(CXX_FLAGS "${${CXX}}")
 | 
			
		||||
    set(C_FLAGS "${${C}}")
 | 
			
		||||
 | 
			
		||||
    if (NOT MSVC)
 | 
			
		||||
        list(APPEND CXX_FLAGS "$<$<BOOL:${CMAKE_SYSROOT}>:--sysroot=${CMAKE_SYSROOT}>")
 | 
			
		||||
        list(APPEND C_FLAGS "$<$<BOOL:${CMAKE_SYSROOT}>:--sysroot=${CMAKE_SYSROOT}>")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    set(prop_incdirs "$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>")
 | 
			
		||||
    list(APPEND CXX_FLAGS "$<$<BOOL:${prop_incdirs}>:-I$<JOIN:${prop_incdirs},$<SEMICOLON>-I>>")
 | 
			
		||||
    list(APPEND C_FLAGS "$<$<BOOL:${prop_incdirs}>:-I$<JOIN:${prop_incdirs},$<SEMICOLON>-I>>")
 | 
			
		||||
 | 
			
		||||
    set(prop_compdefs "$<TARGET_PROPERTY:${TARGET},COMPILE_DEFINITIONS>")
 | 
			
		||||
    list(APPEND CXX_FLAGS "$<$<BOOL:${prop_compdefs}>:-D$<JOIN:${prop_compdefs},$<SEMICOLON>-D>>")
 | 
			
		||||
    list(APPEND C_FLAGS "$<$<BOOL:${prop_compdefs}>:-D$<JOIN:${prop_compdefs},$<SEMICOLON>-D>>")
 | 
			
		||||
 | 
			
		||||
    set(prop_compopt "$<TARGET_PROPERTY:${TARGET},COMPILE_OPTIONS>")
 | 
			
		||||
    list(APPEND CXX_FLAGS "$<$<BOOL:${prop_compopt}>:$<JOIN:${prop_compopt},$<SEMICOLON>>>")
 | 
			
		||||
    list(APPEND C_FLAGS "$<$<BOOL:${prop_compopt}>:$<JOIN:${prop_compopt},$<SEMICOLON>>>")
 | 
			
		||||
 | 
			
		||||
    set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE)
 | 
			
		||||
    set("${C}" "${C_FLAGS}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_set_source_file_flags SOURCE)
 | 
			
		||||
    set(LANGUAGE "")
 | 
			
		||||
 | 
			
		||||
    string(TOLOWER "${SOURCE}" SOURCE_LOWER)
 | 
			
		||||
    if ("${LANGUAGE}" STREQUAL "" AND "${SOURCE_LOWER}" MATCHES "^.*\\.(c|cpp|cc|cx|cxx|cp|c\\+\\+)$")
 | 
			
		||||
        if ("${SOURCE}" MATCHES "^.*\\.c$")
 | 
			
		||||
            set(LANGUAGE C)
 | 
			
		||||
        else()
 | 
			
		||||
            set(LANGUAGE CXX)
 | 
			
		||||
        endif()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if ("${LANGUAGE}" STREQUAL "C")
 | 
			
		||||
        set(CL_PARAMS ${PVS_STUDIO_C_FLAGS} ${PVS_STUDIO_TARGET_C_FLAGS} -DPVS_STUDIO)
 | 
			
		||||
    elseif ("${LANGUAGE}" STREQUAL "CXX")
 | 
			
		||||
        set(CL_PARAMS ${PVS_STUDIO_CXX_FLAGS} ${PVS_STUDIO_TARGET_CXX_FLAGS} -DPVS_STUDIO)
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    set(PVS_STUDIO_LANGUAGE "${LANGUAGE}" PARENT_SCOPE)
 | 
			
		||||
    set(PVS_STUDIO_CL_PARAMS "${CL_PARAMS}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_analyze_file SOURCE SOURCE_DIR BINARY_DIR)
 | 
			
		||||
    set(PLOGS ${PVS_STUDIO_PLOGS})
 | 
			
		||||
    pvs_studio_set_source_file_flags("${SOURCE}")
 | 
			
		||||
 | 
			
		||||
    get_filename_component(SOURCE "${SOURCE}" REALPATH)
 | 
			
		||||
 | 
			
		||||
    get_source_file_property(PROPERTY "${SOURCE}" HEADER_FILE_ONLY)
 | 
			
		||||
    if (PROPERTY)
 | 
			
		||||
        return()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    pvs_studio_relative_path(SOURCE_RELATIVE "${SOURCE_DIR}" "${SOURCE}")
 | 
			
		||||
    pvs_studio_join_path(SOURCE "${SOURCE_DIR}" "${SOURCE}")
 | 
			
		||||
 | 
			
		||||
    set(LOG "${BINARY_DIR}/PVS-Studio/${SOURCE_RELATIVE}.plog")
 | 
			
		||||
    get_filename_component(LOG "${LOG}" REALPATH)
 | 
			
		||||
    get_filename_component(PARENT_DIR "${LOG}" DIRECTORY)
 | 
			
		||||
 | 
			
		||||
    if (EXISTS "${SOURCE}" AND NOT TARGET "${LOG}" AND NOT "${PVS_STUDIO_LANGUAGE}" STREQUAL "")
 | 
			
		||||
        # A workaround to support implicit dependencies for ninja generators.
 | 
			
		||||
        set(depPvsArg)
 | 
			
		||||
        set(depCommandArg)
 | 
			
		||||
        if (CMAKE_VERSION VERSION_GREATER 3.6 AND "${CMAKE_GENERATOR}" STREQUAL "Ninja")
 | 
			
		||||
            pvs_studio_relative_path(relLog "${CMAKE_BINARY_DIR}" "${LOG}")
 | 
			
		||||
            set(depPvsArg --dep-file "${LOG}.d" --dep-file-target "${relLog}")
 | 
			
		||||
            set(depCommandArg DEPFILE "${LOG}.d")
 | 
			
		||||
        endif()
 | 
			
		||||
 | 
			
		||||
        # https://public.kitware.com/Bug/print_bug_page.php?bug_id=14353
 | 
			
		||||
        # https://public.kitware.com/Bug/file/5436/expand_command.cmake
 | 
			
		||||
        #
 | 
			
		||||
        # It is a workaround to expand generator expressions.
 | 
			
		||||
        set(cmdline "${PVS_STUDIO_BIN}" analyze
 | 
			
		||||
                    --output-file "${LOG}"
 | 
			
		||||
                    --source-file "${SOURCE}"
 | 
			
		||||
                    ${depPvsArg}
 | 
			
		||||
                    ${PVS_STUDIO_ARGS}
 | 
			
		||||
                    --cl-params "${PVS_STUDIO_CL_PARAMS}" "${SOURCE}")
 | 
			
		||||
 | 
			
		||||
        string(REPLACE ";" "$<SEMICOLON>" cmdline "${cmdline}")
 | 
			
		||||
        set(pvscmd "${CMAKE_COMMAND}"
 | 
			
		||||
                   -D "PVS_STUDIO_AS_SCRIPT=TRUE"
 | 
			
		||||
                   -D "PVS_STUDIO_COMMAND=${cmdline}"
 | 
			
		||||
                   -D "PVS_STUDIO_LOG_FILE=${LOG}"
 | 
			
		||||
                   -P "${PVS_STUDIO_SCRIPT}")
 | 
			
		||||
 | 
			
		||||
        add_custom_command(OUTPUT "${LOG}"
 | 
			
		||||
                           COMMAND "${CMAKE_COMMAND}" -E make_directory "${PARENT_DIR}"
 | 
			
		||||
                           COMMAND "${CMAKE_COMMAND}" -E remove_directory "${LOG}"
 | 
			
		||||
                           COMMAND ${pvscmd}
 | 
			
		||||
                           WORKING_DIRECTORY "${BINARY_DIR}"
 | 
			
		||||
                           DEPENDS "${SOURCE}" "${PVS_STUDIO_SUPPRESS_BASE}" "${PVS_STUDIO_DEPENDS}"
 | 
			
		||||
                           IMPLICIT_DEPENDS "${PVS_STUDIO_LANGUAGE}" "${SOURCE}"
 | 
			
		||||
                           ${depCommandArg}
 | 
			
		||||
                           VERBATIM
 | 
			
		||||
                           COMMENT "Analyzing ${PVS_STUDIO_LANGUAGE} file ${SOURCE_RELATIVE}")
 | 
			
		||||
        list(APPEND PLOGS "${LOG}")
 | 
			
		||||
    endif()
 | 
			
		||||
    set(PVS_STUDIO_PLOGS "${PLOGS}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function (pvs_studio_analyze_target TARGET DIR)
 | 
			
		||||
    set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}")
 | 
			
		||||
    set(PVS_STUDIO_TARGET_CXX_FLAGS "")
 | 
			
		||||
    set(PVS_STUDIO_TARGET_C_FLAGS "")
 | 
			
		||||
 | 
			
		||||
    get_target_property(PROPERTY "${TARGET}" SOURCES)
 | 
			
		||||
    pvs_studio_relative_path(BINARY_DIR "${CMAKE_SOURCE_DIR}" "${DIR}")
 | 
			
		||||
    if ("${BINARY_DIR}" MATCHES "^/.*$")
 | 
			
		||||
        pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "PVS-Studio/__${BINARY_DIR}")
 | 
			
		||||
    else()
 | 
			
		||||
        pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "${BINARY_DIR}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    file(MAKE_DIRECTORY "${BINARY_DIR}")
 | 
			
		||||
 | 
			
		||||
    pvs_studio_set_directory_flags("${DIR}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS)
 | 
			
		||||
    pvs_studio_set_target_flags("${TARGET}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS)
 | 
			
		||||
 | 
			
		||||
    if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND")
 | 
			
		||||
        foreach (SOURCE ${PROPERTY})
 | 
			
		||||
            pvs_studio_join_path(SOURCE "${DIR}" "${SOURCE}")
 | 
			
		||||
            pvs_studio_analyze_file("${SOURCE}" "${DIR}" "${BINARY_DIR}")
 | 
			
		||||
        endforeach()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
set(PVS_STUDIO_RECURSIVE_TARGETS)
 | 
			
		||||
set(PVS_STUDIO_RECURSIVE_TARGETS_NEW)
 | 
			
		||||
 | 
			
		||||
macro(pvs_studio_get_recursive_targets TARGET)
 | 
			
		||||
    get_target_property(libs "${TARGET}" LINK_LIBRARIES)
 | 
			
		||||
    foreach (lib IN LISTS libs)
 | 
			
		||||
        list(FIND PVS_STUDIO_RECURSIVE_TARGETS "${lib}" index)
 | 
			
		||||
        if (TARGET "${lib}" AND "${index}" STREQUAL -1)
 | 
			
		||||
            get_target_property(target_type "${lib}" TYPE)
 | 
			
		||||
            if (NOT "${target_type}" STREQUAL "INTERFACE_LIBRARY")
 | 
			
		||||
                list(APPEND PVS_STUDIO_RECURSIVE_TARGETS "${lib}")
 | 
			
		||||
                list(APPEND PVS_STUDIO_RECURSIVE_TARGETS_NEW "${lib}")
 | 
			
		||||
                pvs_studio_get_recursive_targets("${lib}")
 | 
			
		||||
            endif()
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
endmacro()
 | 
			
		||||
 | 
			
		||||
option(PVS_STUDIO_DISABLE OFF "Disable PVS-Studio targets")
 | 
			
		||||
option(PVS_STUDIO_DEBUG OFF "Add debug info")
 | 
			
		||||
 | 
			
		||||
# pvs_studio_add_target
 | 
			
		||||
# Target options:
 | 
			
		||||
# ALL                           add PVS-Studio target to default build (default: off)
 | 
			
		||||
# TARGET target                 name of analysis target (default: pvs)
 | 
			
		||||
# ANALYZE targets...            targets to analyze
 | 
			
		||||
# RECURSIVE                     analyze target's dependencies (requires CMake 3.5+)
 | 
			
		||||
# COMPILE_COMMANDS              use compile_commands.json instead of targets (specified by the 'ANALYZE' option) to determine files for analysis
 | 
			
		||||
#                               (set CMAKE_EXPORT_COMPILE_COMMANDS, available only for Makefile and Ninja generators)
 | 
			
		||||
#
 | 
			
		||||
# Output options:
 | 
			
		||||
# OUTPUT                        prints report to stdout
 | 
			
		||||
# LOG path                      path to report (default: ${CMAKE_CURRENT_BINARY_DIR}/PVS-Studio.log)
 | 
			
		||||
# FORMAT format                 format of report
 | 
			
		||||
# MODE mode                     analyzers/levels filter (default: GA:1,2)
 | 
			
		||||
# HIDE_HELP                     do not print help message
 | 
			
		||||
#
 | 
			
		||||
# Analyzer options:
 | 
			
		||||
# PLATFORM name                 linux32/linux64 (default: linux64)
 | 
			
		||||
# PREPROCESSOR name             preprocessor type: gcc/clang (default: auto detected)
 | 
			
		||||
# LICENSE path                  path to PVS-Studio.lic (default: ~/.config/PVS-Studio/PVS-Studio.lic)
 | 
			
		||||
# CONFIG path                   path to PVS-Studio.cfg
 | 
			
		||||
# CFG_TEXT text                 embedded PVS-Studio.cfg
 | 
			
		||||
# SUPPRESS_BASE                 path to suppress base file
 | 
			
		||||
# KEEP_COMBINED_PLOG            do not delete combined plog file *.pvs.raw for further processing with plog-converter
 | 
			
		||||
#
 | 
			
		||||
# Misc options:
 | 
			
		||||
# DEPENDS targets..             additional target dependencies
 | 
			
		||||
# SOURCES path...               list of source files to analyze
 | 
			
		||||
# BIN path                      path to pvs-studio-analyzer (Unix) or CompilerCommandsAnalyzer.exe (Windows)
 | 
			
		||||
# CONVERTER path                path to plog-converter (Unix) or HtmlGenerator.exe (Windows)
 | 
			
		||||
# C_FLAGS flags...              additional C_FLAGS
 | 
			
		||||
# CXX_FLAGS flags...            additional CXX_FLAGS
 | 
			
		||||
# ARGS args...                  additional pvs-studio-analyzer/CompilerCommandsAnalyzer.exe flags
 | 
			
		||||
# CONVERTER_ARGS args...        additional plog-converter/HtmlGenerator.exe flags
 | 
			
		||||
function (pvs_studio_add_target)
 | 
			
		||||
    macro (default VAR VALUE)
 | 
			
		||||
        if ("${${VAR}}" STREQUAL "")
 | 
			
		||||
            set("${VAR}" "${VALUE}")
 | 
			
		||||
        endif()
 | 
			
		||||
    endmacro()
 | 
			
		||||
 | 
			
		||||
    set(PVS_STUDIO_SUPPORTED_PREPROCESSORS "gcc|clang|visualcpp")
 | 
			
		||||
    if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
 | 
			
		||||
        set(DEFAULT_PREPROCESSOR "clang")
 | 
			
		||||
    elseif (MSVC)
 | 
			
		||||
        set(DEFAULT_PREPROCESSOR "visualcpp")
 | 
			
		||||
    else()
 | 
			
		||||
        set(DEFAULT_PREPROCESSOR "gcc")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    set(OPTIONAL OUTPUT ALL RECURSIVE HIDE_HELP KEEP_COMBINED_PLOG COMPILE_COMMANDS KEEP_INTERMEDIATE_FILES)
 | 
			
		||||
    set(SINGLE LICENSE CONFIG TARGET LOG FORMAT BIN CONVERTER PLATFORM PREPROCESSOR CFG_TEXT SUPPRESS_BASE)
 | 
			
		||||
    set(MULTI SOURCES C_FLAGS CXX_FLAGS ARGS DEPENDS ANALYZE MODE CONVERTER_ARGS)
 | 
			
		||||
    cmake_parse_arguments(PVS_STUDIO "${OPTIONAL}" "${SINGLE}" "${MULTI}" ${ARGN})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    default(PVS_STUDIO_C_FLAGS "")
 | 
			
		||||
    default(PVS_STUDIO_CXX_FLAGS "")
 | 
			
		||||
    default(PVS_STUDIO_TARGET "pvs")
 | 
			
		||||
    default(PVS_STUDIO_LOG "PVS-Studio.log")
 | 
			
		||||
 | 
			
		||||
    set(PATHS)
 | 
			
		||||
 | 
			
		||||
    if (WIN32)
 | 
			
		||||
        # The registry value is only read when you do some cache operation on it.
 | 
			
		||||
        # https://stackoverflow.com/questions/1762201/reading-registry-values-with-cmake
 | 
			
		||||
        GET_FILENAME_COMPONENT(ROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\ProgramVerificationSystems\\PVS-Studio;installDir]" ABSOLUTE CACHE)
 | 
			
		||||
 | 
			
		||||
        if (EXISTS "${ROOT}")
 | 
			
		||||
           set(PATHS "${ROOT}")
 | 
			
		||||
        else()
 | 
			
		||||
           set(ROOT "PROGRAMFILES(X86)")
 | 
			
		||||
           set(ROOT "$ENV{${ROOT}}/PVS-Studio")
 | 
			
		||||
           string(REPLACE \\ / ROOT "${ROOT}")
 | 
			
		||||
 | 
			
		||||
           if (EXISTS "${ROOT}")
 | 
			
		||||
              set(PATHS "${ROOT}")
 | 
			
		||||
            else()
 | 
			
		||||
              set(ROOT "PATH")
 | 
			
		||||
              set(ROOT "$ENV{${ROOT}}")
 | 
			
		||||
              set(PATHS "${ROOT}")
 | 
			
		||||
           endif()
 | 
			
		||||
        endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        default(PVS_STUDIO_BIN "CompilerCommandsAnalyzer.exe")
 | 
			
		||||
        default(PVS_STUDIO_CONVERTER "HtmlGenerator.exe")
 | 
			
		||||
    else()
 | 
			
		||||
        default(PVS_STUDIO_BIN "pvs-studio-analyzer")
 | 
			
		||||
        default(PVS_STUDIO_CONVERTER "plog-converter")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    find_program(PVS_STUDIO_BIN_PATH "${PVS_STUDIO_BIN}" ${PATHS})
 | 
			
		||||
    set(PVS_STUDIO_BIN "${PVS_STUDIO_BIN_PATH}")
 | 
			
		||||
 | 
			
		||||
    if (NOT EXISTS "${PVS_STUDIO_BIN}")
 | 
			
		||||
        message(FATAL_ERROR "pvs-studio-analyzer is not found")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    find_program(PVS_STUDIO_CONVERTER_PATH "${PVS_STUDIO_CONVERTER}" ${PATHS})
 | 
			
		||||
    set(PVS_STUDIO_CONVERTER "${PVS_STUDIO_CONVERTER_PATH}")
 | 
			
		||||
 | 
			
		||||
    if (NOT EXISTS "${PVS_STUDIO_CONVERTER}")
 | 
			
		||||
        message(FATAL_ERROR "plog-converter is not found")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    default(PVS_STUDIO_MODE "GA:1,2")
 | 
			
		||||
    default(PVS_STUDIO_PREPROCESSOR "${DEFAULT_PREPROCESSOR}")
 | 
			
		||||
    if (WIN32)
 | 
			
		||||
        default(PVS_STUDIO_PLATFORM "x64")
 | 
			
		||||
    else()
 | 
			
		||||
        default(PVS_STUDIO_PLATFORM "linux64")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    string(REPLACE ";" "+" PVS_STUDIO_MODE "${PVS_STUDIO_MODE}")
 | 
			
		||||
 | 
			
		||||
    if ("${PVS_STUDIO_CONFIG}" STREQUAL "" AND NOT "${PVS_STUDIO_CFG_TEXT}" STREQUAL "")
 | 
			
		||||
        set(PVS_STUDIO_CONFIG "${CMAKE_BINARY_DIR}/PVS-Studio.cfg")
 | 
			
		||||
 | 
			
		||||
        set(PVS_STUDIO_CONFIG_COMMAND "${CMAKE_COMMAND}" -E echo "${PVS_STUDIO_CFG_TEXT}" > "${PVS_STUDIO_CONFIG}")
 | 
			
		||||
 | 
			
		||||
        add_custom_command(OUTPUT "${PVS_STUDIO_CONFIG}"
 | 
			
		||||
                           COMMAND ${PVS_STUDIO_CONFIG_COMMAND}
 | 
			
		||||
                           WORKING_DIRECTORY "${BINARY_DIR}"
 | 
			
		||||
                           COMMENT "Generating PVS-Studio.cfg")
 | 
			
		||||
 | 
			
		||||
        list(APPEND PVS_STUDIO_DEPENDS "${PVS_STUDIO_CONFIG}")
 | 
			
		||||
    endif()
 | 
			
		||||
    if (NOT "${PVS_STUDIO_PREPROCESSOR}" MATCHES "^${PVS_STUDIO_SUPPORTED_PREPROCESSORS}$")
 | 
			
		||||
        message(FATAL_ERROR "Preprocessor ${PVS_STUDIO_PREPROCESSOR} isn't supported. Available options: ${PVS_STUDIO_SUPPORTED_PREPROCESSORS}.")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    pvs_studio_append_standard_flag(PVS_STUDIO_CXX_FLAGS "${CMAKE_CXX_STANDARD}")
 | 
			
		||||
    pvs_studio_set_directory_flags("${CMAKE_CURRENT_SOURCE_DIR}" PVS_STUDIO_CXX_FLAGS PVS_STUDIO_C_FLAGS)
 | 
			
		||||
 | 
			
		||||
    if (NOT "${PVS_STUDIO_LICENSE}" STREQUAL "")
 | 
			
		||||
        list(APPEND PVS_STUDIO_ARGS --lic-file "${PVS_STUDIO_LICENSE}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (NOT ${PVS_STUDIO_CONFIG} STREQUAL "")
 | 
			
		||||
        list(APPEND PVS_STUDIO_ARGS --cfg "${PVS_STUDIO_CONFIG}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    list(APPEND PVS_STUDIO_ARGS --platform "${PVS_STUDIO_PLATFORM}"
 | 
			
		||||
                                --preprocessor "${PVS_STUDIO_PREPROCESSOR}")
 | 
			
		||||
 | 
			
		||||
    if (NOT "${PVS_STUDIO_SUPPRESS_BASE}" STREQUAL "")
 | 
			
		||||
        pvs_studio_join_path(PVS_STUDIO_SUPPRESS_BASE "${CMAKE_CURRENT_SOURCE_DIR}" "${PVS_STUDIO_SUPPRESS_BASE}")
 | 
			
		||||
        list(APPEND PVS_STUDIO_ARGS --suppress-file "${PVS_STUDIO_SUPPRESS_BASE}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (NOT "${CMAKE_CXX_COMPILER}" STREQUAL "")
 | 
			
		||||
        list(APPEND PVS_STUDIO_ARGS --cxx "${CMAKE_CXX_COMPILER}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (NOT "${CMAKE_C_COMPILER}" STREQUAL "")
 | 
			
		||||
        list(APPEND PVS_STUDIO_ARGS --cc "${CMAKE_C_COMPILER}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (PVS_STUDIO_KEEP_INTERMEDIATE_FILES)
 | 
			
		||||
        list(APPEND PVS_STUDIO_ARGS --dump-files)
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    string(REGEX REPLACE [123,:] "" ANALYZER_MODE ${PVS_STUDIO_MODE})
 | 
			
		||||
    if (NOT "$ANALYZER_MODE" STREQUAL "GA")
 | 
			
		||||
        list (APPEND PVS_STUDIO_ARGS -a "${ANALYZER_MODE}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    set(PVS_STUDIO_PLOGS "")
 | 
			
		||||
 | 
			
		||||
    set(PVS_STUDIO_RECURSIVE_TARGETS_NEW)
 | 
			
		||||
    if (${PVS_STUDIO_RECURSIVE})
 | 
			
		||||
        foreach (TARGET IN LISTS PVS_STUDIO_ANALYZE)
 | 
			
		||||
            list(APPEND PVS_STUDIO_RECURSIVE_TARGETS_NEW "${TARGET}")
 | 
			
		||||
            pvs_studio_get_recursive_targets("${TARGET}")
 | 
			
		||||
        endforeach()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    set(inc_path)
 | 
			
		||||
 | 
			
		||||
    foreach (TARGET ${PVS_STUDIO_ANALYZE})
 | 
			
		||||
        set(DIR "${CMAKE_CURRENT_SOURCE_DIR}")
 | 
			
		||||
        string(FIND "${TARGET}" ":" DELIM)
 | 
			
		||||
        if ("${DELIM}" GREATER "-1")
 | 
			
		||||
            math(EXPR DELIMI "${DELIM}+1")
 | 
			
		||||
            string(SUBSTRING "${TARGET}" "${DELIMI}" "-1" DIR)
 | 
			
		||||
            string(SUBSTRING "${TARGET}" "0" "${DELIM}" TARGET)
 | 
			
		||||
            pvs_studio_join_path(DIR "${CMAKE_CURRENT_SOURCE_DIR}" "${DIR}")
 | 
			
		||||
        else()
 | 
			
		||||
            get_target_property(TARGET_SOURCE_DIR "${TARGET}" SOURCE_DIR)
 | 
			
		||||
            if (EXISTS "${TARGET_SOURCE_DIR}")
 | 
			
		||||
                set(DIR "${TARGET_SOURCE_DIR}")
 | 
			
		||||
            endif()
 | 
			
		||||
        endif()
 | 
			
		||||
        pvs_studio_analyze_target("${TARGET}" "${DIR}")
 | 
			
		||||
        list(APPEND PVS_STUDIO_DEPENDS "${TARGET}")
 | 
			
		||||
 | 
			
		||||
        if ("${inc_path}" STREQUAL "")
 | 
			
		||||
            set(inc_path "$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>")
 | 
			
		||||
        else()
 | 
			
		||||
            set(inc_path "${inc_path}$<SEMICOLON>$<TARGET_PROPERTY:${TARGET},INCLUDE_DIRECTORIES>")
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    foreach (TARGET ${PVS_STUDIO_RECURSIVE_TARGETS_NEW})
 | 
			
		||||
        set(DIR "${CMAKE_CURRENT_SOURCE_DIR}")
 | 
			
		||||
        get_target_property(TARGET_SOURCE_DIR "${TARGET}" SOURCE_DIR)
 | 
			
		||||
        if (EXISTS "${TARGET_SOURCE_DIR}")
 | 
			
		||||
            set(DIR "${TARGET_SOURCE_DIR}")
 | 
			
		||||
        endif()
 | 
			
		||||
        pvs_studio_analyze_target("${TARGET}" "${DIR}")
 | 
			
		||||
        list(APPEND PVS_STUDIO_DEPENDS "${TARGET}")
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    set(PVS_STUDIO_TARGET_CXX_FLAGS "")
 | 
			
		||||
    set(PVS_STUDIO_TARGET_C_FLAGS "")
 | 
			
		||||
    foreach (SOURCE ${PVS_STUDIO_SOURCES})
 | 
			
		||||
        pvs_studio_analyze_file("${SOURCE}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    if (PVS_STUDIO_COMPILE_COMMANDS)
 | 
			
		||||
        set(COMPILE_COMMANDS_LOG "${PVS_STUDIO_LOG}.pvs.analyzer.raw")
 | 
			
		||||
        if (NOT CMAKE_EXPORT_COMPILE_COMMANDS)
 | 
			
		||||
            message(FATAL_ERROR "You should set CMAKE_EXPORT_COMPILE_COMMANDS to TRUE")
 | 
			
		||||
        endif()
 | 
			
		||||
        add_custom_command(
 | 
			
		||||
            OUTPUT "${COMPILE_COMMANDS_LOG}"
 | 
			
		||||
            COMMAND "${PVS_STUDIO_BIN}" analyze -i
 | 
			
		||||
                    --output-file "${COMPILE_COMMANDS_LOG}.always"
 | 
			
		||||
                    ${PVS_STUDIO_ARGS}
 | 
			
		||||
            COMMENT "Analyzing with PVS-Studio"
 | 
			
		||||
            WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
 | 
			
		||||
            DEPENDS "${PVS_STUDIO_SUPPRESS_BASE}" "${PVS_STUDIO_DEPENDS}"
 | 
			
		||||
        )
 | 
			
		||||
        list(APPEND PVS_STUDIO_PLOGS_LOGS "${COMPILE_COMMANDS_LOG}.always")
 | 
			
		||||
        list(APPEND PVS_STUDIO_PLOGS_DEPENDENCIES "${COMPILE_COMMANDS_LOG}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    pvs_studio_relative_path(LOG_RELATIVE "${CMAKE_BINARY_DIR}" "${PVS_STUDIO_LOG}")
 | 
			
		||||
    if (PVS_STUDIO_PLOGS OR PVS_STUDIO_COMPILE_COMMANDS)
 | 
			
		||||
        if (WIN32)
 | 
			
		||||
            string(REPLACE / \\ PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}")
 | 
			
		||||
        endif()
 | 
			
		||||
        if (WIN32)
 | 
			
		||||
            set(COMMANDS COMMAND type ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_LOGS} > "${PVS_STUDIO_LOG}" 2>nul || cd .)
 | 
			
		||||
        else()
 | 
			
		||||
            set(COMMANDS COMMAND cat ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_LOGS} > "${PVS_STUDIO_LOG}" 2>/dev/null || true)
 | 
			
		||||
        endif()
 | 
			
		||||
        set(COMMENT "Generating ${LOG_RELATIVE}")
 | 
			
		||||
        if (NOT "${PVS_STUDIO_FORMAT}" STREQUAL "" OR PVS_STUDIO_OUTPUT)
 | 
			
		||||
            if ("${PVS_STUDIO_FORMAT}" STREQUAL "")
 | 
			
		||||
                set(PVS_STUDIO_FORMAT "errorfile")
 | 
			
		||||
            endif()
 | 
			
		||||
            if (PVS_STUDIO_HIDE_HELP)
 | 
			
		||||
              set(PVS_STUDIO_CONVERTER_ARGS ${PVS_STUDIO_CONVERTER_ARGS} --noHelpMessages)
 | 
			
		||||
            endif()
 | 
			
		||||
            if (PVS_STUDIO_OUTPUT)
 | 
			
		||||
              set(PVS_STUDIO_CONVERTER_ARGS ${PVS_STUDIO_CONVERTER_ARGS} --stdout)
 | 
			
		||||
            endif()
 | 
			
		||||
            list(APPEND COMMANDS
 | 
			
		||||
                 COMMAND "${CMAKE_COMMAND}" -E remove -f "${PVS_STUDIO_LOG}.pvs.raw"
 | 
			
		||||
                 COMMAND "${CMAKE_COMMAND}" -E rename "${PVS_STUDIO_LOG}" "${PVS_STUDIO_LOG}.pvs.raw"
 | 
			
		||||
                 COMMAND "${PVS_STUDIO_CONVERTER}" "${PVS_STUDIO_CONVERTER_ARGS}" -t "${PVS_STUDIO_FORMAT}" "${PVS_STUDIO_LOG}.pvs.raw" -o "${PVS_STUDIO_LOG}" -a "${PVS_STUDIO_MODE}")
 | 
			
		||||
            if (NOT PVS_STUDIO_KEEP_COMBINED_PLOG)
 | 
			
		||||
                list(APPEND COMMANDS COMMAND "${CMAKE_COMMAND}" -E remove -f "${PVS_STUDIO_LOG}.pvs.raw")
 | 
			
		||||
            endif()
 | 
			
		||||
        endif()
 | 
			
		||||
    else()
 | 
			
		||||
        set(COMMANDS COMMAND "${CMAKE_COMMAND}" -E touch "${PVS_STUDIO_LOG}")
 | 
			
		||||
        set(COMMENT "Generating ${LOG_RELATIVE}: no sources found")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (WIN32)
 | 
			
		||||
        string(REPLACE / \\ PVS_STUDIO_LOG "${PVS_STUDIO_LOG}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
 | 
			
		||||
        get_filename_component(LOG_NAME ${LOG_RELATIVE} NAME)
 | 
			
		||||
        set(LOG_TARGET "${PVS_STUDIO_TARGET}-${LOG_NAME}-log")
 | 
			
		||||
        add_custom_target("${LOG_TARGET}"
 | 
			
		||||
                          BYPRODUCTS "${PVS_STUDIO_LOG}"
 | 
			
		||||
                          ${COMMANDS}
 | 
			
		||||
                          COMMENT "${COMMENT}"
 | 
			
		||||
                          DEPENDS ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_DEPENDENCIES}
 | 
			
		||||
                          WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
 | 
			
		||||
    else()
 | 
			
		||||
        set(LOG_TARGET "${PVS_STUDIO_LOG}")
 | 
			
		||||
        add_custom_command(OUTPUT "${LOG_TARGET}"
 | 
			
		||||
                           ${COMMANDS}
 | 
			
		||||
                           COMMENT "${COMMENT}"
 | 
			
		||||
                           DEPENDS ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_DEPENDENCIES}
 | 
			
		||||
                           WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if (PVS_STUDIO_ALL)
 | 
			
		||||
        set(ALL "ALL")
 | 
			
		||||
    else()
 | 
			
		||||
        set(ALL "")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    add_custom_target("${PVS_STUDIO_TARGET}" ${ALL}
 | 
			
		||||
                      WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
 | 
			
		||||
                      DEPENDS ${PVS_STUDIO_DEPENDS} "${LOG_TARGET}")
 | 
			
		||||
 | 
			
		||||
    # A workaround to add implicit dependencies of source files from include directories
 | 
			
		||||
    set_target_properties("${PVS_STUDIO_TARGET}" PROPERTIES INCLUDE_DIRECTORIES "${inc_path}")
 | 
			
		||||
 | 
			
		||||
    if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio")
 | 
			
		||||
        set(props_file "${CMAKE_BINARY_DIR}/${PVS_STUDIO_TARGET}.user.props")
 | 
			
		||||
        file(WRITE "${props_file}" [=[
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
			
		||||
 <ImportGroup Label="PropertySheets">
 | 
			
		||||
  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 | 
			
		||||
 </ImportGroup>
 | 
			
		||||
 <ItemDefinitionGroup>
 | 
			
		||||
  <CustomBuild>
 | 
			
		||||
   <BuildInParallel>true</BuildInParallel>
 | 
			
		||||
  </CustomBuild>
 | 
			
		||||
 </ItemDefinitionGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
]=])
 | 
			
		||||
        set_target_properties("${PVS_STUDIO_TARGET}" PROPERTIES VS_USER_PROPS "${props_file}")
 | 
			
		||||
    endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										45
									
								
								MyxxCMake/sanitizers/FindASan.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								MyxxCMake/sanitizers/FindASan.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault 2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 | 
			
		||||
# associated documentation files (the "Software"), to deal in the Software without restriction,
 | 
			
		||||
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
 | 
			
		||||
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all copies or
 | 
			
		||||
# substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 | 
			
		||||
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 | 
			
		||||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
 | 
			
		||||
# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES
 | 
			
		||||
    # Clang 3.2+ use this version. The no-omit-frame-pointer option is optional.
 | 
			
		||||
    "-g -fsanitize=address -fno-omit-frame-pointer" "-g -fsanitize=address"
 | 
			
		||||
    # Older deprecated flag for ASan
 | 
			
		||||
    "-g -faddress-sanitizer")
 | 
			
		||||
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer" "ASan")
 | 
			
		||||
 | 
			
		||||
find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH})
 | 
			
		||||
mark_as_advanced(ASan_WRAPPER)
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_address TARGET)
 | 
			
		||||
    # TODO: check conditions for target:
 | 
			
		||||
    # if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY))
 | 
			
		||||
    #   message(FATAL_ERROR "AddressSanitizer is not compatible with ThreadSanitizer or MemorySanitizer.")
 | 
			
		||||
    # endif ()
 | 
			
		||||
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "AddressSanitizer" "ASan")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										42
									
								
								MyxxCMake/sanitizers/FindCFI.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								MyxxCMake/sanitizers/FindCFI.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault 2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 | 
			
		||||
# associated documentation files (the "Software"), to deal in the Software without restriction,
 | 
			
		||||
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
 | 
			
		||||
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all copies or
 | 
			
		||||
# substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 | 
			
		||||
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 | 
			
		||||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
 | 
			
		||||
# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_CFI "Enable Control Flow Integrity (CFI) for sanitized targets." OFF)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES
 | 
			
		||||
    # FIXME: Brief comment on why the additional flags
 | 
			
		||||
    # In this case you need a
 | 
			
		||||
    # linker that does optimization at
 | 
			
		||||
    # linking time such as LLVM lld or GNU gold.
 | 
			
		||||
    "-g -fsanitize=cfi -fvisibility=hidden -flto -fuse-ld=lld")
 | 
			
		||||
 | 
			
		||||
# There might be some conflict with the other sanitizer
 | 
			
		||||
# hence it might need an if statement here.
 | 
			
		||||
 | 
			
		||||
# add some handy functions
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ControlFlowIntegrity" "CFI")
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_cfi TARGET)
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "ControlFlowIntegrity" "CFI")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										37
									
								
								MyxxCMake/sanitizers/FindLeakSan.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								MyxxCMake/sanitizers/FindLeakSan.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2019 Barcelona Supercomputing Center
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_LEAK "Enable LeakSanitizer for sanitized targets." Off)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES "-g -fsanitize=leak")
 | 
			
		||||
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "LeakSanitizer" "LeakSan")
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_leak TARGET)
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "LeakSanitizer" "LeakSan")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										49
									
								
								MyxxCMake/sanitizers/FindMSan.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								MyxxCMake/sanitizers/FindMSan.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES "-g -fsanitize=memory")
 | 
			
		||||
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
 | 
			
		||||
    message(NOTICE "MemorySanitizer disabled for target ${TARGET} because "
 | 
			
		||||
            "MemorySanitizer is supported for Linux systems only.")
 | 
			
		||||
elseif(NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
 | 
			
		||||
    message(NOTICE "MemorySanitizer disabled for target ${TARGET} because "
 | 
			
		||||
            "MemorySanitizer is supported for 64bit systems only.")
 | 
			
		||||
else()
 | 
			
		||||
    sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer" "MSan")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_memory TARGET)
 | 
			
		||||
    # TODO: check conditions for target:
 | 
			
		||||
    # if (SANITIZE_MEMORY AND (SANITIZE_THREAD OR SANITIZE_ADDRESS))
 | 
			
		||||
    #   message(FATAL_ERROR "AddressSanitizer is not compatible with ThreadSanitizer or MemorySanitizer.")
 | 
			
		||||
    # endif ()
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "MemorySanitizer" "MSan")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										37
									
								
								MyxxCMake/sanitizers/FindSS.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								MyxxCMake/sanitizers/FindSS.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault 2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 | 
			
		||||
# associated documentation files (the "Software"), to deal in the Software without restriction,
 | 
			
		||||
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
 | 
			
		||||
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all copies or
 | 
			
		||||
# substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 | 
			
		||||
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 | 
			
		||||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
 | 
			
		||||
# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_SS "Enable SafeStack for sanitized targets." OFF)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES "-g -fsanitize=safe-stack")
 | 
			
		||||
 | 
			
		||||
# There might be some conflict with the other sanitizer
 | 
			
		||||
# hence it might need an if statement here.
 | 
			
		||||
 | 
			
		||||
# add some handy functions
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "SafeStack" "SS")
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_ss TARGET)
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "SafeStack" "SS")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										109
									
								
								MyxxCMake/sanitizers/FindSanitizers.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								MyxxCMake/sanitizers/FindSanitizers.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
# If any of the used compiler is a GNU compiler, add a second option to static
 | 
			
		||||
# link against the sanitizers.
 | 
			
		||||
option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off)
 | 
			
		||||
 | 
			
		||||
set(FIND_QUIETLY_FLAG "")
 | 
			
		||||
if(DEFINED Sanitizers_FIND_QUIETLY)
 | 
			
		||||
    set(FIND_QUIETLY_FLAG "QUIET")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
find_package(ASan ${FIND_QUIETLY_FLAG})
 | 
			
		||||
find_package(TSan ${FIND_QUIETLY_FLAG})
 | 
			
		||||
find_package(MSan ${FIND_QUIETLY_FLAG})
 | 
			
		||||
find_package(UBSan ${FIND_QUIETLY_FLAG})
 | 
			
		||||
find_package(LeakSan ${FIND_QUIETLY_FLAG})
 | 
			
		||||
find_package(CFI ${FIND_QUIETLY_FLAG})
 | 
			
		||||
find_package(SS ${FIND_QUIETLY_FLAG})
 | 
			
		||||
 | 
			
		||||
function(sanitizer_add_blacklist_file FILE)
 | 
			
		||||
    if(NOT IS_ABSOLUTE ${FILE})
 | 
			
		||||
        set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}")
 | 
			
		||||
    endif()
 | 
			
		||||
    get_filename_component(FILE "${FILE}" REALPATH)
 | 
			
		||||
 | 
			
		||||
    sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}" "SanitizerBlacklist" "SanBlist")
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
function(add_sanitizers ...)
 | 
			
		||||
    # If no sanitizer is enabled, return immediately.
 | 
			
		||||
    if(NOT
 | 
			
		||||
       (SANITIZE_ADDRESS
 | 
			
		||||
        OR SANITIZE_MEMORY
 | 
			
		||||
        OR SANITIZE_THREAD
 | 
			
		||||
        OR SANITIZE_UNDEFINED
 | 
			
		||||
        OR SANITIZE_LEAK
 | 
			
		||||
        OR SANITIZE_CFI
 | 
			
		||||
        OR SANITIZE_SS))
 | 
			
		||||
        message(STATUS "No sanitizer selected.")
 | 
			
		||||
        return()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if(SANITIZE_ADDRESS AND SANITIZE_THREAD)
 | 
			
		||||
        message(
 | 
			
		||||
            FATAL_ERROR
 | 
			
		||||
                "Incompatible Sanitizer combination enabled: AddressSanitizer, ThreadSanitizer")
 | 
			
		||||
    endif()
 | 
			
		||||
    if(SANITIZE_ADDRESS AND SANITIZE_MEMORY)
 | 
			
		||||
        message(
 | 
			
		||||
            FATAL_ERROR
 | 
			
		||||
                "Incompatible Sanitizer combination enabled: AddressSanitizer, MemorySanitizer")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if(SANITIZE_MEMORY AND SANITIZE_THREAD)
 | 
			
		||||
        message(
 | 
			
		||||
            FATAL_ERROR
 | 
			
		||||
                "Incompatible Sanitizer combination enabled: MemorySanitizer, ThreadSanitizer")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    foreach(TARGET ${ARGV})
 | 
			
		||||
        sanitizer_check_target(${TARGET})
 | 
			
		||||
 | 
			
		||||
        # Add sanitizers for target.
 | 
			
		||||
        if(SANITIZE_ADDRESS)
 | 
			
		||||
            add_sanitize_address(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
        if(SANITIZE_THREAD)
 | 
			
		||||
            add_sanitize_thread(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
        if(SANITIZE_MEMORY)
 | 
			
		||||
            add_sanitize_memory(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
        if(SANITIZE_UNDEFINED)
 | 
			
		||||
            add_sanitize_undefined(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
        if(SANITIZE_LEAK)
 | 
			
		||||
            add_sanitize_leak(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
        if(SANITIZE_CFI)
 | 
			
		||||
            add_sanitize_cfi(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
        if(SANITIZE_SS)
 | 
			
		||||
            add_sanitize_ss(${TARGET})
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
endfunction(add_sanitizers)
 | 
			
		||||
							
								
								
									
										53
									
								
								MyxxCMake/sanitizers/FindTSan.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								MyxxCMake/sanitizers/FindTSan.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES "-g -fsanitize=thread")
 | 
			
		||||
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
 | 
			
		||||
    message(NOTICE "ThreadSanitizer disabled for target ${TARGET} because "
 | 
			
		||||
            "ThreadSanitizer is supported for Linux systems and macOS only.")
 | 
			
		||||
    set(SANITIZE_THREAD Off CACHE BOOL "Enable ThreadSanitizer for sanitized targets." FORCE)
 | 
			
		||||
elseif(NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
 | 
			
		||||
    message(NOTICE "ThreadSanitizer disabled for target ${TARGET} because "
 | 
			
		||||
            "ThreadSanitizer is supported for 64bit systems only.")
 | 
			
		||||
    set(SANITIZE_THREAD Off CACHE BOOL "Enable ThreadSanitizer for sanitized targets." FORCE)
 | 
			
		||||
else()
 | 
			
		||||
    sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer" "TSan")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_thread TARGET)
 | 
			
		||||
    # ThreadSanitizer is not compatible with MemorySanitizer.
 | 
			
		||||
    #
 | 
			
		||||
    # if(SANITIZE_THREAD AND SANITIZE_MEMORY)
 | 
			
		||||
    #     message(FATAL_ERROR "ThreadSanitizer is not compatible with " "MemorySanitizer.")
 | 
			
		||||
    # endif()
 | 
			
		||||
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										37
									
								
								MyxxCMake/sanitizers/FindUBSan.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								MyxxCMake/sanitizers/FindUBSan.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
option(SANITIZE_UNDEFINED "Enable UndefinedBehaviorSanitizer for sanitized targets." Off)
 | 
			
		||||
 | 
			
		||||
set(FLAG_CANDIDATES "-g -fsanitize=undefined")
 | 
			
		||||
 | 
			
		||||
include(sanitize-helpers)
 | 
			
		||||
 | 
			
		||||
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "UndefinedBehaviorSanitizer" "UBSan")
 | 
			
		||||
 | 
			
		||||
function(add_sanitize_undefined TARGET)
 | 
			
		||||
    sanitizer_check_target(${TARGET})
 | 
			
		||||
    sanitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan")
 | 
			
		||||
endfunction()
 | 
			
		||||
							
								
								
									
										55
									
								
								MyxxCMake/sanitizers/asan-wrapper
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										55
									
								
								MyxxCMake/sanitizers/asan-wrapper
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
# This script is a wrapper for AddressSanitizer. In some special cases you need
 | 
			
		||||
# to preload AddressSanitizer to avoid error messages - e.g. if you're
 | 
			
		||||
# preloading another library to your application. At the moment this script will
 | 
			
		||||
# only do something, if we're running on a Linux platform. OSX might not be
 | 
			
		||||
# affected.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Exit immediately, if platform is not Linux.
 | 
			
		||||
if [ "$(uname)" != "Linux" ]
 | 
			
		||||
then
 | 
			
		||||
    exec $@
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Get the used libasan of the application ($1). If a libasan was found, it will
 | 
			
		||||
# be prepended to LD_PRELOAD.
 | 
			
		||||
libasan=$(ldd $1 | grep libasan | sed "s/^[[:space:]]//" | cut -d' ' -f1)
 | 
			
		||||
if [ -n "$libasan" ]
 | 
			
		||||
then
 | 
			
		||||
    if [ -n "$LD_PRELOAD" ]
 | 
			
		||||
    then
 | 
			
		||||
        export LD_PRELOAD="$libasan:$LD_PRELOAD"
 | 
			
		||||
    else
 | 
			
		||||
        export LD_PRELOAD="$libasan"
 | 
			
		||||
    fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Execute the application.
 | 
			
		||||
exec $@
 | 
			
		||||
							
								
								
									
										199
									
								
								MyxxCMake/sanitizers/sanitize-helpers.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								MyxxCMake/sanitizers/sanitize-helpers.cmake
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,199 @@
 | 
			
		||||
# The MIT License (MIT)
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c)
 | 
			
		||||
#   2013 Matthew Arsenault
 | 
			
		||||
#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
			
		||||
#   2021 Markus Eggenbauer
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
# of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
# in the Software without restriction, including without limitation the rights
 | 
			
		||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
# copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
# furnished to do so, subject to the following conditions:
 | 
			
		||||
#
 | 
			
		||||
# The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
# copies or substantial portions of the Software.
 | 
			
		||||
#
 | 
			
		||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
# SOFTWARE.
 | 
			
		||||
 | 
			
		||||
# Helper function to get the language of a source file.
 | 
			
		||||
function(sanitizer_lang_of_source FILE RETURN_VAR)
 | 
			
		||||
    get_filename_component(LONGEST_EXT "${FILE}" EXT)
 | 
			
		||||
    # If extension is empty return. This can happen for extensionless headers
 | 
			
		||||
    if("${LONGEST_EXT}" STREQUAL "")
 | 
			
		||||
        set(${RETURN_VAR} "" PARENT_SCOPE)
 | 
			
		||||
        return()
 | 
			
		||||
    endif()
 | 
			
		||||
    # Get shortest extension as some files can have dot in their names
 | 
			
		||||
    string(REGEX REPLACE "^.*(\\.[^.]+)$" "\\1" FILE_EXT ${LONGEST_EXT})
 | 
			
		||||
    string(TOLOWER "${FILE_EXT}" FILE_EXT)
 | 
			
		||||
    string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
 | 
			
		||||
 | 
			
		||||
    get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
 | 
			
		||||
    foreach(LANG ${ENABLED_LANGUAGES})
 | 
			
		||||
        list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
 | 
			
		||||
        if(NOT ${TEMP} EQUAL -1)
 | 
			
		||||
            set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
 | 
			
		||||
            return()
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    set(${RETURN_VAR} "" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
# Helper function to get compilers used by a target.
 | 
			
		||||
function(sanitizer_target_compilers TARGET RETURN_VAR)
 | 
			
		||||
    # Check if all sources for target use the same compiler. If a target uses
 | 
			
		||||
    # e.g. C and Fortran mixed and uses different compilers (e.g. clang and
 | 
			
		||||
    # gfortran) this can trigger huge problems, because different compilers may
 | 
			
		||||
    # use different implementations for sanitizers.
 | 
			
		||||
    set(BUFFER "")
 | 
			
		||||
    get_target_property(TSOURCES ${TARGET} SOURCES)
 | 
			
		||||
    foreach(FILE ${TSOURCES})
 | 
			
		||||
        # If expression was found, FILE is a generator-expression for an object
 | 
			
		||||
        # library. Object libraries will be ignored.
 | 
			
		||||
        string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
 | 
			
		||||
        if("${_file}" STREQUAL "")
 | 
			
		||||
            sanitizer_lang_of_source(${FILE} LANG)
 | 
			
		||||
            if(LANG)
 | 
			
		||||
                list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID})
 | 
			
		||||
            endif()
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    list(REMOVE_DUPLICATES BUFFER)
 | 
			
		||||
    set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
# Helper function to check compiler flags for language compiler.
 | 
			
		||||
function(sanitizer_check_compiler_flag FLAG LANG VARIABLE)
 | 
			
		||||
    if(${LANG} STREQUAL "C")
 | 
			
		||||
        include(CheckCCompilerFlag)
 | 
			
		||||
        check_c_compiler_flag("${FLAG}" ${VARIABLE})
 | 
			
		||||
 | 
			
		||||
    elseif(${LANG} STREQUAL "CXX")
 | 
			
		||||
        include(CheckCXXCompilerFlag)
 | 
			
		||||
        check_cxx_compiler_flag("${FLAG}" ${VARIABLE})
 | 
			
		||||
 | 
			
		||||
    elseif(${LANG} STREQUAL "Fortran")
 | 
			
		||||
        # CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible
 | 
			
		||||
        # with older Cmake versions, we will check if this module is present
 | 
			
		||||
        # before we use it. Otherwise we will define Fortran coverage support as
 | 
			
		||||
        # not available.
 | 
			
		||||
        include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED)
 | 
			
		||||
        if(INCLUDED)
 | 
			
		||||
            CHECK_Fortran_COMPILER_FLAG("${FLAG}" ${VARIABLE})
 | 
			
		||||
        elseif(NOT CMAKE_REQUIRED_QUIET)
 | 
			
		||||
            message(STATUS "Performing Test ${VARIABLE}")
 | 
			
		||||
            message(STATUS "Performing Test ${VARIABLE}" " - Failed (Check not supported)")
 | 
			
		||||
        endif()
 | 
			
		||||
    endif()
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
# Helper function to test compiler flags.
 | 
			
		||||
function(sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
 | 
			
		||||
    set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY})
 | 
			
		||||
 | 
			
		||||
    get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
 | 
			
		||||
    foreach(LANG ${ENABLED_LANGUAGES})
 | 
			
		||||
        # Sanitizer flags are not dependend on language, but the used compiler.
 | 
			
		||||
        # So instead of searching flags foreach language, search flags foreach
 | 
			
		||||
        # compiler used.
 | 
			
		||||
        set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
 | 
			
		||||
        if(NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS)
 | 
			
		||||
            foreach(FLAG ${FLAG_CANDIDATES})
 | 
			
		||||
                if(NOT CMAKE_REQUIRED_QUIET)
 | 
			
		||||
                    message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]")
 | 
			
		||||
                endif()
 | 
			
		||||
 | 
			
		||||
                set(CMAKE_REQUIRED_FLAGS "${FLAG}")
 | 
			
		||||
                unset(${PREFIX}_FLAG_DETECTED CACHE)
 | 
			
		||||
                sanitizer_check_compiler_flag("${FLAG}" ${LANG} ${PREFIX}_FLAG_DETECTED)
 | 
			
		||||
 | 
			
		||||
                if(${PREFIX}_FLAG_DETECTED)
 | 
			
		||||
                    # If compiler is a GNU compiler, search for static flag, if
 | 
			
		||||
                    # SANITIZE_LINK_STATIC is enabled.
 | 
			
		||||
                    if(SANITIZE_LINK_STATIC AND (COMPILER STREQUAL "GNU"))
 | 
			
		||||
                        string(TOLOWER ${PREFIX} PREFIX_lower)
 | 
			
		||||
                        sanitizer_check_compiler_flag("-static-lib${PREFIX_lower}" ${LANG}
 | 
			
		||||
                                                      ${PREFIX}_STATIC_FLAG_DETECTED)
 | 
			
		||||
 | 
			
		||||
                        if(${PREFIX}_STATIC_FLAG_DETECTED)
 | 
			
		||||
                            set(FLAG "-static-lib${PREFIX_lower} ${FLAG}")
 | 
			
		||||
                        endif()
 | 
			
		||||
                    endif()
 | 
			
		||||
 | 
			
		||||
                    set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}"
 | 
			
		||||
                        CACHE STRING "${NAME} flags for ${COMPILER} compiler.")
 | 
			
		||||
                    mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
 | 
			
		||||
                    break()
 | 
			
		||||
                endif()
 | 
			
		||||
            endforeach()
 | 
			
		||||
 | 
			
		||||
            if(NOT ${PREFIX}_FLAG_DETECTED)
 | 
			
		||||
                set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING
 | 
			
		||||
                                                         "${NAME} flags for ${COMPILER} compiler.")
 | 
			
		||||
                mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
 | 
			
		||||
 | 
			
		||||
                message(
 | 
			
		||||
                    NOTICE "${NAME} is not available for ${COMPILER} "
 | 
			
		||||
                    "compiler. Targets using this compiler will be " "compiled without ${NAME}.")
 | 
			
		||||
            endif()
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
# Helper to assign sanitizer flags for TARGET.
 | 
			
		||||
function(sanitizer_add_flags TARGET NAME PREFIX)
 | 
			
		||||
    # Get list of compilers used by target and check, if sanitizer is available
 | 
			
		||||
    # for this target. Other compiler checks like check for conflicting
 | 
			
		||||
    # compilers will be done in add_sanitizers function.
 | 
			
		||||
    sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
 | 
			
		||||
    list(LENGTH TARGET_COMPILER NUM_COMPILERS)
 | 
			
		||||
    if("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL "")
 | 
			
		||||
        return()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    # Set compile- and link-flags for target.
 | 
			
		||||
    set_property(TARGET ${TARGET} APPEND_STRING PROPERTY COMPILE_FLAGS
 | 
			
		||||
                                                         " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
 | 
			
		||||
    set_property(TARGET ${TARGET} APPEND_STRING PROPERTY COMPILE_FLAGS
 | 
			
		||||
                                                         " ${SanBlist_${TARGET_COMPILER}_FLAGS}")
 | 
			
		||||
    set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS
 | 
			
		||||
                                                         " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
macro(sanitizer_check_target TARGET)
 | 
			
		||||
    # Check if this target will be compiled by exactly one compiler. Other-
 | 
			
		||||
    # wise sanitizers can't be used and a warning should be printed once.
 | 
			
		||||
    get_target_property(TARGET_TYPE ${TARGET} TYPE)
 | 
			
		||||
    if(TARGET_TYPE STREQUAL "INTERFACE_LIBRARY")
 | 
			
		||||
        message(NOTICE "Can't use any sanitizers for target ${TARGET}, "
 | 
			
		||||
                "because it is an interface library and cannot be " "compiled directly.")
 | 
			
		||||
        return()
 | 
			
		||||
    endif()
 | 
			
		||||
    sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
 | 
			
		||||
    list(LENGTH TARGET_COMPILER NUM_COMPILERS)
 | 
			
		||||
    if(NUM_COMPILERS GREATER 1)
 | 
			
		||||
        message(
 | 
			
		||||
            NOTICE "Can't use any sanitizers for target ${TARGET}, "
 | 
			
		||||
            "because it will be compiled by incompatible compilers. "
 | 
			
		||||
            "Target will be compiled without sanitizers.")
 | 
			
		||||
        return()
 | 
			
		||||
 | 
			
		||||
        # If the target is compiled by no or no known compiler, give a warning.
 | 
			
		||||
    elseif(NUM_COMPILERS EQUAL 0)
 | 
			
		||||
        message(
 | 
			
		||||
            NOTICE "Sanitizers for target ${TARGET} may not be"
 | 
			
		||||
            " usable, because it uses no or an unknown compiler. "
 | 
			
		||||
            "This is a false warning for targets using only " "object lib(s) as input.")
 | 
			
		||||
        return()
 | 
			
		||||
    endif()
 | 
			
		||||
endmacro(sanitizer_check_target)
 | 
			
		||||
		Reference in New Issue
	
	Block a user