[MISC] Add support for static code analysis

Static code analysis can be executed with following commands:
  meson build
  ninja -C build analyze-cppcheck
  ninja -C build analyze-clang-tidy

These commands are available only if additional tools are installed:
  - cppcheck
  - clang-tidy
  - clang-tools is optional if you want to paralelize the clang-tidy

In case of cppcheck analysis, a file called build/cppchecklog.log is
created with the analysis results.

In case of clang-tidy analysis, some checks are disabled. See file
.clang-tidy, and reenable them if you see fit.
Also it does not scan all the files in the project, since some of them
are imported from other sources. It does not scan any sources under:
  - subprojects/
  - lib/asn1c/
  - lib/ipfw/
This commit is contained in:
Bostjan Meglic 2022-06-30 05:55:19 +00:00 committed by Sukchan Lee
parent 50be661cf9
commit 114f783d06
3 changed files with 136 additions and 0 deletions

69
.clang-tidy Normal file
View File

@ -0,0 +1,69 @@
---
Checks: '*,
-altera-id-dependent-backward-branch,
-altera-struct-pack-align,
-altera-unroll-loops,
-android-cloexec-*,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-macro-parentheses,
-bugprone-reserved-identifier,
-bugprone-sizeof-expression,
-cert-dcl37-c,
-cert-dcl51-cpp,
-cert-err33-c,
-cert-err34-c,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.insecureAPI.bcmp,
-clang-analyzer-security.insecureAPI.bcopy,
-clang-analyzer-security.insecureAPI.bzero,
-clang-diagnostic-error,
-clang-diagnostic-typedef-redefinition,
-clang-diagnostic-unknown-warning-option,
-concurrency-mt-unsafe,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-init-variables,
-google-readability-braces-around-statements,
-google-readability-casting,
-google-readability-function-size,
-google-readability-todo,
-hicpp-braces-around-statements,
-hicpp-function-size,
-hicpp-multiway-paths-covered,
-llvm-else-after-return,
-llvm-header-guard,
-llvm-include-order,
-llvmlibc-restrict-system-libc-headers,
-misc-no-recursion,
-misc-unused-parameters,
-performance-no-int-to-ptr,
-readability-avoid-const-params-in-decls,
-readability-braces-around-statements,
-readability-duplicate-include,
-readability-else-after-return,
-readability-function-cognitive-complexity,
-readability-function-size,
-readability-identifier-length,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-non-const-parameter,
-readability-redundant-control-flow,
-readability-redundant-declaration,
-readability-suspicious-call-argument,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-narrowing-conversions,
-cert-exp42-c,
-cert-flp37-c,
-clang-analyzer-core.NullDereference,
-clang-analyzer-deadcode.DeadStores,
-clang-analyzer-security.insecureAPI.strcpy,
-cppcoreguidelines-interfaces-global-init,
-cppcoreguidelines-narrowing-conversions,
-hicpp-signed-bitwise,
'
WarningsAsErrors: false
HeaderFilterRegex: '(.*\.h)'

View File

@ -42,6 +42,12 @@ python3 = find_program('python3', 'python')
python3_exe = join_paths(python3.path())
mkdir_p = 'import os; os.makedirs("@0@", exist_ok=True) if not os.environ.get("DESTDIR") else False;'
install_conf = 'import os; import shutil; shutil.copy("@0@", "@1@") if not os.environ.get("DESTDIR") and not os.path.isfile(os.path.join("@1@", os.path.split("@0@")[1])) else False;'
cppcheck = find_program('cppcheck', required: false)
clangtidy = find_program('run-clang-tidy', required: false) # requires clang-tools package
if clangtidy.found() != true
clangtidy = find_program('clang-tidy', required: false)
endif
meson.add_install_script(python3_exe, '-c',
mkdir_p.format(join_paths(localstatedir, 'log', 'open5gs')))
@ -131,3 +137,24 @@ message('\n'.join([
' debugging support: ' + get_option('buildtype'),
'',
]))
if cppcheck.found()
run_target('analyze-cppcheck',
command : [ 'misc/static_code_analyze.sh',
cppcheck.path(),
meson.build_root(),
meson.source_root()
]
)
endif
if clangtidy.found()
run_target('analyze-clang-tidy',
command : [ 'misc/static_code_analyze.sh',
clangtidy.path(),
meson.build_root(),
meson.source_root()
]
)
endif

40
misc/static_code_analyze.sh Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
ANALYZE_TOOL="${1}" && shift
BUILD_DIR="${1}" && shift
SOURCES_DIR="${1}" && shift
SOURCES=$(find ${SOURCES_DIR}/src ${SOURCES_DIR}/lib -not -path *asn1c* -not -path *ipfw* -name *.c)
#SOURCES=$(find ${SOURCES_DIR}/src ${SOURCES_DIR}/lib ${SOURCES_DIR}/subprojects -name *.c)
if [[ ${ANALYZE_TOOL} == *"clang-tidy"* ]];
then
if [[ ${ANALYZE_TOOL} == *"run-clang-tidy"* ]]; then
OPTS="${OPTS} -j $(nproc)"
fi
OPTS="${OPTS} -quiet"
OPTS="${OPTS} -p=${BUILD_DIR}"
${ANALYZE_TOOL} ${OPTS} ${SOURCES} 2>/dev/null
elif [[ ${ANALYZE_TOOL} == *"cppcheck"* ]];
then
OPTS="${OPTS} -j $(nproc)"
# OPTS="${OPTS} --quiet"
OPTS="${OPTS} --verbose"
OPTS="${OPTS} --enable=all"
OPTS="${OPTS} --verbose"
OPTS="${OPTS} --suppress=variableScope"
OPTS="${OPTS} --suppress=preprocessorErrorDirective"
OPTS="${OPTS} --suppress=unusedVariable"
OPTS="${OPTS} --output-file=cppchecklog.log"
OPTS="${OPTS} --cppcheck-build-dir=${BUILD_DIR}/cppcheck"
OPTS="${OPTS} --project=${BUILD_DIR}/compile_commands.json"
${ANALYZE_TOOL} ${OPTS} ${SOURCES}
else
echo "Unknown static code analysis tool: ${ANALYZE_TOOL}"
exit 1
fi