From 6da4e606d497253c5b5e125847b5b9b63ddfe5ed Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Jan 2025 19:40:00 +0100 Subject: [PATCH] Add cppcheck workflow Add a workflow for linting and add a cppcheck job. The job is using cppcheck provided by package manager. Existing errors are suppressed to get going with CI linting, ideally tho the suppression list would be empty. Some of the suppressed errors are only found with more recent cppcheck than what is available in the runner. Also remove old arclint cppcheck setup. Signed-off-by: Ralph Sennhauser --- .gitea/workflows/lint.yml | 43 ++++++++++++++ .gitignore | 3 + build/arclint/README.md | 7 --- build/arclint/dummies/cppcheck.bat | 2 - build/arclint/dummies/cppcheck.php | 43 -------------- source/tools/lint/README.md | 18 ++++++ source/tools/lint/cppcheck/cppcheck.sh | 59 +++++++++++++++++++ .../tools/lint/cppcheck/suppressions-list.txt | 56 ++++++++++++++++++ source/tools/lint/lint.sh | 16 +++++ 9 files changed, 195 insertions(+), 52 deletions(-) create mode 100644 .gitea/workflows/lint.yml delete mode 100644 build/arclint/dummies/cppcheck.bat delete mode 100755 build/arclint/dummies/cppcheck.php create mode 100644 source/tools/lint/README.md create mode 100755 source/tools/lint/cppcheck/cppcheck.sh create mode 100644 source/tools/lint/cppcheck/suppressions-list.txt create mode 100755 source/tools/lint/lint.sh diff --git a/.gitea/workflows/lint.yml b/.gitea/workflows/lint.yml new file mode 100644 index 0000000000..21f46f9cdd --- /dev/null +++ b/.gitea/workflows/lint.yml @@ -0,0 +1,43 @@ +--- +# yamllint disable rule:line-length +name: lint +on: + - push + - pull_request +jobs: + cppcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # cache only works for items in workspace, so configure apt to allow for caching. + - name: Setup apt cache locations + id: apt-cache-location + run: | + mkdir -p apt-cache/archives/partial + mkdir -p apt-lists/partial + mkdir -p apt-lists/auxfiles + sudo echo "Dir::Cache \"$(realpath apt-cache)\";" >/etc/apt/apt.conf.d/99cachelocation + sudo echo "Dir::State::lists \"$(realpath apt-lists)\";" >>/etc/apt/apt.conf.d/99cachelocation + + - name: Cache apt pkg db and and deb files + id: apt-cache + uses: actions/cache@v4 + with: + path: | + apt-cache + apt-lists + key: ${{ runner.os }}-apt-cache-4 + + - name: Update package db + if: steps.apt-cache.outputs.cache-hit != 'true' + run: sudo apt-get update + + - name: Install cppcheck + run: sudo apt-get --assume-yes --no-install-recommends install cppcheck + + - name: Fetch the base branch, so we can use `git diff` + run: git fetch origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }} + + - name: Check for issues + run: ./source/tools/lint/cppcheck/cppcheck.sh --diff ${{ github.event.pull_request.base.ref }} diff --git a/.gitignore b/.gitignore index 6c351f2a8b..fd0c4557c6 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,9 @@ archives/ build/bin/ source/tools/spirv/rules.*.json +# Linting +cppcheck-error.log + # Files generated by running premake5 build/premake/.gccmachine.tmp build/premake/.gccver.tmp diff --git a/build/arclint/README.md b/build/arclint/README.md index 5336b78569..8b3802e7ff 100644 --- a/build/arclint/README.md +++ b/build/arclint/README.md @@ -10,7 +10,6 @@ https://secure.phabricator.com/book/phabricator/article/arcanist_lint/ - `json` detects JSON syntax errors. - `licence-year` detects Copyright header years and compares against modification time. - `eslint`, if installed, will run on javascript files. -- `cppcheck`, if installed, will run on C++ files. ## Installation @@ -34,9 +33,3 @@ npm install -g eslint@latest eslint-plugin-brace-rules` ``` See also https://eslint.org/docs/user-guide/getting-started - -#### cppcheck - -Cppcheck is available on various package managers, including HomeBrew on macOS. -An installer is available on windows. -See http://cppcheck.sourceforge.net for details. diff --git a/build/arclint/dummies/cppcheck.bat b/build/arclint/dummies/cppcheck.bat deleted file mode 100644 index bb8a22f67f..0000000000 --- a/build/arclint/dummies/cppcheck.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -php build\arclint\dummies\cppcheck.php diff --git a/build/arclint/dummies/cppcheck.php b/build/arclint/dummies/cppcheck.php deleted file mode 100755 index 9f0f74934e..0000000000 --- a/build/arclint/dummies/cppcheck.php +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env php -. - */ - - -/** - * This file replaces cppcheck if the former is not found, to avoid failure in 'arc lint'. - * It is written in PHP as we can assume php is installed if arcanist is to work at all. - * It mimics `cppcheck --xml`. - * Set the VERBOSE env variable to generate an 'advice' level lint message. - */ - -$verbose = getenv("VERBOSE") ? getenv("VERBOSE") : false; - -$advice = !$verbose ? "" : << - - -EOD; - -$str = << -$advice -EOD; - -fwrite(STDERR, $str); -?> diff --git a/source/tools/lint/README.md b/source/tools/lint/README.md new file mode 100644 index 0000000000..43c0b931c7 --- /dev/null +++ b/source/tools/lint/README.md @@ -0,0 +1,18 @@ +# Linters + +Linters for use in CI or by developers. Also providing configurations for IDEs. + +## cppcheck + +### suppression-list + +The suppression list is ideally empty, restricting to file scope is preferred. + +The format for an error suppression is one of: +[error id]:[filename]:[line] +[error id]:[filename2] +[error id] + +### libraries + +Adding library cfg's for other deps could improve cppchecks ability to find issues. diff --git a/source/tools/lint/cppcheck/cppcheck.sh b/source/tools/lint/cppcheck/cppcheck.sh new file mode 100755 index 0000000000..26620e2bbf --- /dev/null +++ b/source/tools/lint/cppcheck/cppcheck.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +cd "$(dirname "$0")/../../../.." || exit 1 + +. source/tools/utils.sh + +while [ "$#" -gt 0 ]; do + case "$1" in + --diff) + mode="diff" + commitish=$2 + shift + ;; + -j*) JOBS="$1" ;; + *) + printf "Unknown option: %s\n\n" "$1" + exit 1 + ;; + esac + shift +done + +: "${JOBS:=-j$(utils_num_online_cpu)}" + +if [ "${mode}" = diff ]; then + git diff --name-status "${commitish}" | awk '!/^D/{if ($2 ~ /(\.cpp|\.h)$/) {print "./" $2}}' >cppcheck-file-list.txt +else + find . \( -name '*.cpp' -o -name '*.h' \) >cppcheck-file-list.txt +fi + +awk '!/^\.\/(binaries|build|libraries|source\/third_party)\//' cppcheck-file-list-filtered.txt + +rm -f cppcheck-error.log + +cppcheck \ + "${JOBS}" \ + --language=c++ \ + --std=c++17 \ + --force \ + --check-level=exhaustive \ + --library=boost \ + --library=icu \ + --library=libcurl \ + --library=sdl \ + --library=wxwidgets \ + -Isource \ + --file-list=cppcheck-file-list-filtered.txt \ + --suppressions-list=source/tools/lint/cppcheck/suppressions-list.txt \ + 2>&1 >/dev/null | tee cppcheck-error.log >&2 + +rm cppcheck-file-list.txt +rm cppcheck-file-list-filtered.txt + +has_errors=$(wc -l /dev/null; then + ./cppcheck/cppcheck.sh || has_errors=true +else + echo "Cppcheck not found in path" +fi + +if [ ${has_errors} = true ]; then + exit 1 +fi