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-FileCopyrightText: Copyright (C) swift Project Community / Contributors
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
Checks:
|
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'
|
|
||||||
|
|
||||||
|
|
||||||
CheckOptions:
|
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_vatsim_key: ${{ github.event_name == 'push' }}
|
||||||
do_symbols: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
do_symbols: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||||
do_doxygen: ${{ 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
|
qt_version: 6.10.0
|
||||||
bitrock_version: qt-professional-24.7.0
|
bitrock_version: qt-professional-24.7.0
|
||||||
bitrock_url: https://releases.installbuilder.com/installbuilder
|
bitrock_url: https://releases.installbuilder.com/installbuilder
|
||||||
@@ -104,6 +105,62 @@ jobs:
|
|||||||
uses: actions/upload-pages-artifact@v3
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: docs/html/
|
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:
|
buildLinux:
|
||||||
runs-on: ubuntu-22.04
|
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_ONLY_XSWIFTBUS_WORKAROUND "Only build xswiftbus (useful when compiling on ARM)" OFF)
|
||||||
|
|
||||||
option(SWIFT_USE_CRASHPAD "Use crashpad" OFF)
|
option(SWIFT_USE_CRASHPAD "Use crashpad" OFF)
|
||||||
|
option(SWIFT_USE_PCH "Use precompiled headers" ON)
|
||||||
|
|
||||||
|
|
||||||
# Shortcut to only build xswiftbus
|
# Shortcut to only build xswiftbus
|
||||||
|
|||||||
@@ -77,6 +77,22 @@
|
|||||||
"SWIFT_USE_CRASHPAD": "OFF"
|
"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",
|
"name": "dev-debug",
|
||||||
"displayName": "Development 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_compile_definitions(core PRIVATE BUILD_SWIFT_CORE_LIB)
|
||||||
|
|
||||||
target_precompile_headers(core
|
|
||||||
PRIVATE
|
if(SWIFT_USE_PCH)
|
||||||
${SWIFT_MISC_PCH}
|
target_precompile_headers(core
|
||||||
${SWIFT_CORE_PCH}
|
PRIVATE
|
||||||
)
|
${SWIFT_MISC_PCH}
|
||||||
|
${SWIFT_CORE_PCH}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS core
|
install(TARGETS core
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
|
|||||||
@@ -881,12 +881,14 @@ target_link_libraries(gui
|
|||||||
|
|
||||||
target_compile_definitions(gui PRIVATE BUILD_SWIFT_GUI_LIB)
|
target_compile_definitions(gui PRIVATE BUILD_SWIFT_GUI_LIB)
|
||||||
|
|
||||||
target_precompile_headers(gui
|
if(SWIFT_USE_PCH)
|
||||||
PRIVATE
|
target_precompile_headers(gui
|
||||||
${SWIFT_MISC_PCH}
|
PRIVATE
|
||||||
${SWIFT_CORE_PCH}
|
${SWIFT_MISC_PCH}
|
||||||
${SWIFT_GUI_PCH}
|
${SWIFT_CORE_PCH}
|
||||||
)
|
${SWIFT_GUI_PCH}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS gui
|
install(TARGETS gui
|
||||||
LIBRARY DESTINATION lib
|
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")
|
target_link_libraries(misc PRIVATE "-lbsm -framework AVFoundation -framework Security -framework CoreFoundation -framework ApplicationServices -framework Foundation -framework IOKit")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_precompile_headers(misc
|
if(SWIFT_USE_PCH)
|
||||||
PRIVATE
|
target_precompile_headers(misc
|
||||||
${SWIFT_MISC_PCH}
|
PRIVATE
|
||||||
)
|
${SWIFT_MISC_PCH}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS misc
|
install(TARGETS misc
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
|
|||||||
Reference in New Issue
Block a user