mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 06:45:37 +08:00
ci: Run static code analysis
This commit is contained in:
28
.clang-tidy
28
.clang-tidy
@@ -1,32 +1,8 @@
|
||||
# SPDX-FileCopyrightText: Copyright (C) swift Project Community / Contributors
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
Checks:
|
||||
- '-*'
|
||||
- 'modernize-*'
|
||||
- '-modernize-use-trailing-return-type'
|
||||
- '-modernize-use-nodiscard'
|
||||
- '-modernize-pass-by-value'
|
||||
- '-modernize-avoid-c-arrays'
|
||||
- 'bugprone-*'
|
||||
- '-bugprone-easily-swappable-parameters'
|
||||
- 'readability-*'
|
||||
- '-readability-identifier-length'
|
||||
- '-readability-implicit-bool-conversion'
|
||||
- '-readability-braces-around-statements'
|
||||
- '-readability-function-cognitive-complexity'
|
||||
- '-readability-convert-member-functions-to-static'
|
||||
- '-readability-math-missing-parentheses'
|
||||
- '-readability-avoid-unconditional-preprocessor-if'
|
||||
- '-readability-magic-numbers'
|
||||
- '-readability-container-size-empty'
|
||||
- 'cppcoreguidelines-*'
|
||||
- '-cppcoreguidelines-avoid-magic-numbers'
|
||||
- '-cppcoreguidelines-non-private-member-variables-in-classes'
|
||||
- '-cppcoreguidelines-avoid-c-arrays'
|
||||
- '-cppcoreguidelines-owning-memory'
|
||||
- '-cppcoreguidelines-misleading-capture-default-by-value'
|
||||
- '-cppcoreguidelines-pro-bounds-array-to-pointer-decay'
|
||||
Checks: >
|
||||
-*,
|
||||
|
||||
|
||||
CheckOptions:
|
||||
|
||||
57
.github/workflows/build.yml
vendored
57
.github/workflows/build.yml
vendored
@@ -18,6 +18,7 @@ env:
|
||||
do_vatsim_key: ${{ github.event_name == 'push' }}
|
||||
do_symbols: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
do_doxygen: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
do_static_analysis: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
|
||||
qt_version: 6.10.0
|
||||
bitrock_version: qt-professional-24.7.0
|
||||
bitrock_url: https://releases.installbuilder.com/installbuilder
|
||||
@@ -104,6 +105,62 @@ jobs:
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: docs/html/
|
||||
- name: Check if clang-tidy analysis is required
|
||||
id: check_need_clang_tidy
|
||||
run: |
|
||||
if python3 -u scripts/run_static_analysis.py --check-changed-files; then
|
||||
echo "should_run_clang_tidy=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_run_clang_tidy=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Checkout repository
|
||||
if: ${{ steps.check_need_clang_tidy.outputs.should_run_clang_tidy == 'true' }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
submodules: 'true'
|
||||
- name: Install Qt
|
||||
if: ${{ steps.check_need_clang_tidy.outputs.should_run_clang_tidy == 'true' }}
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: ${{ env.qt_version }}
|
||||
modules: 'qtmultimedia'
|
||||
cache: true
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.check_need_clang_tidy.outputs.should_run_clang_tidy == 'true' }}
|
||||
run: |
|
||||
sudo apt-get -y install dbus-x11 libglu1-mesa-dev libpulse-dev libdbus-1-dev ninja-build
|
||||
pip3 install requests conan
|
||||
- name: Checkout externals
|
||||
if: ${{ env.use_externals == 'true' && steps.check_need_clang_tidy.outputs.should_run_clang_tidy == 'true' }}
|
||||
uses: actions/checkout@v4
|
||||
env:
|
||||
EXTERNALS_PAT: ${{ secrets.EXTERNALS_PAT }}
|
||||
with:
|
||||
repository: ${{ env.externals }}
|
||||
ref: ${{ env.externals_sha }}
|
||||
token: ${{ env.EXTERNALS_PAT }}
|
||||
path: 'third_party/externals'
|
||||
- name: Install conan dependencies
|
||||
if: ${{ steps.check_need_clang_tidy.outputs.should_run_clang_tidy == 'true' }}
|
||||
shell: bash
|
||||
env:
|
||||
ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }}
|
||||
ARTIFACTORY_TOKEN: ${{ secrets.ARTIFACTORY_TOKEN }}
|
||||
run: |
|
||||
conan profile detect
|
||||
conan remote disable conancenter
|
||||
conan remote add swift https://artifactory.swift-project.org/artifactory/api/conan/conan-local
|
||||
conan remote login swift "$ARTIFACTORY_USER" --password "$ARTIFACTORY_TOKEN"
|
||||
conan install . --output-folder=build_conan --deployer=full_deploy -pr=ci/profile_linux
|
||||
- name: Run clang-tidy
|
||||
if: ${{ steps.check_need_clang_tidy.outputs.should_run_clang_tidy == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build && pushd build
|
||||
cmake .. --preset ci-build-linux-no-pch
|
||||
popd
|
||||
python3 scripts/run_static_analysis.py --clang-tidy --build-path build --changed-files-ci
|
||||
|
||||
buildLinux:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
@@ -59,6 +59,7 @@ option(SWIFT_MINIFY_DEBUG_SYMBOLS "Minify debug symbols" OFF)
|
||||
option(SWIFT_ONLY_XSWIFTBUS_WORKAROUND "Only build xswiftbus (useful when compiling on ARM)" OFF)
|
||||
|
||||
option(SWIFT_USE_CRASHPAD "Use crashpad" OFF)
|
||||
option(SWIFT_USE_PCH "Use precompiled headers" ON)
|
||||
|
||||
|
||||
# Shortcut to only build xswiftbus
|
||||
|
||||
@@ -77,6 +77,22 @@
|
||||
"SWIFT_USE_CRASHPAD": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-build-linux-no-pch",
|
||||
"displayName": "CI Build Linux without PCH (used for static code analysis)",
|
||||
"inherits": "ci-build-linux",
|
||||
"generator": "Ninja",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
||||
"VATSIM_KEY_JSON": "",
|
||||
"SWIFT_USE_PCH": "OFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dev-debug",
|
||||
"displayName": "Development Debug",
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/env python
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright (C) 2025 swift Project Community / Contributors
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
||||
|
||||
"""This script runs clang-tidy only on files that have changed compared to the latest origin/main branch."""
|
||||
|
||||
import argparse
|
||||
|
||||
import utils
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def run_clang_tidy(build_path: str):
|
||||
src_path = utils.get_swift_source_path()
|
||||
os.chdir(src_path)
|
||||
|
||||
result = subprocess.run(
|
||||
['git', 'diff', '--name-only', 'origin/main...HEAD'],
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
|
||||
files = [line for line in result.stdout.splitlines() if (line.endswith('.cpp') or line.endswith('.h')) and not line.startswith('tests')]
|
||||
nproc = os.cpu_count()
|
||||
subprocess.run([
|
||||
'xargs',
|
||||
'-P', str(nproc),
|
||||
'-n', '1',
|
||||
'-r',
|
||||
'clang-tidy',
|
||||
'-p', build_path,
|
||||
'--warnings-as-errors', '*'
|
||||
], input='\n'.join(files), text=True, check=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(prog="swift clang-tidy helper")
|
||||
parser.add_argument("--build-path", required=True, help='Path to build folder')
|
||||
args = parser.parse_args()
|
||||
|
||||
run_clang_tidy(args.build_path)
|
||||
160
scripts/run_static_analysis.py
Normal file
160
scripts/run_static_analysis.py
Normal file
@@ -0,0 +1,160 @@
|
||||
#!/bin/env python
|
||||
|
||||
# SPDX-FileCopyrightText: Copyright (C) 2025 swift Project Community / Contributors
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
||||
|
||||
"""This script runs static analysis tools only on files that have changed compared to the latest origin/main branch."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
import utils
|
||||
|
||||
# Currently we are not checking all directories as they might need to run compilation first for Qt UIC
|
||||
CHECK_DIRECTORIES = [
|
||||
"src/core",
|
||||
"src/misc",
|
||||
"src/input",
|
||||
"src/sound",
|
||||
]
|
||||
|
||||
|
||||
def _get_all_files(build_path: str) -> list[str]:
|
||||
"""Get all files inside the compile commands."""
|
||||
src_path = utils.get_swift_source_path()
|
||||
os.chdir(src_path)
|
||||
|
||||
with open(os.path.join(build_path, "compile_commands.json"), 'r') as f:
|
||||
commands = json.load(f)
|
||||
commands = set([os.path.relpath(entry["file"], utils.get_swift_source_path()) for entry in commands])
|
||||
|
||||
commands = [command for command in commands if
|
||||
not command.startswith("third_party") and not command.startswith(build_path)]
|
||||
return commands
|
||||
|
||||
|
||||
def _get_all_files_ci(build_path: str) -> list[str]:
|
||||
"""Get all files in the compile commands and which will be checked in CI runs."""
|
||||
src_path = utils.get_swift_source_path()
|
||||
os.chdir(src_path)
|
||||
|
||||
with open(os.path.join(build_path, "compile_commands.json"), 'r') as f:
|
||||
commands = json.load(f)
|
||||
commands = set([os.path.relpath(entry["file"], utils.get_swift_source_path()) for entry in commands])
|
||||
|
||||
commands = [command for command in commands if command.startswith(tuple(CHECK_DIRECTORIES))]
|
||||
return commands
|
||||
|
||||
|
||||
def _get_changed_files_ci(build_path: str) -> set[str]:
|
||||
"""Get all files in the compile commands which has changed since the last main commit and are in the included directories."""
|
||||
src_path = utils.get_swift_source_path()
|
||||
os.chdir(src_path)
|
||||
|
||||
result = subprocess.run(
|
||||
['git', 'diff', '--name-only', 'origin/main'],
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
with open(os.path.join(build_path, "compile_commands.json"), 'r') as f:
|
||||
commands = json.load(f)
|
||||
commands = set([os.path.relpath(entry["file"], utils.get_swift_source_path()) for entry in commands])
|
||||
|
||||
files = set([line for line in result.stdout.splitlines() if
|
||||
(line.endswith('.cpp') or line.endswith('.h')) and line.startswith(tuple(CHECK_DIRECTORIES))])
|
||||
return files & commands
|
||||
|
||||
|
||||
def _has_changed_files() -> bool:
|
||||
src_path = utils.get_swift_source_path()
|
||||
os.chdir(src_path)
|
||||
|
||||
result = subprocess.run(
|
||||
['git', 'diff', '--name-only', 'origin/main'],
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
|
||||
return len([line for line in result.stdout.splitlines() if
|
||||
(line.endswith('.cpp') or line.endswith('.h')) and line.startswith(tuple(CHECK_DIRECTORIES))]) > 0
|
||||
|
||||
|
||||
def run_clang_tidy(build_path: str, changed_source_files: set[str]):
|
||||
print(f"Run clang-tidy on files: {changed_source_files}")
|
||||
nproc = 10
|
||||
try:
|
||||
subprocess.run([
|
||||
'xargs',
|
||||
'-P', str(nproc),
|
||||
'-n', '1',
|
||||
'-r',
|
||||
'clang-tidy',
|
||||
'-p', build_path,
|
||||
'--warnings-as-errors', '*',
|
||||
'--quiet',
|
||||
'--header-filter', f'{utils.get_swift_source_path()}/src/',
|
||||
], input='\n'.join(changed_source_files), text=True, check=True)
|
||||
except CalledProcessError:
|
||||
print("Clang-tidy finished with errors")
|
||||
exit(1)
|
||||
|
||||
|
||||
def run_clazy(build_path: str, changed_source_files: set[str]):
|
||||
print(f"Run clazy on files: {changed_source_files}")
|
||||
nproc = os.cpu_count()
|
||||
try:
|
||||
subprocess.run([
|
||||
'clazy-standalone',
|
||||
'-p', build_path,
|
||||
"-extra-arg", "-Werror",
|
||||
"-extra-arg", "-Wno-unnecessary-virtual-specifier",
|
||||
'--header-filter', '(config|core|gui|input|misc|plugins|sound|swiftcore|swiftdata|swiftguistandard|swiftlauncher|xswiftbus)/',
|
||||
*changed_source_files
|
||||
], text=True, check=True)
|
||||
except CalledProcessError:
|
||||
print("Clazy finished with errors")
|
||||
exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(prog="swift clang-tidy helper")
|
||||
parser.add_argument("--build-path", help='Path to build folder')
|
||||
|
||||
check_mode = parser.add_mutually_exclusive_group(required=True)
|
||||
check_mode.add_argument("--all-files", action="store_true",
|
||||
help="Run check on all files in the compile commands")
|
||||
check_mode.add_argument("--all-files-ci", action="store_true",
|
||||
help="Run check on all files in the compile commands and which will be checked in CI runs.")
|
||||
check_mode.add_argument("--changed-files-ci", action="store_true",
|
||||
help="Run check on all files in the compile commands which are changed since the last main commit and are in the included directories (no Qt UIC files).")
|
||||
check_mode.add_argument("--check-changed-files", action="store_true",
|
||||
help="Check if files have changed for evaluation. Program exits with 0 if no files changed; with 1 otherwise")
|
||||
|
||||
parser.add_argument("--clang-tidy", action="store_true",
|
||||
help="Run clang-tidy checks")
|
||||
parser.add_argument("--clazy", action="store_true",
|
||||
help="Run clazy checks")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.all_files:
|
||||
source_files = _get_all_files(args.build_path)
|
||||
elif args.all_files_ci:
|
||||
source_files = _get_all_files_ci(args.build_path)
|
||||
elif args.changed_files_ci:
|
||||
source_files = _get_changed_files_ci(args.build_path)
|
||||
else:
|
||||
exit(1 if _has_changed_files() else 0)
|
||||
|
||||
if args.clang_tidy:
|
||||
run_clang_tidy(args.build_path, source_files)
|
||||
elif args.clazy:
|
||||
run_clazy(args.build_path, source_files)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -272,11 +272,14 @@ endif()
|
||||
|
||||
target_compile_definitions(core PRIVATE BUILD_SWIFT_CORE_LIB)
|
||||
|
||||
target_precompile_headers(core
|
||||
PRIVATE
|
||||
${SWIFT_MISC_PCH}
|
||||
${SWIFT_CORE_PCH}
|
||||
)
|
||||
|
||||
if(SWIFT_USE_PCH)
|
||||
target_precompile_headers(core
|
||||
PRIVATE
|
||||
${SWIFT_MISC_PCH}
|
||||
${SWIFT_CORE_PCH}
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS core
|
||||
LIBRARY DESTINATION lib
|
||||
|
||||
@@ -881,12 +881,14 @@ target_link_libraries(gui
|
||||
|
||||
target_compile_definitions(gui PRIVATE BUILD_SWIFT_GUI_LIB)
|
||||
|
||||
target_precompile_headers(gui
|
||||
PRIVATE
|
||||
${SWIFT_MISC_PCH}
|
||||
${SWIFT_CORE_PCH}
|
||||
${SWIFT_GUI_PCH}
|
||||
)
|
||||
if(SWIFT_USE_PCH)
|
||||
target_precompile_headers(gui
|
||||
PRIVATE
|
||||
${SWIFT_MISC_PCH}
|
||||
${SWIFT_CORE_PCH}
|
||||
${SWIFT_GUI_PCH}
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS gui
|
||||
LIBRARY DESTINATION lib
|
||||
|
||||
@@ -718,10 +718,12 @@ if(APPLE)
|
||||
target_link_libraries(misc PRIVATE "-lbsm -framework AVFoundation -framework Security -framework CoreFoundation -framework ApplicationServices -framework Foundation -framework IOKit")
|
||||
endif()
|
||||
|
||||
target_precompile_headers(misc
|
||||
PRIVATE
|
||||
${SWIFT_MISC_PCH}
|
||||
)
|
||||
if(SWIFT_USE_PCH)
|
||||
target_precompile_headers(misc
|
||||
PRIVATE
|
||||
${SWIFT_MISC_PCH}
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS misc
|
||||
LIBRARY DESTINATION lib
|
||||
|
||||
Reference in New Issue
Block a user