Run clang-tidy on Bazel C++ targets. This project is heavily inspired by
bazel_clang_tidy but has options
to enable or disable checks as aspect arguments.
MODULE
# //:.bazelrc
common --registry=https://raw.githubusercontent.com/digiboys/bazel-registry/main
common --registry=https://bcr.bazel.build# //:MODULE.bazel
bazel_dep(
name = "rules_clang_tidy",
version = "0.0.0",
dev_dependency = True
)WORKSPACE
# //:WORKSPACE.bazel
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_repository")
RULES_CLANG_TIDY_COMMIT = ...
http_repository(
name = "rules_clang_tidy",
integrity = ...,
strip_prefix = "rules_clang_tidy-{commit}".format(
commit = RULES_CLANG_TIDY_COMMIT,
),
url = "https://github.com/oliverlee/rules_clang_tidy/archive/{commit}.tar.gz".format(
commit = RULES_CLANG_TIDY_COMMIT,
),
)
load("@rules_clang_tidy//:dependencies.bzl", "rules_clang_tidy_dependencies")
rules_clang_tidy_dependencies()# //:.bazelrc
build:clang-tidy --aspects=@rules_clang_tidy//:aspects.bzl%check
build:clang-tidy --output_groups=report
build:clang-tidy --remote_download_outputs=toplevel
build:clang-tidy --keep_goingPerform static analysis with
bazel build //... --config=clang-tidyThis will use clang-tidy in your PATH and .clang-tidy
defined in this repository.
To specify a specific binary (e.g. clang-tidy is specified by a hermetic
toolchain like this), update
the build setting in .bazelrc.
# //:.bazelrc
build --@rules_clang_tidy//:clang-tidy=@llvm18//:clang-tidy
build:clang-tidy --aspects=@rules_clang_tidy//:aspects.bzl%check
build:clang-tidy --output_groups=report
build:clang-tidy --remote_download_outputs=toplevel
build:clang-tidy --keep_goingTo override the default .clang-tidy, define a filegroup containing the
replacement config and update build setting in .bazelrc.
# //:BUILD.bazel
filegroup(
name = "clang-tidy-config",
srcs = [".clang-tidy"],
visibility = ["//visibility:public"],
)# //:.bazelrc
build --@rules_clang_tidy//:config=//:clang-tidy-config
build:clang-tidy --aspects=@rules_clang_tidy//:aspects.bzl%check
build:clang-tidy --output_groups=report
build:clang-tidy --remote_download_outputs=toplevel
build:clang-tidy --keep_goingTo apply fixes, run @rules_clang_tidy//:apply-fixes. This uses the exported
fixes generated by the check aspect in the output_path.
bazel build //... --config=clang-tidy
bazel run @rules_clang_tidy//:apply-fixes -- $(bazel info output_path)If only a subset of checks needs to be run, those can be specified with
extra-options. This flag can be specified multiples times.
bazel build //... --config=clang-tidy \
--@rules_clang_tidy//:extra-options="--checks=-*,misc-unused-alias-decls"
bazel run @rules_clang_tidy//:apply-fixes -- $(bazel info output_path)Alternatively, use rule apply_fixes and specify the dependencies for the
target.
load("@rules_clang_tidy//:defs.bzl", "apply_fixes")
apply_fixes(
name = "apply-fixes",
deps = [
...
],
desired_deps = "//...", # requires Bazel 7.1.0
testonly = True, # if deps includes cc_test targets
)and run the apply_fixes target
bazel run //:apply-fixes
# or generate and apply fixes for only a single check
bazel run //:apply-fixes \
--@rules_clang_tidy//:extra-options="--checks=-*,misc-unused-alias-decls*"Both the apply-fixes executable target and the apply_fixes rule use the
binary specified with --@rules_clang_tidy//:clang-apply-replacements. If not
set, clang-apply-replacements must be in PATH. Similarly to
--@rules_clang_tidy//:clang-tidy, it's convenient to define the value in
.bazelrc.
# //:.bazelrc
build --@rules_clang_tidy//:clang-apply-replacements=@llvm18//:clang-apply-replacements- Bazel 5.x
- ClangTidy ?? (at least 14?)