Skip to content

cpp-linter/cpp-linter-hooks

Repository files navigation

cpp-linter-hooks

PyPI PyPI - Python Version codecov Test CodeQL

A powerful pre-commit hook for auto-formatting and linting C/C++ code with clang-format and clang-tidy.

Table of Contents

Quick Start

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-*']

Custom Configuration Files

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

Custom Clang Tool Version

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.

Output

clang-format Output

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 Output

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 (;;)
            ^
             {

Troubleshooting

Performance Optimization

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.

Verbose Output

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

FAQ

What's the difference between cpp-linter-hooks and mirrors-clang-format?

Feature cpp-linter-hooks mirrors-clang-format
Supports clang-format and clang-tidy ✅ (clang-format & clang-tidy) ✅ (clang-format only)
Loads style configuration ✅ via --version ✅ (default behavior)
Specify clang-format version ✅ via --version ✅ via rev
Supports passing code string ✅ via --style
Verbose output ✅ via --verbose

Contributing

We welcome contributions! Whether it's fixing issues, suggesting improvements, or submitting pull requests, your support is greatly appreciated.

License

This project is licensed under the MIT License.