A powerful pre-commit hook for auto-formatting and linting C/C++ code with clang-format
and clang-tidy
.
Add this configuration to your .pre-commit-config.yaml
file:
repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks rev: v1.0.1 # Use the tag or commit you want hooks: - id: clang-format args: [--style=Google] # Other coding style: LLVM, GNU, Chromium, Microsoft, Mozilla, WebKit. - id: clang-tidy args: [--checks='boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,clang-analyzer-*,cppcoreguidelines-*']
To use custom configurations like .clang-format
and .clang-tidy
:
repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks rev: v1.0.1 hooks: - id: clang-format args: [--style=file] # Loads style from .clang-format file - id: clang-tidy args: [--checks=.clang-tidy] # Loads checks from .clang-tidy file
To use specific versions of clang-format and clang-tidy (using Python wheel packages):
repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks rev: v1.0.1 hooks: - id: clang-format args: [--style=file, --version=18] # Specifies version - id: clang-tidy args: [--checks=.clang-tidy, --version=18] # Specifies version
Note
Starting from version v1.0.0, this package uses Python wheel packages (clang-format and clang-tidy) instead of the previous clang-tools binaries. The wheel packages provide better cross-platform compatibility and easier installation. For more details, see the Migration Guide.
clang-format.............................................................Failed - hook id: clang-format - files were modified by this hook
Here’s a sample diff showing the formatting applied:
--- a/testing/main.c +++ b/testing/main.c @@ -1,3 +1,6 @@ #include <stdio.h> -int main() {for (;;) break; printf("Hello world!\n");return 0;} - +int main() { + for (;;) break; + printf("Hello world!\n"); + return 0; +}
Note
Use --dry-run
in args
of clang-format
to print instead of changing the format, e.g.:
clang-format.............................................................Failed - hook id: clang-format - exit code: 255 main.c:2:11: warning: code should be clang-formatted [-Wclang-format-violations] int main() {for (;;) break; printf("Hello world!\n");return 0;} ^ main.c:2:13: warning: code should be clang-formatted [-Wclang-format-violations] int main() {for (;;) break; printf("Hello world!\n");return 0;} ^ main.c:2:21: warning: code should be clang-formatted [-Wclang-format-violations] int main() {for (;;) break; printf("Hello world!\n");return 0;} ^ main.c:2:28: warning: code should be clang-formatted [-Wclang-format-violations] int main() {for (;;) break; printf("Hello world!\n");return 0;} ^ main.c:2:54: warning: code should be clang-formatted [-Wclang-format-violations] int main() {for (;;) break; printf("Hello world!\n");return 0;} ^ main.c:2:63: warning: code should be clang-formatted [-Wclang-format-violations] int main() {for (;;) break; printf("Hello world!\n");return 0;} ^
clang-tidy...............................................................Failed - hook id: clang-tidy - exit code: 1 522 warnings generated. Suppressed 521 warnings (521 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. /home/runner/work/cpp-linter-hooks/cpp-linter-hooks/testing/main.c:4:13: warning: statement should be inside braces [readability-braces-around-statements] for (;;) ^ {
Tip
If your pre-commit
runs longer than expected, it is highly recommended to add files
in .pre-commit-config.yaml
to limit the scope of the hook. This helps improve performance by reducing the number of files being checked and avoids unnecessary processing. Here's an example configuration:
- repo: https://github.com/cpp-linter/cpp-linter-hooks rev: v1.0.1 hooks: - id: clang-format args: [--style=file, --version=18] files: ^(src|include)/.*\.(cpp|cc|cxx|h|hpp)$ # Limits to specific dirs and file types - id: clang-tidy args: [--checks=.clang-tidy, --version=18] files: ^(src|include)/.*\.(cpp|cc|cxx|h|hpp)$
Alternatively, if you want to run the hooks manually on only the changed files, you can use the following command:
pre-commit run --files $(git diff --name-only)
This approach ensures that only modified files are checked, further speeding up the linting process during development.
Note
Use -v
or --verbose
in args
of clang-format
to show the list of processed files e.g.:
repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks rev: v1.0.1 hooks: - id: clang-format args: [--style=file, --version=18, --verbose] # Add -v or --verbose for detailed output
We welcome contributions! Whether it's fixing issues, suggesting improvements, or submitting pull requests, your support is greatly appreciated.
This project is licensed under the MIT License.