From 114f783d060a2e320c929bc7849eb5be5d638954 Mon Sep 17 00:00:00 2001 From: Bostjan Meglic Date: Thu, 30 Jun 2022 05:55:19 +0000 Subject: [PATCH] [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/ --- .clang-tidy | 69 +++++++++++++++++++++++++++++++++++++ meson.build | 27 +++++++++++++++ misc/static_code_analyze.sh | 40 +++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 .clang-tidy create mode 100755 misc/static_code_analyze.sh diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..481519ad7 --- /dev/null +++ b/.clang-tidy @@ -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)' diff --git a/meson.build b/meson.build index 03009673d..b9cedfd2d 100644 --- a/meson.build +++ b/meson.build @@ -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 diff --git a/misc/static_code_analyze.sh b/misc/static_code_analyze.sh new file mode 100755 index 000000000..7fb82ca7a --- /dev/null +++ b/misc/static_code_analyze.sh @@ -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