123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- # - Run cppcheck on C/C++ source files as a custom target
- #
- # Requires these CMake modules:
- # Findcppcheck
- if(NOT CPPCHECK_FOUND)
- find_package(CPPCHECK)
- # Reset its value if it is on the cache
- set(CPPCHECK_EXCLUDED_HEADERS "" CACHE INTERNAL "")
- set(CPPCHECK_PROJECT_OPTIONS "" CACHE INTERNAL "")
- endif()
- set(CPPCHECK_REPORT_DIR ${CMAKE_BINARY_DIR}/cppcheck-reports CACHE STRING
- "The directory where to put the cppcheck reports.")
- set(CPPCHECK_MODULE_DIRECTORY_STRUCTURE FALSE CACHE BOOL
- "Whether the directory was a module type of structure. \
- If the directory has this type of structure - separate \
- directories containing independent sets of sources - \
- an analyse-<module> target will be created for each \
- module")
- set(CPPCHECK_CHECK_CONFIG FALSE CACHE BOOL
- "Whether the config should be checked (--check-config cppcheck option: Check cppcheck configuration. The normal code analysis is disabled by this flag")
- if(CPPCHECK_EXECUTABLE)
- execute_process(COMMAND ${CPPCHECK_EXECUTABLE} --version
- OUTPUT_VARIABLE CPPCHECK_VERSION
- ERROR_QUIET
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(REPLACE "Cppcheck " "" CPPCHECK_VERSION ${CPPCHECK_VERSION})
- string(REPLACE "\n" "" CPPCHECK_VERSION ${CPPCHECK_VERSION})
- message("cppcheck version: ${CPPCHECK_VERSION}")
- endif(CPPCHECK_EXECUTABLE)
- if(NOT TARGET cppcheck_analyse_all)
- add_custom_target(cppcheck_analyse_all)
- set_target_properties(cppcheck_analyse_all PROPERTIES EXCLUDE_FROM_ALL TRUE)
- endif()
- # ::
- #
- # add_cppcheck_project_option(<header> ...)
- #
- #
- # Adds additional options to run cppcheck with
- #
- function(add_cppcheck_project_option)
- set(CPPCHECK_PROJECT_OPTIONS "${CPPCHECK_PROJECT_OPTIONS};${ARGN}" CACHE INTERNAL "")
- endfunction()
- # ::
- #
- # add_cppcheck_header_exclusion(<header> ...)
- #
- #
- # Causes warnings about missing includes for an header or list of header
- # files to be removed. Useful to ignore auto-generated header files.
- #
- function(add_cppcheck_header_exclusion)
- set(CPPCHECK_EXCLUDED_HEADERS "${CPPCHECK_EXCLUDED_HEADERS};${ARGN}" CACHE INTERNAL "")
- endfunction()
- # ::
- #
- # target_add_cppcheck(<target>
- # [ALL]
- # [IGNORE_WARNINGS]
- # [IGNORE_STYLE]
- # [IGNORE_PERFORMANCE]
- # [IGNORE_PORTABILITY]
- # [IGNORE_INFORMATION]
- # [IGNORE_UNUSED_FUNC]
- # [IGNORE_MISSING_INCLUDE]
- # [WARNINGS]
- # [STYLE]
- # [PERFORMANCE]
- # [PORTABILITY]
- # [INFORMATION]
- # [UNUSED_FUNC]
- # [MISSING_INCLUDE]
- # [FORCE_CHECK]
- # [INCLUDES])
- #
- # Adds a CMake target that causes the sources and header files used to
- # build <target> to be static analysed with the cppcheck tool.
- #
- # The checks to be performed can be controlled by giving some options.
- # If <ALL> was given, all checks will be performed. It is possible to
- # exclude a check by passing IGNORE_<CHECK>.
- #
- # If <ALL> was not given, then only the checks specified will be
- # performed. If no check was specified, then the static analysis will
- # not produce any warning.
- #
- # <FORCE_CHECK> runs cppcheck with the `--force` option.
- #
- # <INCLUDES> allows to specify an additional list of directories to look
- # for header files. This may be required as CMake does not return the
- # include directories for a library, when it is being linked with an
- # executable.
- #
- function(target_add_cppcheck _target_name)
- if(NOT TARGET ${_target_name})
- message(FATAL_ERROR
- "[CppCheck] add_cppcheck given a target name that does not exist: '${_target_name}' !")
- endif()
- # Find out the module name
- if (CPPCHECK_MODULE_DIRECTORY_STRUCTURE)
- file(RELATIVE_PATH rel ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
- set(dirname ${rel})
- while(NOT ${dirname} STREQUAL "" )
- set(prev_dirname ${dirname})
- get_filename_component(dirname ${prev_dirname} DIRECTORY)
- endwhile()
- set(_module_name "${prev_dirname}")
- set(_module_cppcheck_tgt "analyse-${_module_name}")
- if(NOT TARGET ${_module_cppcheck_tgt})
- add_custom_target(${_module_cppcheck_tgt})
- set_target_properties(${_module_cppcheck_tgt} PROPERTIES EXCLUDE_FROM_ALL TRUE)
- endif()
- endif()
- set(_cppcheck_args)
- #list(APPEND _cppcheck_args "--xml")
- #list(APPEND _cppcheck_args "--xml-version=2")
- foreach(_cppcheck_opt ${CPPCHECK_PROJECT_OPTIONS})
- list(APPEND _cppcheck_args ${_cppcheck_opt})
- endforeach()
- set(options
- IGNORE_WARNINGS
- IGNORE_STYLE
- IGNORE_PERFORMANCE
- IGNORE_PORTABILITY
- IGNORE_INFORMATION
- IGNORE_UNUSED_FUNC
- IGNORE_MISSING_INCLUDE
- WARNINGS
- STYLE
- PERFORMANCE
- PORTABILITY
- INFORMATION
- UNUSED_FUNC
- MISSING_INCLUDE
- FORCE_CHECK)
- set(multi_value_keywords INCLUDES)
- cmake_parse_arguments(CPPCHECK "${options}" "" "${multi_value_keywords}" ${ARGN})
- if(CPPCHECK_ALL)
- if(NOT CPPCHECK_IGNORE_WARNINGS)
- list(APPEND _cppcheck_args ${CPPCHECK_WARNINGS_ARG})
- endif()
- if(NOT CPPCHECK_IGNORE_STYLE)
- list(APPEND _cppcheck_args ${CPPCHECK_STYLE_ARG})
- endif()
- if(NOT CPPCHECK_IGNORE_PERFORMANCE)
- list(APPEND _cppcheck_args ${CPPCHECK_PERFORMANCE_ARG})
- endif()
- if(NOT CPPCHECK_IGNORE_PORTABILITY)
- list(APPEND _cppcheck_args ${CPPCHECK_PORTABILITY_ARG})
- endif()
- if(NOT CPPCHECK_IGNORE_INFORMATION)
- list(APPEND _cppcheck_args ${CPPCHECK_INFORMATION_ARG})
- endif()
- if(NOT CPPCHECK_IGNORE_UNUSED_FUNC)
- list(APPEND _cppcheck_args ${CPPCHECK_UNUSEDFUNC_ARG})
- endif()
- if(NOT CPPCHECK_IGNORE_MISSING_INCLUDE)
- list(APPEND _cppcheck_args ${CPPCHECK_MISSINGINCLUDE_ARG})
- endif()
- else()
- if(CPPCHECK_WARNINGS)
- list(APPEND _cppcheck_args ${CPPCHECK_WARNINGS_ARG})
- endif()
- if(CPPCHECK_STYLE)
- list(APPEND _cppcheck_args ${CPPCHECK_STYLE_ARG})
- endif()
- if(CPPCHECK_PERFORMANCE)
- list(APPEND _cppcheck_args ${CPPCHECK_PERFORMANCE_ARG})
- endif()
- if(CPPCHECK_PORTABILITY)
- list(APPEND _cppcheck_args ${CPPCHECK_PORTABILITY_ARG})
- endif()
- if(CPPCHECK_INFORMATION)
- list(APPEND _cppcheck_args ${CPPCHECK_INFORMATION_ARG})
- endif()
- if(CPPCHECK_UNUSED_FUNC)
- list(APPEND _cppcheck_args ${CPPCHECK_UNUSEDFUNC_ARG})
- endif()
- if(CPPCHECK_MISSING_INCLUDE)
- list(APPEND _cppcheck_args ${CPPCHECK_MISSINGINCLUDE_ARG})
- endif()
- endif()
- list(APPEND _cppcheck_args ${CPPCHECK_LIBRARY_ARG})
- list(APPEND _cppcheck_args ${CPPCHECK_LIBRARY_STANDARD_ARG})
- list(APPEND _cppcheck_args ${CPPCHECK_LANGUAGE_ARG})
- list(APPEND _cppcheck_args "--relative-paths=${CMAKE_CURRENT_SOURCE_DIR}")
- if(CPPCHECK_FORCE_CHECK)
- list(APPEND _cppcheck_args "--force")
- endif()
- get_target_property(_cppcheck_includes "${_target_name}" INCLUDE_DIRECTORIES)
- get_target_property(_cppcheck_sources "${_target_name}" SOURCES)
- list(APPEND _cppcheck_includes ${CPPCHECK_INCLUDES})
- message(STATUS "[CppCheck] _cppcheck_includes:${_cppcheck_includes}")
- set(_files)
- foreach(_source ${_cppcheck_sources})
- get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE)
- get_source_file_property(_cppcheck_loc "${_source}" LOCATION)
- if("${_cppcheck_lang}" MATCHES "^CXX$" OR "${_cppcheck_lang}" MATCHES "^C$")
- list(APPEND _files "${_cppcheck_loc}")
- message(STATUS "[CppCheck] append file: ${_cppcheck_lang}|${_cppcheck_loc}")
- endif()
- endforeach()
- if (CPPCHECK_MODULE_DIRECTORY_STRUCTURE)
- set(cppcheck_target ${_module_cppcheck_tgt}-${_target_name})
- set(cppcheck_report_file ${CPPCHECK_REPORT_DIR}/${_module_name}-${_target_name})
- else()
- set(cppcheck_target analyse-${_target_name})
- set(cppcheck_report_file ${CPPCHECK_REPORT_DIR}/${_target_name})
- endif()
- if(CPPCHECK_CHECK_CONFIG)
- set(_cppcheck_check_config "true")
- else()
- set(_cppcheck_check_config "false")
- endif()
- if(MSVC)
- set(COMMAND_SCRPIT ${CMAKE_SOURCE_DIR}/addin/cmake/scripts/cppcheck-wrapper/win.bat)
- else()
- set(COMMAND_SCRPIT ${CMAKE_SOURCE_DIR}/addin/cmake/scripts/cppcheck-wrapper/uos.sh)
- endif(MSVC)
- add_custom_target(
- ${cppcheck_target}
- COMMAND
- ${COMMAND_SCRPIT}
- ${CPPCHECK_EXECUTABLE}
- "${_cppcheck_includes}"
- ${CPPCHECK_QUIET_ARG}
- ${CPPCHECK_TEMPLATE_ARG}
- ${_cppcheck_args}
- ${_files}
- WORKING_DIRECTORY
- "${CMAKE_CURRENT_SOURCE_DIR}"
- COMMENT
- "[CppCheck] ${cppcheck_target}: Running cppcheck on target ${_target_name}..."
- VERBATIM
- )
- set_target_properties(${cppcheck_target} PROPERTIES FOLDER "CodeAnalysis")
- add_dependencies(cppcheck_analyse_all ${cppcheck_target})
- if (CPPCHECK_MODULE_DIRECTORY_STRUCTURE)
- add_dependencies(${_module_cppcheck_tgt} ${cppcheck_target})
- endif()
- endfunction()
|