> ## Documentation Index
> Fetch the complete documentation index at: https://aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Linting and Formatting

> Lint and format C/C++ code in Bazel with clang-tidy and clang-format, running checks as Bazel aspects over cc_library targets without BUILD changes.

We’ll use the LLVM project’s `clang-tidy` tool to find possible programming mistakes, and the `clang-format` tool to reformat the whitespace in our code.

# Linting

We already have a `.clang-tidy` file in the repository. This is used by the `clangd` editor extension we installed earlier, and you may have noticed warning underlines like the following:

<img src="https://mintcdn.com/aspectbuild/gtqBKXWWd-jWHweY/learning/bazel-104/clang-tidy.png?fit=max&auto=format&n=gtqBKXWWd-jWHweY&q=85&s=42a0b96f4057857ec5ea0f266842d7da" alt="Screenshot 2025-06-04 at 4.02.00 PM.png" width="1440" height="538" data-path="learning/bazel-104/clang-tidy.png" />

This is already great for any developers who have their editor setup this way. They can see warnings or errors based on the `.clang-tidy` configuration, and accept any auto-fixes it provides.

However developers might choose to ignore the warnings. We can run clang-tidy with Bazel as well. Our approach doesn’t require any changes to `BUILD` files, as the `cc_library` targets already supply the “bare facts” about the code, and shouldn’t have to specify what to do with it.

Look in the `tools/lint` folder. You’ll see a `clang_tidy` target in `tools/lint/BUILD` that runs the tool. In order to run it over existing targets, we use a Bazel feature called “aspects”. The `clang_tidy` aspect is declared in `tools/lint/linters.bzl`.

The Aspect CLI’s [`lint`](/docs/cli/tasks/lint) task applies that aspect for you and prints the results directly, rather than leaving them in `bazel-bin` for you to hunt down:

```bash theme={null}
% aspect lint :all
INFO: Analyzed target //src:magic (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src:magic up-to-date (nothing to build)
Aspect //tools/lint:linters.bzl%clang_tidy of //src:magic up-to-date:
  bazel-bin/src/magic.AspectRulesLintClangTidy.out
  bazel-bin/src/magic.AspectRulesLintClangTidy.out.exit_code
  bazel-bin/src/magic.AspectRulesLintClangTidy.patch
INFO: Elapsed time: 0.113s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
Lint results for //src:magic:

6796 warnings generated.
warning: redefining builtin macro [clang-diagnostic-builtin-macro-redefined]
/private/var/folders/8n/7cfngjb106sgwb8mr1tytx700000gn/T/rules_lint_patcher-oheSnn/_main/src/magic.c:17:9: warning: the value returned by this function should be used [cert-err33-c]
        fprintf(stderr, "Failed to initialize libmagic\n");
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/var/folders/8n/7cfngjb106sgwb8mr1tytx700000gn/T/rules_lint_patcher-oheSnn/_main/src/magic.c:17:9: note: cast the expression to void to silence this warning
/private/var/folders/8n/7cfngjb106sgwb8mr1tytx700000gn/T/rules_lint_patcher-oheSnn/_main/src/magic.c:23:9: warning: the value returned by this function should be used [cert-err33-c]
        fprintf(stderr, "Cannot load magic database: %s\n", magic_error(magic));
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/var/folders/8n/7cfngjb106sgwb8mr1tytx700000gn/T/rules_lint_patcher-oheSnn/_main/src/magic.c:23:9: note: cast the expression to void to silence this warning
/private/var/folders/8n/7cfngjb106sgwb8mr1tytx700000gn/T/rules_lint_patcher-oheSnn/_main/src/magic.c:31:9: warning: the value returned by this function should be used [cert-err33-c]
        fprintf(stderr, "Error determining MIME type: %s\n", magic_error(magic));
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/var/folders/8n/7cfngjb106sgwb8mr1tytx700000gn/T/rules_lint_patcher-oheSnn/_main/src/magic.c:31:9: note: cast the expression to void to silence this warning
Suppressed 6790 warnings (6790 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.
```

<Info>
  With the [`tools/bazel` wrapper](/docs/cli/install#keep-your-team-typing-bazel-with-the-tools/bazel-wrapper) installed, your team can keep typing `bazel lint :all` and Bazelisk routes it through the Aspect CLI.
</Info>

<Note>
  `aspect lint` wraps `aspect_rules_lint`'s aspects. If you can't use the Aspect CLI, you can apply the aspect by hand with vanilla Bazel — `bazel build --aspects=//tools/lint:linters.bzl%clang_tidy //src:all` — which adds clang-tidy build actions to the `cc_library` targets it visits (cached and remotable like any other action) and leaves the report at `bazel-bin/src/magic.AspectRulesLintClangTidy.out`. rules\_lint also ships an example [`lint.sh`](https://github.com/aspect-build/rules_lint/blob/main/example/lint.sh) that wraps that invocation. The CLI exists so you don't have to.
</Note>
