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 <ralph.sennhauser@gmail.com>
This commit is contained in:
Ralph Sennhauser 2025-01-16 19:40:00 +01:00
parent 387ea927ac
commit 6da4e606d4
No known key found for this signature in database
9 changed files with 195 additions and 52 deletions

43
.gitea/workflows/lint.yml Normal file
View file

@ -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 }}

3
.gitignore vendored
View file

@ -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

View file

@ -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.

View file

@ -1,2 +0,0 @@
@echo off
php build\arclint\dummies\cppcheck.php

View file

@ -1,43 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* 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
<error id="skipped" msg="Cppcheck was not found - skipped" severity="advice" inconclusive="true">
<location file="build/arclint/dummies/cppcheck.php" line="23"/>
</error>
EOD;
$str = <<<EOD
<?xml version="1.0" encoding="UTF-8"?>
<results version="2"><errors>$advice</errors></results>
EOD;
fwrite(STDERR, $str);
?>

View file

@ -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.

View file

@ -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.txt >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 <cppcheck-error.log)
if [ "${has_errors}" != 0 ]; then
exit 1
else
rm cppcheck-error.log
fi

View file

@ -0,0 +1,56 @@
// Some versions of cppcheck segfault here, 2.13 to 2.16 probably. Git main is fine.
cppcheckError:./source/lib/file/file_system.cpp
// Suppress all from source/third_party
*:source/third_party/*
// Issues reported by cppcheck and not yet fixed
danglingLifetime:source/lib/sysdep/os/unix/ufilesystem.cpp
danglingTemporaryLifetime:source/graphics/TerrainTextureManager.cpp
danglingTemporaryLifetime:source/lib/sysdep/os/unix/ufilesystem.cpp
invalidFunctionArg:source/lib/tests/test_secure_crt.h
mismatchAllocDealloc:source/lib/tex/tex.cpp
mismatchingContainers:source/graphics/TerrainTextureManager.cpp
missingReturn:source/simulation2/helpers/PathGoal.cpp
nullPointer:source/lib/tests/test_secure_crt.h
nullPointerArithmetic:source/lib/sysdep/os/win/wposix/wposix_internal.h
nullPointerArithmetic:source/lib/sysdep/os/win/wposix/wpthread.cpp
nullPointerOutOfMemory:source/lib/sysdep/os/osx/dir_watch.cpp
nullPointerOutOfMemory:source/lib/sysdep/smbios.cpp
nullPointerOutOfMemory:source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp
preprocessorErrorDirective:source/lib/sysdep/arch.h
preprocessorErrorDirective:source/lib/sysdep/arch/x86_x64/x86_x64.h
preprocessorErrorDirective:source/lib/sysdep/os/win/win.h
preprocessorErrorDirective:source/network/NMTCreator.h
preprocessorErrorDirective:source/scriptinterface/ScriptTypes.h
preprocessorErrorDirective:source/tools/atlas/AtlasUI/CustomControls/Windows/AtlasWindow.h
returnDanglingLifetime:source/lib/file/vfs/vfs_tree.cpp
syntaxError:source/lib/tests/test_byte_order.h
syntaxError:source/ps/FileIo.cpp
syntaxError:source/tools/atlas/AtlasUI/CustomControls/EditableListCtrl/EditableListCtrl.cpp
syntaxError:source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
syntaxError:source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.cpp
syntaxError:source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformPath.cpp
syntaxError:source/tools/atlas/GameInterface/Messages.h
syntaxError:source/tools/atlas/GameInterface/MessagesSetup.h
unknownMacro:source/lib/external_libraries/dbghelp_funcs.h
unknownMacro:source/lib/sysdep/os/win/wdbg_sym.cpp
unknownMacro:source/lib/sysdep/os/win/wfirmware.cpp
unknownMacro:source/lib/sysdep/os/win/wposix/wutsname.cpp
unknownMacro:source/ps/CStr.cpp
unknownMacro:source/simulation2/TypeList.h

16
source/tools/lint/lint.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
set -e
cd "$(dirname "$0")"
has_errors=false
if command -v cppcheck >/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