Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Static Code Analysis

on:
push:
branches: [ trunk ]
pull_request:
branches: [ trunk ]

env:
BUILD_TYPE: Debug

jobs:
cppcheck:
runs-on: ubuntu-latest
if: ${{ contains(github.event.head_commit.message, 'PERFORM_CA') || contains(github.event.pull_request.body, 'PERFORM_CA') }}
permissions:
contents: read

steps:
- uses: actions/checkout@v3

- name: Install cppcheck
run: sudo apt-get update && sudo apt-get install -y cppcheck

- name: Install dependencies
run: |
sudo apt-get install -y g++ libcurl4-gnutls-dev libfreetype6-dev libgif-dev libgtest-dev libjpeg-dev libpixman-1-dev libpng-dev libsdl2-dev libsdl2-image-dev libtinyxml2-dev libwebp-dev libx11-dev libxcursor-dev ninja-build libnode-dev zlib1g-dev libarchive-dev
pip install cmake

- name: Git submodules
run: git submodule update --init --recursive

- name: Configure CMake
run: mkdir build && cd build && cmake -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..

- name: Build the project (required to generate *.xml.h files)
run: cd build && ninja besprited

- name: Run cppcheck
run: cd build && cmake --build . --target cppcheck
continue-on-error: true

clang-tidy:
runs-on: ubuntu-latest
if: ${{ contains(github.event.head_commit.message, 'PERFORM_CA') || contains(github.event.pull_request.body, 'PERFORM_CA') }}
permissions:
contents: read

steps:
- uses: actions/checkout@v3

- name: Install clang-tidy
run: sudo apt-get update && sudo apt-get install -y clang-tidy

- name: Install dependencies
run: |
sudo apt-get install -y g++ libcurl4-gnutls-dev libfreetype6-dev libgif-dev libgtest-dev libjpeg-dev libpixman-1-dev libpng-dev libsdl2-dev libsdl2-image-dev libtinyxml2-dev libwebp-dev libx11-dev libxcursor-dev ninja-build libnode-dev zlib1g-dev libarchive-dev
pip install cmake

- name: Git submodules
run: git submodule update --init --recursive

- name: Configure CMake
run: mkdir build && cd build && cmake -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..

- name: Build the project (required to generate *.xml.h files)
run: cd build && ninja besprited

- name: Run clang-tidy
run: cd build && cmake --build . --target clang-tidy
continue-on-error: true

gcc-analyzer:
runs-on: ubuntu-latest
if: ${{ contains(github.event.head_commit.message, 'PERFORM_CA') || contains(github.event.pull_request.body, 'PERFORM_CA') }}
permissions:
contents: read

steps:
- uses: actions/checkout@v3

- name: Install GCC (ensure version with -fanalyzer support)
run: |
sudo apt-get update
sudo apt-get install -y gcc-10 g++-10
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100

- name: Verify GCC version
run: gcc --version && g++ --version

- name: Install dependencies
run: |
sudo apt-get install -y libcurl4-gnutls-dev libfreetype6-dev libgif-dev libgtest-dev libjpeg-dev libpixman-1-dev libpng-dev libsdl2-dev libsdl2-image-dev libtinyxml2-dev libwebp-dev libx11-dev libxcursor-dev ninja-build libnode-dev zlib1g-dev libarchive-dev
pip install cmake

- name: Git submodules
run: git submodule update --init --recursive

- name: Configure CMake
run: mkdir build && cd build && cmake -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..

- name: Build the project (required to generate *.xml.h files)
run: cd build && ninja besprited

- name: Run GCC with -fanalyzer
run: cd build && cmake --build . --target gcc-analyzer
continue-on-error: true
71 changes: 71 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,74 @@ add_subdirectory(src)
# Third party libraries

add_subdirectory(third_party)

######################################################################
# Static code analysis targets

# cppcheck target
find_program(CPPCHECK_EXECUTABLE cppcheck)
if(CPPCHECK_EXECUTABLE)
add_custom_target(cppcheck
COMMAND ${CPPCHECK_EXECUTABLE}
--enable=all
--suppress=missingIncludeSystem
--suppress=unmatchedSuppression
--inline-suppr
--error-exitcode=1
--std=c++20
-I ${CMAKE_SOURCE_DIR}/src
-I ${CMAKE_SOURCE_DIR}/third_party
${CMAKE_SOURCE_DIR}/src
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running cppcheck static analysis"
VERBATIM
)
message(STATUS "cppcheck found: ${CPPCHECK_EXECUTABLE}")
else()
message(STATUS "cppcheck not found - target 'cppcheck' will not be available")
endif()

# clang-tidy target
find_program(CLANG_TIDY_EXECUTABLE clang-tidy)
if(CLANG_TIDY_EXECUTABLE)
# Get list of source files
file(GLOB_RECURSE ALL_SOURCE_FILES
${CMAKE_SOURCE_DIR}/src/*.cpp
${CMAKE_SOURCE_DIR}/src/*.cc
${CMAKE_SOURCE_DIR}/src/*.c
)

add_custom_target(clang-tidy
COMMAND ${CLANG_TIDY_EXECUTABLE}
-p=${CMAKE_BINARY_DIR}
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy static analysis"
VERBATIM
)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXECUTABLE}")
else()
message(STATUS "clang-tidy not found - target 'clang-tidy' will not be available")
endif()

# gcc-analyzer target
# Note: This target builds the 'besprited' executable with GCC's -fanalyzer flag.
# If analyzing different targets is needed, modify the --target argument below.
if(CMAKE_COMPILER_IS_GNUCXX)
add_custom_target(gcc-analyzer
COMMAND ${CMAKE_COMMAND} -E echo "Building with GCC -fanalyzer..."
COMMAND ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_CXX_FLAGS="-fanalyzer"
-DCMAKE_C_FLAGS="-fanalyzer"
-B${CMAKE_BINARY_DIR}/analyzer_build
-S${CMAKE_SOURCE_DIR}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/analyzer_build --target besprited
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running GCC with -fanalyzer flag"
VERBATIM
)
message(STATUS "GCC compiler found: ${CMAKE_CXX_COMPILER}")
else()
message(STATUS "GCC compiler not found - target 'gcc-analyzer' will not be available")
endif()
45 changes: 45 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* [MacOS details](#macos-details)
* [Android details](#android-details)
* [Installing](#installing)
* [Static Code Analysis](#static-code-analysis)

## Platforms

Expand Down Expand Up @@ -126,3 +127,47 @@ Once you've finished compiling, you can install Besprited by running the
following command from the `build` directory:

ninja install

## Static Code Analysis

Besprited includes build targets for running static code analysis tools. These targets help maintain code quality by detecting potential bugs, security vulnerabilities, and code style issues.

### Available Analysis Targets

From the `build` directory, you can run the following analysis targets:

**cppcheck** - Runs cppcheck static analysis:

cmake --build . --target cppcheck

Requires: [cppcheck](http://cppcheck.sourceforge.net/) to be installed on your system.

**clang-tidy** - Runs clang-tidy static analysis:

cmake --build . --target clang-tidy

Requires: clang-tidy to be installed on your system.

**gcc-analyzer** - Builds with GCC's `-fanalyzer` flag:

cmake --build . --target gcc-analyzer

Requires: GCC 10 or higher (which includes the `-fanalyzer` feature).

### Installing Analysis Tools

**Linux (Debian/Ubuntu):**

sudo apt-get install cppcheck clang-tidy gcc-10 g++-10

**Linux (Fedora):**

sudo dnf install cppcheck clang-tools-extra gcc

**MacOS:**

brew install cppcheck llvm gcc

**Windows (MSYS2):**

pacman -S mingw-w64-i686-cppcheck mingw-w64-i686-clang-tools-extra mingw-w64-i686-gcc
Loading