Repository navigation
Clang Format
Audience: Programmers | Mixed
Thread Context: N/A (development/process reference)
Platform/Backend Scope: All platforms (formatting is platform-independent; CI runs on Ubuntu)
The CI check-format job enforces clang-format on changed C++ files across the full engine surface on every push and pull request. It compares the pushed range or pull-request base to HEAD, so legacy formatting debt does not conceal new debt and does not require unrelated mass rewrites.
The single source of truth for formatting rules is .clang-format at the repo root. Never pass --style=... explicitly — clang-format discovers the root config automatically.
The exact command lives in .github/workflows/build.yml under the check-format job. Its source roots are:
SparkEngine/Source GameModules SparkEditor/Source SparkConsole/src SparkShaderCompiler/src \
SparkBuild/src SparkInstaller/src SparkDaemon/src SparkServer/src SparkGateway/src \
SparkCooker/src SparkWorker/src SparkAutomation/src SparkLauncher/src TestsCI obtains changed paths with git diff --name-only --diff-filter=ACMR -z <base> HEAD, keeps *.h, *.hpp, and *.cpp, excludes */Metal/*, and passes that bounded list directly to clang-format.
CI then greps the log for the violation marker rather than trusting the exit code:
if echo "$OUTPUT" | grep -q "\-Wclang-format-violations"; then
exit 1
fiThe workflow records the formatter exit code, verifies every source root and the tool first, fails on real violation markers, and also rejects abnormal formatter exits. A normal exit 1 without a violation marker remains tolerated because clang-format 18+ can emit a spurious "missing Objective-C config" warning.
The path list covers the engine, every game module, editor, standalone processes and tools, launcher, and tests; it includes *.hpp and excludes */Metal/* (the Objective-C++ Metal sources are not C++-formatted). A docs-only change therefore performs no formatter invocation and succeeds explicitly.
find SparkEngine/Source SparkEditor/Source SparkConsole/src GameModules \
-name '*.h' -o -name '*.cpp' \
| head -50 \
| xargs clang-format --dry-run --Werrorhead -50 caps the input to 50 files. Locally this passes while leaving thousands of files unchecked; CI runs without it and fails immediately. The path list is also stale and *.hpp is missing.
Mirror CI: format-check every C++ file changed from Working, committed or not, under the same fifteen roots. This is the pre-commit check in CLAUDE.md.
git diff --name-only --diff-filter=ACMR origin/Working -- \
SparkEngine/Source GameModules SparkEditor/Source SparkConsole/src SparkShaderCompiler/src \
SparkBuild/src SparkInstaller/src SparkDaemon/src SparkServer/src SparkGateway/src \
SparkCooker/src SparkWorker/src SparkAutomation/src SparkLauncher/src Tests \
| grep -E '\.(h|hpp|cpp)$' | grep -v '/Metal/' \
| xargs -r clang-format --dry-run --WerrorFor a whole-tree sweep (which can also surface legacy debt in files you did not touch, because CI is incremental and never checks those), point find at every CI root:
find SparkEngine/Source GameModules SparkEditor/Source SparkConsole/src SparkShaderCompiler/src \
SparkBuild/src SparkInstaller/src SparkDaemon/src SparkServer/src SparkGateway/src \
SparkCooker/src SparkWorker/src SparkAutomation/src SparkLauncher/src Tests \
-not -path '*/Metal/*' \( -name '*.h' -o -name '*.hpp' -o -name '*.cpp' \) \
| xargs clang-format --dry-run --WerrorThe standalone process roots (SparkDaemon/src, SparkServer/src, SparkGateway/src, SparkCooker/src, SparkWorker/src, SparkAutomation/src, SparkLauncher/src) and Tests are part of CI's list; a local command that stops at the engine, editor and game modules passes while CI fails on a touched daemon or gateway file.
git diff --name-only --diff-filter=ACMR origin/Working -- \
SparkEngine/Source GameModules SparkEditor/Source SparkConsole/src SparkShaderCompiler/src \
SparkBuild/src SparkInstaller/src SparkDaemon/src SparkServer/src SparkGateway/src \
SparkCooker/src SparkWorker/src SparkAutomation/src SparkLauncher/src Tests \
| grep -E '\.(h|hpp|cpp)$' | grep -v '/Metal/' \
| xargs -r clang-format -i-
Never use
head -Nin a format check. If the argv is too long locally, batch without truncating the inventory. -
--Werroris required — without it,--dry-runonly reports diffs and exits 0. -
Exclude
*/Metal/*to match CI (Objective-C++ sources are not C++-formatted). -
Include
*.hpp— CI does. -
.clang-formatat the repo root is the source of truth. Don't pass--style=.... - When you change formatting rules, match the
check-formatjob in.github/workflows/build.yml. -
Zero-initialise
struct stat(and any other elaborated-type declaration) with= {}, not{}. clang-format 18 readsstruct stat s{};as a struct definition and, under this repo's Allman style, rewrites it into a three-line brace block;struct stat s = {};is the same zero-initialisation and stays on one line.
-
Original entry date: 2026-04-17 (
.claude/knowledge/clang-format.md, type: Pattern) - Verified against codebase 2026-06-08.
-
UPDATED: The CI
check-formatpath list has expanded — it now scansSparkGame/SparkGameMMOGameModules subtrees,SparkBuild/src, andSparkInstaller/src, includes*.hpp, and excludes*/Metal/*. The old entry's path list was stale. - UPDATED: CI validates every configured source root and clang-format installation, preserves the Objective-C warning workaround, and incrementally enforces all engine/module/tool/test surfaces without failing on unrelated legacy formatting debt.
-
UPDATED 2026-09-03: The local commands now carry CI's full fifteen-root list (the standalone process roots and
Testswere missing, which let a touchedSparkDaemon/SparkGatewayfile pass locally and failcheck-format), and the incrementalgit diffform is the primary check. Recorded thestruct stat s = {};rule. -
VERIFIED:
--Werrorrequirement, nohead -N, no--style=override,.clang-formatat repo root all still hold. CI command still lives in.github/workflows/build.yml.
- AI-Bloat-Pattern.md — anti-bloat philosophy, the other half of pre-commit hygiene
- Code-Quality-Violations.md — function/method size limits enforced beyond formatting
- MinGW-Wine-Cross-Compilation.md — building Windows code on the same Linux CI runners
Published from 2b03dc797148. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Platform Certification
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Fuzz Policy and Parser Security
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Crash Reporting
- Golden Image Testing
- Utilities
- Testing
- Fuzz Policy and Parser Security
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers