diff --git a/.github/workflows/sil-kit-ci.yml b/.github/workflows/sil-kit-ci.yml index 730207040..8e063f4f7 100644 --- a/.github/workflows/sil-kit-ci.yml +++ b/.github/workflows/sil-kit-ci.yml @@ -9,6 +9,7 @@ concurrency: cancel-in-progress: true jobs: + check-licenses: name: License checks for SIL Kit sources runs-on: ubuntu-22.04 @@ -35,6 +36,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: false + - name: Check if build CI should run id: build_check run: | @@ -59,6 +61,31 @@ jobs: python3 ./SilKit/ci/check_formatting.py shell: bash + clang-tidy: + name: Running clang-tidy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Run clang-tidy + id: clang-tidy + run: | + mkdir _o + export CC=clang && export CXX=clang++ + cmake -S . -B build_tidy -GNinja -DSILKIT_BUILD_DASHBOARD=OFF -DSILKIT_BUILD_DEMOS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo + python3 ./SilKit/ci/silkit_clang_tidy.py build_tidy/ _o/ + shell: bash + + - name: Artifact + id: artifact + uses: actions/upload-artifact@v4 + with: + name: clang_tidy_reports + path: | + ./_o/*.yaml + retention-days: 1 + clang14-tsan: name: Thread Sanitizer Tests needs: [check-licenses, check-run-builds, check-formatting] diff --git a/.gitignore b/.gitignore index f35ba7339..ea7296c26 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # compile commands for clangd support compile_commands.json # ignore cmake-generated path directories -^build*/ +build*/ _build*/ install*/ _install*/ diff --git a/SilKit/ci/silkit_clang_tidy.py b/SilKit/ci/silkit_clang_tidy.py new file mode 100644 index 000000000..4ac66f19e --- /dev/null +++ b/SilKit/ci/silkit_clang_tidy.py @@ -0,0 +1,95 @@ +#! /bin/env python3 + +# SPDX-FileCopyrightText: 2025 Vector Informatik GmbH +# +# SPDX-License-Identifier: MIT + +import argparse +import json +import os +import subprocess +import sys + +from multiprocessing import Pool, cpu_count +from pathlib import Path + +isCI = os.getenv('CI') +INFO_PREFIX = "::notice ::" if isCI is not None else "INFO: " +WARN_PREFIX = "::warning ::" if isCI is not None else "WARNING: " +ERROR_PREFIX = "::error ::" if isCI is not None else "ERROR: " + + +# Convenience +def log(fmt, *args): + print(fmt.format(*args)) + + +def info(fmt, *args): + log(INFO_PREFIX + fmt, *args) + + +def warn(fmt, *args): + log(WARN_PREFIX + fmt, *args) + + +def die(status, fmt, *args): + log(ERROR_PREFIX + fmt, *args) + sys.exit(status) + + +def run_clang_tidy(source_file: Path, outdir: Path): + + source_file_str = str(outdir / f"{source_file.name}_fixes.yaml") + cmd_args = ['clang-tidy', source_file, '--header-filter', '\'^.*SilKit.*\'', + '-p', 'build_tidy/', + '--export-fixes', source_file_str, + '--quiet'] + + clang_tidy = subprocess.run(cmd_args, + capture_output=True, encoding='utf-8') + + if clang_tidy.stdout != "" and "ThirdParty" not in clang_tidy.stdout: + warn(f"{source_file}:\n{clang_tidy.stdout}", flush=True) + + +def main(): + + parser = argparse.ArgumentParser( + prog="ClangTidyRunner", + description="Run clang tidy on select source files") + + parser.add_argument( + 'builddir', help="The build dir containing the compile_commands.json", type=Path) + parser.add_argument( + 'outdir', help="The directory to store reports in", type=Path) + + args = parser.parse_args() + with open(args.builddir / 'compile_commands.json', 'r') as f: + cc = json.load(f) + + source_files = [] + for file_entry in cc: + # Exclude ThirdParty Stuff + filename = file_entry["file"] + if "ThirdParty" not in filename: + + # Skip F|I|UTests due to gmock macro hell + if "Test_" in filename: + continue + source_files.append(filename) + + print(f"Processing {len(source_files)} cpp files!") + + global parallel_tidy + + def parallel_tidy(source_file): + run_clang_tidy(Path(source_file), args.outdir) + + num_cpus = cpu_count() + + with Pool(num_cpus) as p: + p.map(parallel_tidy, source_files) + + +if __name__ == "__main__": + main() diff --git a/SilKit/source/core/participant/Participant.hpp b/SilKit/source/core/participant/Participant.hpp index 02b53a8ec..9b2a87c6a 100644 --- a/SilKit/source/core/participant/Participant.hpp +++ b/SilKit/source/core/participant/Participant.hpp @@ -81,7 +81,7 @@ namespace SilKit { namespace Core { template -class Participant : public IParticipantInternal +class Participant final : public IParticipantInternal { public: // ---------------------------------------- diff --git a/SilKit/source/tracing/PcapReader.hpp b/SilKit/source/tracing/PcapReader.hpp index c74ff8b62..c55b0a701 100755 --- a/SilKit/source/tracing/PcapReader.hpp +++ b/SilKit/source/tracing/PcapReader.hpp @@ -12,7 +12,7 @@ namespace SilKit { namespace Tracing { -class PcapReader : public SilKit::IReplayChannelReader +class PcapReader final : public SilKit::IReplayChannelReader { public: // Constructors diff --git a/SilKit/source/tracing/detail/NamedPipeLinux.hpp b/SilKit/source/tracing/detail/NamedPipeLinux.hpp index 98124c6d1..bb073c898 100644 --- a/SilKit/source/tracing/detail/NamedPipeLinux.hpp +++ b/SilKit/source/tracing/detail/NamedPipeLinux.hpp @@ -11,7 +11,7 @@ namespace SilKit { namespace Tracing { namespace Detail { -class NamedPipeLinux : public NamedPipe +class NamedPipeLinux final : public NamedPipe { public: // ---------------------------------------- diff --git a/ThirdParty/rapidyaml/.clang-tidy b/ThirdParty/rapidyaml/.clang-tidy new file mode 100644 index 000000000..612bd0ee8 --- /dev/null +++ b/ThirdParty/rapidyaml/.clang-tidy @@ -0,0 +1 @@ +Checks: '-*'