1# - Run cppcheck on c++ source files as a custom target and a test 2# 3# include(CppcheckTargets) 4# add_cppcheck(<target-name> [UNUSED_FUNCTIONS] [STYLE] [POSSIBLE_ERROR] [FORCE] [FAIL_ON_WARNINGS]) - 5# Create a target to check a target's sources with cppcheck and the indicated options 6# add_cppcheck_sources(<target-name> [UNUSED_FUNCTIONS] [STYLE] [POSSIBLE_ERROR] [FORCE] [FAIL_ON_WARNINGS]) - 7# Create a target to check standalone sources with cppcheck and the indicated options 8# 9# Requires these CMake modules: 10# Findcppcheck 11# 12# Requires CMake 2.6 or newer (uses the 'function' command) 13# 14# Original Author: 15# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net> 16# http://academic.cleardefinition.com 17# Iowa State University HCI Graduate Program/VRAC 18# 19# Copyright Iowa State University 2009-2010. 20# Distributed under the Boost Software License, Version 1.0. 21# (See accompanying file LICENSE_1_0.txt or copy at 22# http://www.boost.org/LICENSE_1_0.txt) 23 24if(__add_cppcheck) 25 return() 26endif() 27set(__add_cppcheck YES) 28 29if(NOT CPPCHECK_FOUND) 30 find_package(cppcheck QUIET) 31endif() 32 33if(CPPCHECK_FOUND) 34 if(NOT TARGET all_cppcheck) 35 add_custom_target(all_cppcheck) 36 set_target_properties(all_cppcheck PROPERTIES EXCLUDE_FROM_ALL TRUE) 37 endif() 38endif() 39 40function(add_cppcheck_sources _targetname) 41 if(CPPCHECK_FOUND) 42 set(_cppcheck_args) 43 set(_input ${ARGN}) 44 list(FIND _input UNUSED_FUNCTIONS _unused_func) 45 if("${_unused_func}" GREATER "-1") 46 list(APPEND _cppcheck_args ${CPPCHECK_UNUSEDFUNC_ARG}) 47 list(REMOVE_AT _input ${_unused_func}) 48 endif() 49 50 list(FIND _input STYLE _style) 51 if("${_style}" GREATER "-1") 52 list(APPEND _cppcheck_args ${CPPCHECK_STYLE_ARG}) 53 list(REMOVE_AT _input ${_style}) 54 endif() 55 56 list(FIND _input POSSIBLE_ERROR _poss_err) 57 if("${_poss_err}" GREATER "-1") 58 list(APPEND _cppcheck_args ${CPPCHECK_POSSIBLEERROR_ARG}) 59 list(REMOVE_AT _input ${_poss_err}) 60 endif() 61 62 list(FIND _input FORCE _force) 63 if("${_force}" GREATER "-1") 64 list(APPEND _cppcheck_args "--force") 65 list(REMOVE_AT _input ${_force}) 66 endif() 67 68 list(FIND _input FAIL_ON_WARNINGS _fail_on_warn) 69 if("${_fail_on_warn}" GREATER "-1") 70 list(APPEND 71 CPPCHECK_FAIL_REGULAR_EXPRESSION 72 ${CPPCHECK_WARN_REGULAR_EXPRESSION}) 73 list(REMOVE_AT _input ${_fail_on_warn}) 74 endif() 75 76 set(_files) 77 foreach(_source ${_input}) 78 get_source_file_property(_cppcheck_loc "${_source}" LOCATION) 79 if(_cppcheck_loc) 80 # This file has a source file property, carry on. 81 get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE) 82 if("${_cppcheck_lang}" MATCHES "CXX") 83 list(APPEND _files "${_cppcheck_loc}") 84 endif() 85 else() 86 # This file doesn't have source file properties - figure it out. 87 get_filename_component(_cppcheck_loc "${_source}" ABSOLUTE) 88 if(EXISTS "${_cppcheck_loc}") 89 list(APPEND _files "${_cppcheck_loc}") 90 else() 91 message(FATAL_ERROR 92 "Adding CPPCHECK for file target ${_targetname}: " 93 "File ${_source} does not exist or needs a corrected path location " 94 "since we think its absolute path is ${_cppcheck_loc}") 95 endif() 96 endif() 97 endforeach() 98 99 if("1.${CMAKE_VERSION}" VERSION_LESS "1.2.8.0") 100 # Older than CMake 2.8.0 101 add_test(${_targetname}_cppcheck_test 102 "${CPPCHECK_EXECUTABLE}" 103 ${CPPCHECK_TEMPLATE_ARG} 104 ${_cppcheck_args} 105 ${_files}) 106 else() 107 # CMake 2.8.0 and newer 108 add_test(NAME 109 ${_targetname}_cppcheck_test 110 COMMAND 111 "${CPPCHECK_EXECUTABLE}" 112 ${CPPCHECK_TEMPLATE_ARG} 113 ${_cppcheck_args} 114 ${_files}) 115 endif() 116 117 set_tests_properties(${_targetname}_cppcheck_test 118 PROPERTIES 119 FAIL_REGULAR_EXPRESSION 120 "${CPPCHECK_FAIL_REGULAR_EXPRESSION}") 121 122 add_custom_command(TARGET 123 all_cppcheck 124 PRE_BUILD 125 COMMAND 126 ${CPPCHECK_EXECUTABLE} 127 ${CPPCHECK_QUIET_ARG} 128 ${CPPCHECK_TEMPLATE_ARG} 129 ${_cppcheck_args} 130 ${_files} 131 WORKING_DIRECTORY 132 "${CMAKE_CURRENT_SOURCE_DIR}" 133 COMMENT 134 "${_targetname}_cppcheck: Running cppcheck on target ${_targetname}..." 135 VERBATIM) 136 endif() 137endfunction() 138 139function(add_cppcheck _name) 140 if(NOT TARGET ${_name}) 141 message(FATAL_ERROR 142 "add_cppcheck given a target name that does not exist: '${_name}' !") 143 endif() 144 if(CPPCHECK_FOUND) 145 set(_cppcheck_args) 146 147 list(FIND ARGN UNUSED_FUNCTIONS _unused_func) 148 if("${_unused_func}" GREATER "-1") 149 list(APPEND _cppcheck_args ${CPPCHECK_UNUSEDFUNC_ARG}) 150 endif() 151 152 list(FIND ARGN STYLE _style) 153 if("${_style}" GREATER "-1") 154 list(APPEND _cppcheck_args ${CPPCHECK_STYLE_ARG}) 155 endif() 156 157 list(FIND ARGN POSSIBLE_ERROR _poss_err) 158 if("${_poss_err}" GREATER "-1") 159 list(APPEND _cppcheck_args ${CPPCHECK_POSSIBLEERROR_ARG}) 160 endif() 161 162 list(FIND ARGN FORCE _force) 163 if("${_force}" GREATER "-1") 164 list(APPEND _cppcheck_args "--force") 165 endif() 166 167 list(FIND _input FAIL_ON_WARNINGS _fail_on_warn) 168 if("${_fail_on_warn}" GREATER "-1") 169 list(APPEND 170 CPPCHECK_FAIL_REGULAR_EXPRESSION 171 ${CPPCHECK_WARN_REGULAR_EXPRESSION}) 172 list(REMOVE_AT _input ${_unused_func}) 173 endif() 174 175 get_target_property(_cppcheck_includes "${_name}" INCLUDE_DIRECTORIES) 176 set(_includes) 177 foreach(_include ${_cppcheck_includes}) 178 list(APPEND _includes "-I${_include}") 179 endforeach() 180 181 get_target_property(_cppcheck_sources "${_name}" SOURCES) 182 set(_files) 183 foreach(_source ${_cppcheck_sources}) 184 get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE) 185 get_source_file_property(_cppcheck_loc "${_source}" LOCATION) 186 if("${_cppcheck_lang}" MATCHES "CXX") 187 list(APPEND _files "${_cppcheck_loc}") 188 endif() 189 endforeach() 190 191 if("1.${CMAKE_VERSION}" VERSION_LESS "1.2.8.0") 192 # Older than CMake 2.8.0 193 add_test(${_name}_cppcheck_test 194 "${CPPCHECK_EXECUTABLE}" 195 ${CPPCHECK_TEMPLATE_ARG} 196 ${_cppcheck_args} 197 ${_files}) 198 else() 199 # CMake 2.8.0 and newer 200 add_test(NAME 201 ${_name}_cppcheck_test 202 COMMAND 203 "${CPPCHECK_EXECUTABLE}" 204 ${CPPCHECK_TEMPLATE_ARG} 205 ${_cppcheck_args} 206 ${_files}) 207 endif() 208 209 set_tests_properties(${_name}_cppcheck_test 210 PROPERTIES 211 FAIL_REGULAR_EXPRESSION 212 "${CPPCHECK_FAIL_REGULAR_EXPRESSION}") 213 214 add_custom_command(TARGET 215 all_cppcheck 216 PRE_BUILD 217 COMMAND 218 ${CPPCHECK_EXECUTABLE} 219 ${CPPCHECK_QUIET_ARG} 220 ${CPPCHECK_TEMPLATE_ARG} 221 ${_cppcheck_args} 222 ${_includes} 223 ${_files} 224 WORKING_DIRECTORY 225 "${CMAKE_CURRENT_SOURCE_DIR}" 226 COMMENT 227 "${_name}_cppcheck: Running cppcheck on target ${_name}..." 228 VERBATIM) 229 endif() 230 231endfunction() 232