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