1
|
1 # - Generate a cppcheck documentation for a project. |
|
2 # The function GENERATE_CPPCHECK is provided to create a "cppcheck" target that |
|
3 # performs static code analysis using the cppcheck utility program. |
|
4 # |
|
5 # GENERATE_CPPCHECK(SOURCES <sources to check...> |
|
6 # [SUPPRESSION_FILE <file>] |
|
7 # [ENABLE_IDS <id...>] |
|
8 # [TARGET_NAME <name>] |
|
9 # [INCLUDES <dir...>]) |
|
10 # |
|
11 # Generates a target "cppcheck" that executes cppcheck on the specified sources. |
|
12 # Sources may either be file names or directories containing files where all |
|
13 # C++ files will be parsed automatically. Use directories whenever possible |
|
14 # because there is a limitation in arguments to pass to the cppcheck binary. |
|
15 # SUPPRESSION_FILE may be give additionally to specify suppressions for# |
|
16 # cppcheck. The sources mentioned in the suppression file must be in the same |
|
17 # format like given for SOURCES. This means if you specified them relative to |
|
18 # CMAKE_CURRENT_SOURCE_DIR, then the same relative paths must be used in the |
|
19 # suppression file. |
|
20 # ENABLE_IDS allows to specify which additional cppcheck check ids to execute, |
|
21 # e.g. all or style. They are combined with AND. |
|
22 # With TARGET_NAME a different name for the generated check target can be |
|
23 # specified. This is useful if several calles to this function are made in one |
|
24 # CMake project, as otherwise the target names collide. |
|
25 # Additional include directories for the cppcheck program can be given with |
|
26 # INCLUDES. |
|
27 # |
|
28 # cppcheck will be executed with CMAKE_CURRENT_SOURCE_DIR as working directory. |
|
29 # |
|
30 # This function can always be called, even if no cppcheck was found. Then no |
|
31 # target is created. |
|
32 # |
|
33 # Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de> |
|
34 # |
|
35 # This program is free software; you can redistribute it |
|
36 # and/or modify it under the terms of the GNU General |
|
37 # Public License as published by the Free Software Foundation; |
|
38 # either version 2, or (at your option) |
|
39 # any later version. |
|
40 # |
|
41 # This program is distributed in the hope that it will be useful, |
|
42 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
43 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
44 # GNU General Public License for more details. |
|
45 # |
|
46 |
|
47 GET_FILENAME_COMPONENT(GENERATE_CPPCHECK_MODULE_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) |
|
48 |
|
49 # FIND_PACKAGE(Cppcheck) |
|
50 find_program(CPPCHECK_EXECUTABLE |
|
51 cppcheck |
|
52 ) |
|
53 |
|
54 if(CPPCHECK_EXECUTABLE) |
|
55 set(CPPCHECK_FOUND True) |
|
56 endif() |
|
57 |
|
58 include(ParseArguments) |
|
59 |
|
60 FUNCTION(GENERATE_CPPCHECK) |
|
61 |
|
62 IF(CPPCHECK_FOUND) |
|
63 |
|
64 PARSE_ARGUMENTS(ARG "SOURCES;SUPPRESSION_FILE;ENABLE_IDS;TARGET_NAME;INCLUDES" "" ${ARGN}) |
|
65 |
|
66 SET(TARGET_NAME "cppcheck") |
|
67 SET(TARGET_NAME_SUFFIX "") |
|
68 # parse target name |
|
69 LIST(LENGTH ARG_TARGET_NAME TARGET_NAME_LENGTH) |
|
70 IF(${TARGET_NAME_LENGTH} EQUAL 1) |
|
71 SET(TARGET_NAME ${ARG_TARGET_NAME}) |
|
72 SET(TARGET_NAME_SUFFIX "-${ARG_TARGET_NAME}") |
|
73 ENDIF() |
|
74 |
|
75 SET(CPPCHECK_CHECKFILE "${CMAKE_BINARY_DIR}/cppcheck-files${TARGET_NAME_SUFFIX}") |
|
76 SET(CPPCHECK_REPORT_FILE "${CMAKE_BINARY_DIR}/cppcheck-report${TARGET_NAME_SUFFIX}.xml") |
|
77 SET(CPPCHECK_WRAPPER_SCRIPT "${CMAKE_BINARY_DIR}/cppcheck${TARGET_NAME_SUFFIX}.cmake") |
|
78 |
|
79 # write a list file containing all sources to check for the call to |
|
80 # cppcheck |
|
81 SET(SOURCE_ARGS "") |
|
82 FOREACH(SOURCE ${ARG_SOURCES}) |
|
83 SET(SOURCE_ARGS "${SOURCE_ARGS} \"${SOURCE}\"") |
|
84 ENDFOREACH() |
|
85 |
|
86 # prepare a cmake wrapper to write the stderr output of cppcheck to |
|
87 # the result file |
|
88 |
|
89 # suppression argument |
|
90 LIST(LENGTH ARG_SUPPRESSION_FILE SUPPRESSION_FILE_LENGTH) |
|
91 IF(${SUPPRESSION_FILE_LENGTH} EQUAL 1) |
|
92 GET_FILENAME_COMPONENT(ABS "${ARG_SUPPRESSION_FILE}" ABSOLUTE) |
|
93 MESSAGE(STATUS "Using suppression file ${ABS}") |
|
94 SET(SUPPRESSION_ARGUMENT --suppressions) |
|
95 SET(SUPPRESSION_FILE "\"${ABS}\"") |
|
96 ENDIF() |
|
97 |
|
98 # includes |
|
99 SET(INCLUDE_ARGUMENTS "") |
|
100 FOREACH(INCLUDE ${ARG_INCLUDES}) |
|
101 SET(INCLUDE_ARGUMENTS "${INCLUDE_ARGUMENTS} \"-I${INCLUDE}\"") |
|
102 ENDFOREACH() |
|
103 |
|
104 # enabled ids |
|
105 SET(ID_LIST "") |
|
106 FOREACH(ID ${ARG_ENABLE_IDS}) |
|
107 SET(ID_LIST "${ID_LIST},${ID}") |
|
108 ENDFOREACH() |
|
109 IF(ID_LIST) |
|
110 STRING(LENGTH ${ID_LIST} LIST_LENGTH) |
|
111 MATH(EXPR FINAL_LIST_LENGTH "${LIST_LENGTH} - 1") |
|
112 STRING(SUBSTRING ${ID_LIST} 1 ${FINAL_LIST_LENGTH} FINAL_ID_LIST) |
|
113 SET(IDS_ARGUMENT "\"--enable=${FINAL_ID_LIST}\"") |
|
114 ELSE() |
|
115 SET(IDS_ARGUMENT "") |
|
116 ENDIF() |
|
117 |
|
118 FILE(WRITE ${CPPCHECK_WRAPPER_SCRIPT} |
|
119 " |
|
120 EXECUTE_PROCESS(COMMAND \"${CPPCHECK_EXECUTABLE}\" ${INCLUDE_ARGUMENTS} ${SUPPRESSION_ARGUMENT} ${SUPPRESSION_FILE} ${IDS_ARGUMENT} --inline-suppr --xml ${SOURCE_ARGS} |
|
121 RESULT_VARIABLE CPPCHECK_EXIT_CODE |
|
122 ERROR_VARIABLE ERROR_OUT |
|
123 WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\") |
|
124 IF(NOT CPPCHECK_EXIT_CODE EQUAL 0) |
|
125 MESSAGE(FATAL_ERROR \"Error executing cppcheck for target ${TARGET}, return code: \${CPPCHECK_EXIT_CODE}\") |
|
126 ENDIF() |
|
127 IF(ERROR_OUT) |
|
128 MESSAGE(\"Detected errors:\\n\${ERROR_OUT}\") |
|
129 ENDIF() |
|
130 FILE(WRITE \"${CPPCHECK_REPORT_FILE}\" \"\${ERROR_OUT}\") |
|
131 " |
|
132 ) |
|
133 |
|
134 ADD_CUSTOM_TARGET(${TARGET_NAME} ${CMAKE_COMMAND} -P "${CPPCHECK_WRAPPER_SCRIPT}" |
|
135 COMMENT "Generating cppcheck result ${TARGET_NAME}") |
|
136 |
|
137 MESSAGE(STATUS "Generating cppcheck target with name ${TARGET_NAME}") |
|
138 |
|
139 ENDIF() |
|
140 |
|
141 ENDFUNCTION() |