Skip to main content

Automatically formats and lints C/C++ code using clang-format and clang-tidy

Project description

cpp-linter-hooks

PyPI PyPI - Python Version codecov Test CodeQL

A pre-commit hook that automatically formats and lints your C/C++ code using 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.1.11  # 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.1.11
    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

[!TIP] By default, the latest version of clang-format and clang-tidy will be installed if not specified. You can specify the version using the --version argument in the args list as shown below.

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.1.11
    hooks:
      - id: clang-format
        args: [--style=file, --version=21] # Specifies version
      - id: clang-tidy
        args: [--checks=.clang-tidy, --version=21] # Specifies version

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] For large codebases, 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.1.11
  hooks:
    - id: clang-format
      args: [--style=file, --version=21]
      files: ^(src|include)/.*\.(cpp|cc|cxx|h|hpp)$ # Limits to specific dirs and file types
    - id: clang-tidy
      args: [--checks=.clang-tidy, --version=21]
      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.1.11
    hooks:
      - id: clang-format
        args: [--style=file, --version=21, --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)
Custom configuration files .clang-format, .clang-tidy .clang-format
Specify clang-format and clang-tidy version ✅ via --version ✅ via rev
Supports passing format style string ✅ via --style
Verbose output ✅ via --verbose
Dry-run mode ✅ via --dry-run

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cpp_linter_hooks-1.1.12-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file cpp_linter_hooks-1.1.12-py3-none-any.whl.

File metadata

File hashes

Hashes for cpp_linter_hooks-1.1.12-py3-none-any.whl
Algorithm Hash digest
SHA256 570a33261055d543e704f7c486afac726b78f9f083b36c24afd153e2144f4876
MD5 4ed71ecfef503331e692b48449bd093a
BLAKE2b-256 d47bb797281c66617ead58d1c9ea3015762288861dfdb4b15039651c1ce769b3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page