Skip to content

Commit b4718ac

Browse files
cmake: sca: Add cppcheck
This commit adds cppcheck as a Static Analyser using Zephyr's SCA framework. By specifing -DZEPHYR_SCA_VARIANT=cppcheck to west build, the file sca/cppcheck/index.html will be generated. Signed-off-by: Reto Schneider <[email protected]>
1 parent 3acb5f9 commit b4718ac

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

cmake/sca/cppcheck/sca.cmake

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# SPDX-FileCopyrightText: Copyright (c) 2025 GARDENA GmbH
4+
5+
# If not specified manually, let Cppcheck to use all available (logical) CPU
6+
# cores.
7+
if(NOT DEFINED CPPCHECK_JOBS_COUNT)
8+
cmake_host_system_information(RESULT CPPCHECK_JOBS_COUNT
9+
QUERY NUMBER_OF_LOGICAL_CORES)
10+
endif()
11+
12+
find_program(CPPCHECK_EXE NAMES cppcheck REQUIRED)
13+
message(STATUS "Found SCA: cppcheck (${CPPCHECK_EXE})")
14+
15+
# Defaulting to exhaustive to prevent normalCheckLevelMaxBranches "findings"
16+
set(CPPCHECK_CHECK_LEVEL "exhaustive" CACHE STRING
17+
"Value of the --check-level argument passed to cppcheck")
18+
19+
# The premium edition exits with a non-zero exit code whenever it finds a bug,
20+
# causing the SCA infrastructure of Zephyr to quit with an error too.
21+
# We can prevent this by adding the "--premium=safety-off" argument. However,
22+
# this is known only the the Premium edition of Cppcheck.
23+
if(NOT DEFINED CPPCHECK_IS_PREMIUM)
24+
execute_process(COMMAND "${CPPCHECK_EXE}" "--version"
25+
OUTPUT_VARIABLE CPPCHECK_VERSION_STRING
26+
COMMAND_ERROR_IS_FATAL ANY)
27+
if("${CPPCHECK_VERSION_STRING}" MATCHES "Premium")
28+
set(CPPCHECK_IS_PREMIUM 1)
29+
endif()
30+
endif()
31+
option(CPPCHECK_IS_PREMIUM "Whether we run Cppcheck premium" 0)
32+
if(CPPCHECK_IS_PREMIUM)
33+
set(CPPCHECK_PREMIUM_ARGUMENT "--premium=safety-off")
34+
message(STATUS "Using the Premium version of Cppcheck")
35+
else()
36+
set(CPPCHECK_PREMIUM_ARGUMENT "")
37+
message(STATUS "Using the Open Source version of Cppcheck")
38+
endif()
39+
40+
# Cppcheck uses the compile_commands.json as input
41+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
42+
43+
# Create an output directory for our tool
44+
set(output_dir ${CMAKE_BINARY_DIR}/sca/cppcheck)
45+
file(MAKE_DIRECTORY ${output_dir})
46+
47+
# Help Cppcheck parse the Zephyr headers, reduce runtime by ensuring all
48+
# relevant configs defined
49+
set_property(
50+
GLOBAL
51+
APPEND
52+
PROPERTY
53+
extra_post_build_commands
54+
COMMAND
55+
${CMAKE_COMMAND}
56+
ARGS
57+
-E
58+
touch
59+
${output_dir}/compiler-macros.c
60+
)
61+
set_property(
62+
GLOBAL
63+
APPEND
64+
PROPERTY extra_post_build_byproducts ${output_dir}/compiler-macros.c
65+
)
66+
67+
# Note: This works only for GCC and compatibles. Please add support for other
68+
# compilers!
69+
set_property(
70+
GLOBAL
71+
APPEND
72+
PROPERTY
73+
extra_post_build_commands
74+
COMMAND
75+
${CMAKE_C_COMPILER}
76+
ARGS
77+
-dM
78+
-E
79+
${output_dir}/compiler-macros.c
80+
-o
81+
${output_dir}/compiler-macros.h
82+
)
83+
84+
set_property(
85+
GLOBAL
86+
APPEND
87+
PROPERTY extra_post_build_byproducts ${output_dir}/compiler-macros.h
88+
)
89+
90+
add_custom_target(
91+
cppcheck
92+
ALL
93+
COMMAND
94+
${CPPCHECK_EXE} --project=${CMAKE_BINARY_DIR}/compile_commands.json
95+
--xml # Write results in XML format
96+
--output-file=${output_dir}/cppcheck.xml # write output to file, not stderr
97+
--library=zephyr.cfg # Enable Zephyr specific knowledge
98+
--quiet # Suppress progress reporting
99+
--include=${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/autoconf.h
100+
--include=${output_dir}/compiler-macros.h # Use exact compiler macros
101+
-j ${CPPCHECK_JOBS_COUNT} # Parallelize analysis
102+
-D__cppcheck__ # As recommended by the Cppcheck manual
103+
--check-level=${CPPCHECK_CHECK_LEVEL}
104+
${CPPCHECK_PREMIUM_ARGUMENT}
105+
${CODECHECKER_ANALYZE_OPTS}
106+
DEPENDS
107+
${CMAKE_BINARY_DIR}/compile_commands.json
108+
${output_dir}/compiler-macros.h
109+
BYPRODUCTS ${output_dir}/cppcheck.xml
110+
VERBATIM
111+
)
112+
113+
# Cleanup helper files
114+
add_custom_command(
115+
TARGET cppcheck
116+
POST_BUILD
117+
COMMAND ${CMAKE_COMMAND}
118+
ARGS -E rm ${output_dir}/compiler-macros.c ${output_dir}/compiler-macros.h
119+
)
120+
121+
find_program(CPPCHECK_HTMLREPORT_EXE NAMES cppcheck-htmlreport REQUIRED)
122+
message(STATUS "Found SCA: cppcheck-htmlreport (${CPPCHECK_HTMLREPORT_EXE})")
123+
add_custom_command(
124+
TARGET cppcheck
125+
POST_BUILD
126+
COMMAND
127+
${CPPCHECK_HTMLREPORT_EXE} --title=Zephyr
128+
--file=${output_dir}/cppcheck.xml # Read in file created by Cppcheck
129+
--report-dir=${output_dir} # Set output directory
130+
${CPPCHECK_HTMLREPORT_OPTS}
131+
BYPRODUCTS
132+
${output_dir}/index.html
133+
${output_dir}/stats.html
134+
${output_dir}/style.css
135+
VERBATIM
136+
)

0 commit comments

Comments
 (0)