Add clang-tidy linting to merge requests CI

Introduce a new clang_tidy job that runs on merge requests
and the default branch. The job configures CMake to export
compile_commands.json and runs run-clang-tidy restricted to
repo files. Any warnings or errors cause the job to fail.

Artifacts include clang-tidy.log and compile_commands.json
to aid local reproduction. Shared Vulkan Loader setup was
factored into a YAML anchor for reuse across jobs.

Signed-off-by: Maged Elnaggar <maged.elnaggar@arm.com>
Change-Id: I61b48656e68e0e83725500ae1b37f8626f9a248c
This commit is contained in:
Maged Elnaggar 2025-09-10 13:31:35 +00:00 committed by Rosen Zhelev
parent f9b4a0df56
commit 9608f70237
7 changed files with 103 additions and 41 deletions

View file

@ -26,40 +26,92 @@ workflow:
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
stages: [lint, build]
# Shared setup: toolchain + Vulkan Loader/Headers
.vulkan_loader_setup: &vulkan_loader_setup
- set -euo pipefail
- pwd
- uname -a
# Retry a few times on transient mirror/metadata issues
- |
max_tries=6
for i in $(seq 1 "$max_tries"); do
dnf -y --refresh --best --setopt=install_weak_deps=False install \
make cmake gcc gcc-c++ python3 git clang clang-tools-extra \
pkgconf-pkg-config \
'pkgconfig(x11)' 'pkgconfig(xrandr)' 'pkgconfig(xcb)' 'pkgconfig(x11-xcb)' \
'pkgconfig(xkbcommon)' 'pkgconfig(wayland-client)' && break || {
echo "DNF install attempt $i/$max_tries failed; retrying in 10s."; sleep 10;
}
done
if [ "$i" -eq "$max_tries" ]; then
echo "DNF failed after $max_tries attempts"; exit 1;
fi
- mkdir -p /build
- pushd /build
- git clone --depth=1 https://github.com/KhronosGroup/Vulkan-Loader.git
- cd Vulkan-Loader
- mkdir -p build && cd build
- ../scripts/update_deps.py --cmake_var VULKAN_HEADERS_ENABLE_MODULE=OFF
- cmake -C helper.cmake ..
- make -j"$(nproc)"
- make install
- popd
pre-commit:
stage: lint
image: python:3.10.6
rules:
- if: $CI_MERGE_REQUEST_DIFF_BASE_SHA
before_script:
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get install -y git
script:
- pip install pre-commit
- echo Using $CI_MERGE_REQUEST_DIFF_BASE_SHA as Pre-commit base
- pre-commit run --show-diff-on-failure --from-ref $CI_MERGE_REQUEST_DIFF_BASE_SHA --to-ref HEAD
- pre-commit run --show-diff-on-failure --from-ref "$CI_MERGE_REQUEST_DIFF_BASE_SHA" --to-ref HEAD
clang_tidy:
stage: lint
image: "registry.fedoraproject.org/fedora"
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
before_script:
- *vulkan_loader_setup
script:
# Generate compile_commands.json (no build needed)
- mkdir -p build
- >
cmake -S . -B build
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DVULKAN_CXX_INCLUDE=/build/Vulkan-Loader/build/Vulkan-Headers/build/install/include
- test -f build/compile_commands.json || { echo "compile_commands.json missing"; exit 2; }
# Run clang-tidy across all TUs in the DB; restrict diagnostics to this repo
- set +e
- run-clang-tidy -p build -j "$(nproc)" -quiet -header-filter="$(pwd)/.*" | tee clang-tidy.log
- set -e
# Fail if any warnings/errors were emitted for repo files
- |
if grep -E "^(.*):[0-9]+:[0-9]+: (warning|error):" clang-tidy.log >/dev/null; then
echo "clang-tidy found issues. See clang-tidy.log"; exit 1
fi
allow_failure: false
artifacts:
when: always
paths:
- clang-tidy.log
- build/compile_commands.json
build_vulkan_wsi_layer:
# For now start from a standard Fedora image and install everything each time.
stage: build
image: "registry.fedoraproject.org/fedora"
before_script:
- pwd
- uname -a
# Install necessary packages.
# Oddly the exit status of the command below is nonzero even on success, just ignore it.
- yes | dnf install make cmake gcc g++ python git libxcb-devel libxkbcommon-devel wayland-devel libXrandr-devel || true
# Check out and set-up the Vulkan Loader.
- mkdir /build
- pushd /build
- git clone --depth=1 https://github.com/KhronosGroup/Vulkan-Loader.git
- cd Vulkan-Loader
- mkdir build
- cd build/
- ../scripts/update_deps.py --cmake_var VULKAN_HEADERS_ENABLE_MODULE=OFF
# Build the Vulkan loader.
- cmake -C helper.cmake ..
- make
- make install
- popd
- *vulkan_loader_setup
script:
- pwd
- mkdir build
- mkdir -p build
- cd build
- cmake .. -DVULKAN_CXX_INCLUDE=/build/Vulkan-Loader/build/Vulkan-Headers/build/install/include
- make
- make -j"$(nproc)"

View file

@ -48,7 +48,7 @@ surface_properties::surface_properties(surface *wsi_surface)
: m_specific_surface(wsi_surface)
, m_supported_modes({ VK_PRESENT_MODE_FIFO_KHR })
{
populate_present_mode_compatibilities();
this->surface_properties::populate_present_mode_compatibilities();
}
surface_properties::surface_properties()
@ -74,7 +74,7 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
/* Composite alpha */
pSurfaceCapabilities->supportedCompositeAlpha =
static_cast<VkCompositeAlphaFlagBitsKHR>(VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);
static_cast<VkCompositeAlphaFlagsKHR>(VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);
return VK_SUCCESS;
}
@ -603,4 +603,4 @@ bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mo
} /* namespace display */
} /* namespace wsi */
} /* namespace wsi */

View file

@ -72,7 +72,7 @@ surface_properties::surface_properties()
VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR,
VK_PRESENT_MODE_FIFO_LATEST_READY_EXT })
{
populate_present_mode_compatibilities();
this->surface_properties::populate_present_mode_compatibilities();
}
surface_properties &surface_properties::get_instance()

View file

@ -117,7 +117,7 @@ void get_surface_capabilities_common(VkPhysicalDevice physical_device, VkSurface
surface_capabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
/* Composite alpha */
surface_capabilities->supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagBitsKHR>(
surface_capabilities->supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagsKHR>(
VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR | VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR);
@ -127,4 +127,4 @@ void get_surface_capabilities_common(VkPhysicalDevice physical_device, VkSurface
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
} /* namespace wsi */
} /* namespace wsi */

View file

@ -72,16 +72,16 @@ void swapchain_base::page_flip_thread()
{
/* In continuous mode the application will only make one presentation request,
* therefore the page flip semaphore will only be signalled once. */
if (!m_first_present)
if (m_first_present)
{
vk_res = VK_SUCCESS;
VkResult wait_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT);
if (wait_res == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
}
assert(wait_res == VK_SUCCESS);
}
else if ((vk_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT)) == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
}
assert(vk_res == VK_SUCCESS);
/* For continuous mode there will be only one image in the swapchain.
* This image will always be used, and there is no pending state in this case. */
@ -91,10 +91,13 @@ void swapchain_base::page_flip_thread()
{
/* Waiting for the page_flip_semaphore which will be signalled once there is an
* image to display.*/
if ((vk_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT)) == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
VkResult wait_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT);
if (wait_res == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
}
}
/* We want to present the oldest queued for present image from our present queue,

View file

@ -33,9 +33,16 @@
#define TOSTRING(x) STRINGIFY(x)
#if VK_HEADER_VERSION > WSI_LAYER_VK_PATCH
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-W#pragma-messages"
#endif
#pragma message("The Vulkan header version is newer than the currently supported version.")
#pragma message("Current Vulkan header version: " TOSTRING(VK_HEADER_VERSION))
#pragma message("Supported Vulkan API version: " TOSTRING(WSI_LAYER_VK_PATCH))
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif
namespace wsi

View file

@ -71,7 +71,7 @@ surface_properties::surface_properties(surface *wsi_surface, const util::allocat
, supported_formats(allocator)
, m_supported_modes({ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_LATEST_READY_EXT })
{
populate_present_mode_compatibilities();
this->surface_properties::populate_present_mode_compatibilities();
}
surface_properties::surface_properties()
@ -94,7 +94,7 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
pSurfaceCapabilities->minImageCount = 2;
/* Composite alpha */
pSurfaceCapabilities->supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagBitsKHR>(
pSurfaceCapabilities->supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagsKHR>(
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR);
return VK_SUCCESS;
}