Skip to content

feat: add clang tooling, lint infrastructure, Linux debug/release presets#13

Merged
deku2026 merged 1 commit into
mainfrom
feature/clang-tooling
Mar 10, 2026
Merged

feat: add clang tooling, lint infrastructure, Linux debug/release presets#13
deku2026 merged 1 commit into
mainfrom
feature/clang-tooling

Conversation

@deku2026
Copy link
Copy Markdown

Summary

This PR adds comprehensive C++ lint infrastructure and code quality tooling.

0. CMake & VSCode changes

  • CMakePresets.json: Added linux-debug and linux-release configure+build presets (symmetric with windows-debug/windows-release)
  • CMakeLists.txt: Added sync-compile-commands ALL target — copies compile_commands.json from the preset's binary dir to build/ so clangd and lint tools always find it
  • .vscode/settings.json: --compile-commands-dirbuild/; editor.tabSize → 4 (matches new style); C++ formatter → clangd

1. New tooling files

  • .clang-format: Modern C++20 style (Google-based, 4-space indent, 120 col column limit)
  • .clang-tidy: Comprehensive check set (bugprone, cert, modernize, performance, readability, cppcoreguidelines, portability)
  • .gitattributes: Language detection, LF line ending normalization, binary file handling
  • .pre-commit-config.yaml: clang-format v22.1.0, clang-tidy v22.1.0, codespell, standard file hygiene hooks

2. GitHub CI

  • linux-ci.yml: Added lint step between configure and build — copies compile_commands.json to build/, sets up Python 3.11, runs pre-commit/action@v3.0.1 (all hooks)

3. Code quality fixes

Applied clang-format to all source/header files and fixed all clang-tidy warnings:

  • [[nodiscard]] annotations on all const query methods
  • Narrowing conversion casts (static_cast<int>, static_cast<float>, etc.)
  • Braced-init-list returns where type is redundant
  • misc-unconventional-assign-operator: operator= now returns rational&
  • std::isnan qualified name (fixes clang diagnostic error)
  • std::ranges::any_of replaces manual loops in TimeRangeList
  • Consistent parameter names across declarations and definitions
  • // NOLINT(portability-simd-intrinsics) for intentional SSE intrinsics in guarded blocks

All pre-commit hooks pass locally (clang-format, clang-tidy, codespell, file hygiene).

…presets

- Replace .clang-format with modern C++20 style (4-space indent, 120 col, Google-based)
- Add .clang-tidy with comprehensive check set (bugprone, modernize, performance, readability)
- Add .gitattributes for language detection, LF normalization, binary file handling
- Add .pre-commit-config.yaml (clang-format v22.1.0, clang-tidy v22.1.0, codespell)
- Update .github/workflows/linux-ci.yml: add pre-commit lint step between configure and build
- Add linux-debug and linux-release configure+build presets to CMakePresets.json
- Add sync-compile-commands CMake target to copy compile_commands.json to build/ for clangd
- Update .vscode/settings.json: clangd points to build/, tabSize=4, clangd as C++ formatter
- Apply clang-format to all source files
- Fix all clang-tidy warnings (nodiscard, narrowing casts, braced-init-list, unconventional
  assign-operator, simd NOLINT, ranges::any_of, inconsistent param names, std::isnan)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 10, 2026 08:46
@deku2026 deku2026 merged commit acc9498 into main Mar 10, 2026
5 of 6 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a full C++ lint/format toolchain (clang-format/clang-tidy via pre-commit), wires it into Linux CI, adds Linux CMake presets, and applies formatting/tidy-driven refactors across the codebase to align with the new tooling.

Changes:

  • Add repository-wide lint/format infrastructure: .clang-format, .clang-tidy, .pre-commit-config.yaml, and .gitattributes
  • Add Linux debug/release presets and CI lint step; update VS Code to point clangd at a unified build/compile_commands.json
  • Apply clang-format + clang-tidy cleanups across util/render code (API annotations, include modernization, small refactors)

Reviewed changes

Copilot reviewed 33 out of 40 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/util/value.cpp Collapse empty namespace definition to single-line form.
src/util/timerange.cpp Reformat + tidy refactors (ranges algorithms, move-based iterator ctor, casts).
src/util/timecodefunctions.cpp Reformat + tidy refactors (casts, switch formatting, std qualifiers).
src/util/tests.cpp Replace deprecated C headers and reformat test harness helpers.
src/util/stringutils.cpp Replace deprecated C headers and reformat; minor return-style tweaks.
src/util/rational.cpp Replace deprecated math header and update NaN handling/formatting.
src/util/color.cpp Include modernization + formatting + explicit casts in conversions.
src/util/bezier.cpp Reformat + minor arithmetic formatting/cleanup.
src/render/samplebuffer.cpp Include modernization + formatting; SIMD lint suppressions added; API signature adjustments.
src/render/audioparams.cpp Formatting + minor logic change for samples_to_time multiplication/cast.
include/arcvideo/foundation/util/value.h Reformat Value container; include ordering adjustments.
include/arcvideo/foundation/util/timerange.h Add [[nodiscard]], ranges-based helpers, iterator API adjustments, and formatting.
include/arcvideo/foundation/util/timecodefunctions.h Reformat enums and function declarations; minor signature formatting.
include/arcvideo/foundation/util/tests.h Reformat test runner API.
include/arcvideo/foundation/util/stringutils.h Reformat + inline helper restructuring and signature formatting.
include/arcvideo/foundation/util/rational.h Add [[nodiscard]], modernize operators/defaults, and reformat.
include/arcvideo/foundation/util/math.h Simplify to empty namespace + header guard formatting.
include/arcvideo/foundation/util/log.h Reformat and modernize small returns/constructors.
include/arcvideo/foundation/util/cpuoptimize.h Header guard comment formatting only.
include/arcvideo/foundation/util/color.h Add [[nodiscard]], reformat, and small API/inline modernization.
include/arcvideo/foundation/util/bezier.h Add [[nodiscard]], reformat, and inline return braced-init updates.
include/arcvideo/foundation/render/sampleformat.h Reformat + add [[nodiscard]] on accessors; tidy-style refactors.
include/arcvideo/foundation/render/samplebuffer.h API tweaks (AudioParams by value), add [[nodiscard]], and reformat.
include/arcvideo/foundation/render/pixelformat.h Reformat + add [[nodiscard]] on accessors.
include/arcvideo/foundation/render/audioparams.h Reformat + add [[nodiscard]] on many APIs; member default init cleanup.
include/arcvideo/foundation/foundation.h Header guard comment formatting only.
docs/BUILD_GUIDE.md Normalize line endings/markdown separators; no functional change.
SECURITY.md Trailing whitespace cleanup.
README.md Normalize line endings/markdown separators; no functional change.
CMakePresets.json Add linux-debug / linux-release presets and matching build presets; formatting normalization.
CMakeLists.txt Add sync-compile-commands ALL target; formatting normalization.
.vscode/settings.json Point clangd to build/ compile commands; set tab size to 4; switch formatter to clangd.
.pre-commit-config.yaml Add pre-commit hooks for formatting/tidy/codespell and hygiene checks.
.gitignore Normalize line endings; no rule logic change.
.github/workflows/linux-ci.yml Add lint step (copy compile_commands + run pre-commit) before build.
.github/dependabot.yml Trailing newline cleanup.
.gitattributes Enforce LF normalization; mark binaries; improve GitHub linguist language detection.
.clang-tidy Add comprehensive clang-tidy configuration/check set.
.clang-format Add modern Google-based C++20 style (4-space indent, 120 cols, regrouped includes).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +161 to +168
__m128 mult = _mm_load1_ps(&volume);
unopt_start = (sample_count_per_channel_ / 4) * 4;
for (size_t j = 0; j < unopt_start; j += 4) {
float* here = cdat + j;
__m128 samples = _mm_loadu_ps(here);
__m128 multiplied = _mm_mul_ps(samples, mult); // NOLINT(portability-simd-intrinsics)
_mm_storeu_ps(here, multiplied);
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

portability-simd-intrinsics is enabled in the repo’s .clang-tidy, but only _mm_mul_ps is annotated with NOLINT. The other intrinsics in this block (_mm_load1_ps, _mm_loadu_ps, _mm_storeu_ps) are likely to be flagged too; consider annotating the whole block (e.g., NOLINTBEGIN/NOLINTEND) or each intrinsic call consistently.

Copilot uses AI. Check for mistakes.
Comment on lines +257 to +269
__m128 min_sse = _mm_load1_ps(&min);
__m128 max_sse = _mm_load1_ps(&max);

unopt_start = (sample_count_per_channel_ / 4) * 4;
for (size_t j=0; j<unopt_start; j+=4) {
float *here = cdat + j;
__m128 samples = _mm_loadu_ps(here);
unopt_start = (sample_count_per_channel_ / 4) * 4;
for (size_t j = 0; j < unopt_start; j += 4) {
float* here = cdat + j;
__m128 samples = _mm_loadu_ps(here);

samples = _mm_max_ps(samples, min_sse);
samples = _mm_min_ps(samples, max_sse);
samples = _mm_max_ps(samples, min_sse); // NOLINT(portability-simd-intrinsics)
samples = _mm_min_ps(samples, max_sse); // NOLINT(portability-simd-intrinsics)

_mm_storeu_ps(here, samples);
}
_mm_storeu_ps(here, samples);
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: the SSE clamp loop uses multiple _mm_* intrinsics but only some lines have NOLINT(portability-simd-intrinsics). To keep clang-tidy clean, annotate the full intrinsic sequence consistently (block-level suppression is usually less error-prone).

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +49
AudioParams(const int& sample_rate, const uint64_t& channel_layout, const SampleFormat& format)
: sample_rate_(sample_rate), channel_layout_(channel_layout), format_(format) {
set_default_footage_parameters();
timebase_ = sample_rate_as_time_base();
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor takes sample_rate/channel_layout by const& even though they’re fundamental types. This typically triggers readability-avoid-const-params-in-decls; consider passing these by value to simplify the API and avoid needless references.

Copilot uses AI. Check for mistakes.
Comment on lines +88 to +96
[[nodiscard]] int64_t time_to_bytes(const double& time) const;
[[nodiscard]] int64_t time_to_bytes(const rational& time) const;
[[nodiscard]] int64_t time_to_bytes_per_channel(const double& time) const;
[[nodiscard]] int64_t time_to_bytes_per_channel(const rational& time) const;
[[nodiscard]] int64_t time_to_samples(const double& time) const;
[[nodiscard]] int64_t time_to_samples(const rational& time) const;
[[nodiscard]] int64_t samples_to_bytes(const int64_t& samples) const;
[[nodiscard]] int64_t samples_to_bytes_per_channel(const int64_t& samples) const;
[[nodiscard]] rational samples_to_time(const int64_t& samples) const;
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several APIs here take fundamental types by const& (e.g., const double&, const int64_t&). With readability-avoid-const-params-in-decls enabled, these should generally be passed by value to avoid lint warnings and make call sites simpler.

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +37
SampleBuffer::SampleBuffer(AudioParams audio_params, const rational& length) : audio_params_(audio_params) {
sample_count_per_channel_ = audio_params_.time_to_samples(length);
allocate();
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructors now take AudioParams by value, but the member initializer copies it (audio_params_(audio_params)), which adds an extra copy for lvalue callers. Either move into the member (std::move(audio_params)) or revert the parameter back to const AudioParams& if copying is intended.

Copilot uses AI. Check for mistakes.
Comment on lines 24 to +28
#include <stdint.h>
#include <string>
#include <string.h>

#include <map>
#include <string>
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header still includes deprecated C headers (<stdint.h>, <string.h>) while other files were migrated to C++ headers. With modernize-deprecated-headers enabled in .clang-tidy, consider switching these to <cstdint> / <cstring> and using std::memcpy / std::strlen for consistency.

Copilot uses AI. Check for mistakes.
const TimeRange& operator-=(const rational& rhs);

std::list<TimeRange> Split(const int &chunk_size) const;
[[nodiscard]] std::list<TimeRange> Split(const int& chunk_size) const;
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split takes const int&, but .clang-tidy enables readability-avoid-const-params-in-decls, which recommends passing small trivially-copyable types by value. Consider changing this parameter to plain int (and matching the definition) to avoid unnecessary references and lint noise.

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +51
[[nodiscard]] const size_t& sample_count() const { return sample_count_per_channel_; }
void set_sample_count(const size_t& sample_count);
void set_sample_count(const rational& length) { set_sample_count(audio_params_.time_to_samples(length)); }
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_sample_count takes const size_t& even though size_t is cheap to copy. Given readability-avoid-const-params-in-decls is enabled, consider taking size_t by value (and update the .cpp definition accordingly).

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +42
SampleBuffer::SampleBuffer(AudioParams audio_params, size_t samples_per_channel)
: audio_params_(audio_params), sample_count_per_channel_(samples_per_channel) {
allocate();
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overload also takes AudioParams by value but copies it into audio_params_. Consider moving the parameter into the member to avoid an extra copy.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants