blob: 752641818be07ca3a476f7d0d26886ba4ffbc77f [file] [log] [blame]
#!/bin/bash
#-------------------------------------------------------------------------------
# Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
##
##@file
##@brief Execute cppcheck
##
##This bash script can be used to execute cppcheck for the tf-m project.
##It will use the CMake generated "compile_commands.json" file.
##CMake is executed to generate the build commands for the "default" build
##configuration (i.e. no build config file is specified on the command-line).
##
##This file shall be executed from the root directory of the tf-m working copy.
##
##In order to have all include file in place, some CMake external projects will
##be built, and thus C build tools for the default build configuration must be
##available.
##
##The script will generate two XML output files:
##file | description
##--------|--------
##chk-config.xml | The result of cppcheck configuration verification.
##chk-src.xml. | The result of source file verification.
##
##@todo The current version of cppcheck seems to ignore command line parameters
## when using the --project command line switch. As a result it is not
## possible to define additional macros and include paths on the command
## line. This results in some incorrect error and warning messages.
##@todo The file cppcheck/arm-cortex-m.cfg needs to be revised. Some settings
## might be invalid, and also a different file may be needed based on
## used compiler switches (i.e. to match width specification and or default
## sign for some types).
##@todo Currently cppcheck is only executed for the default build configuration
## "ConfigDefault.cmake"for target AN521 of the "top level" project.
## This might need to be revised/changed in the future.
##
#Fail if any command exit with error.
set -e
export PATH=$PATH:$GCC_7_3_1_PATH
RAW_OUTPUT=0
while getopts "hr" opt ; do
case "$opt" in
h)
echo "Usage: $(basename -- "$0") [-h] [-r] [git_hash]"
echo " -r, Raw output. (Default is to create xml reports)."
echo " -h, Script help"
exit 0
;;
r)
RAW_OUTPUT=1
;;
esac
done
shift $((OPTIND-1))
#The location from where the script executes
mypath=$(dirname $0)
#The cmake_exported project file in json format
cmake_commands=compile_commands.json
. "$mypath/util_cmake.sh"
#Library file for cppcheck
library_file="$(fix_win_path $(get_full_path $mypath))/cppcheck/arm-cortex-m.cfg"
suppress_file="$(fix_win_path $(get_full_path $mypath))/cppcheck/tfm-suppress-list.txt"
tfm_repo="$(fix_win_path $(get_full_path ./))"
toolchain_file="$tfm_repo/toolchain_GNUARM.cmake"
test_repo="$tfm_repo/../tf-m-tests"
mbedtls_repo="$tfm_repo/../mbedtls"
mcuboot_repo="$tfm_repo/../mcuboot"
#Apply TF-M patches to dependency repos
cnt=$(ls $tfm_repo/lib/ext/mcuboot/*.patch 2> /dev/null | wc -l)
if [ "$cnt" != "0" ] ; then
cd $mcuboot_repo
git apply $tfm_repo/lib/ext/mcuboot/*.patch
cd -
fi
cnt=$(ls $tfm_repo/lib/ext/mbedcrypto/*.patch 2> /dev/null | wc -l)
if [ "$cnt" != "0" ] ; then
cd $mbedtls_repo
git apply $tfm_repo/lib/ext/mbedcrypto/*.patch
cd -
fi
#Cmake compile params
cmake_params="-DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DTFM_PLATFORM=arm/mps2/an521 -DTFM_TOOLCHAIN_FILE=$toolchain_file"
cmake_params="$cmake_params -DTFM_TEST_REPO_PATH=$test_repo -DMBEDCRYPTO_PATH=$mbedtls_repo -DMCUBOOT_PATH=$mcuboot_repo"
#Enable all additional checks by default
additional_checklist="all"
#Run cmake to get the compile_commands.json file
echo
echo '******* Generating compile_commands.json ***************'
echo
generate_project $(fix_win_path $(get_full_path ./)) "./" "cppcheck" "$cmake_params"
#Enter the build directory
bdir=$(make_build_dir_name "./" "cppcheck")
pushd "$bdir" >/dev/null
#The following snippet allows cppcheck to be run differentially against a
#commit hash passed as first argument $1. It does not
#affect the legacy functionality of the script, checking the whole codebase,
#when called without an argument
if [[ ! -z "$1" ]]
then
echo "Enabled git-diff mode against hash: $1"
# Do not execute unused function check and information check when running in diff-mode
additional_checklist="style,performance,portability,missingInclude"
# Grep will set exit status to 1 if a commit does not contain c/cpp.. files
set +e
filtered_cmd_f=compile_commands_filtered.json
# Get a list of files modified by the commits between the reference and HEAD
flist=$(git diff-tree --no-commit-id --name-only -r $1 | grep -E '\S*\.(c|cpp|cc|cxx|inc|h)$')
flist=$(echo $flist | xargs)
echo -e "[" > $filtered_cmd_f
IFS=$' ' read -ra git_flist <<< "${flist}"
for fl in "${git_flist[@]}"; do
echo "Looking for reference of file: $fl"
# dry run the command to see if there any output
JSON_CMD=$(grep -B 3 "\"file\": \".*$fl\"" $cmake_commands)
if [ -n "${JSON_CMD}" ]; then
command_matched=1
grep -B 3 "\"file\": \".*$fl\"" $cmake_commands >> $filtered_cmd_f
echo -e "}," >> $filtered_cmd_f
fi
done
set -e
# Only continue if files in the patch are included in the build commands
if [ -n "${command_matched}" ]; then
sed -i '$ d' $filtered_cmd_f
echo -e "}\n]" >> $filtered_cmd_f
cat $filtered_cmd_f > $cmake_commands
else
echo "CppCheck: Ignoring files not contained in the build config"
if [ "$RAW_OUTPUT" == "0" ] ; then
# Always generate an empty file for other stages of ci expecting one
echo "Files Ignored: $flist"
cat <<-EOF > chk-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<results version="2">
<cppcheck version="$(cppcheck --version)"/>
<errors>
</errors>
</results>
EOF
cp chk-config.xml chk-src.xml
fi
exit 0
fi
fi
function cppcheck_failed {
echo "cppcheck failed."
echo "Check log for errors."
exit 1
}
EXTRA_ARGS="--error-exitcode=1"
if [ "$RAW_OUTPUT" != "1" ] ; then
# If not in raw output mode, use xml output.
EXTRA_ARGS="--xml"
else
trap cppcheck_failed ERR
fi
CPPCHECK_ARGS="$EXTRA_ARGS --enable="$additional_checklist" --library="$library_file" --project=$cmake_commands --suppressions-list="$suppress_file" --inline-suppr"
#Now run cppcheck.
echo
echo '******* checking cppcheck configuration ***************'
echo
if [ "$RAW_OUTPUT" == "1" ] ; then
cppcheck $CPPCHECK_ARGS --check-config > /dev/null
else
cppcheck $CPPCHECK_ARGS --check-config 2>chk-config.xml
fi
echo
echo '******* analyzing files with cppcheck ***************'
echo
if [ "$RAW_OUTPUT" == "1" ] ; then
cppcheck $CPPCHECK_ARGS > /dev/null
echo '******* cppcheck complete ***************'
else
cppcheck $CPPCHECK_ARGS 2>chk-src.xml
echo
echo '******* Please check chk-config.xml and chk-src.xml for the results. ***************'
echo
fi
popd