5

I'm teaching myself C++ and working on a small project with Bazel. I'd like to make sure I'm writing safe code and following reasonable best practices, but I'm not sure how to go about doing so. I'm aware of several static analysis tools such as tsan and other analyzers, clang-tidy, or cpplint.

However I'm not sure how I'm supposed to go about setting these tools up with Bazel. Some poking around has found custom-looking solutions such as Drake (see cpplint.bzl) or apollo, but it seems weird to need to write a bunch of custom build toolchain logic in order to make these work. Is there a proper way to set these up?

dimo414
  • 47,227
  • 18
  • 148
  • 244

2 Answers2

0

I don't have a great answer yet, and I'm still surprised it's this manual, but I have at least got cpplint.py and clang-tidy working, like so:

cpplint

I added this target to my src/BUILD file (you'll want to configure --filter as needed):

py_test(
    name = "cpplint",
    srcs = ["@google_styleguide//:cpplint/cpplint.py"],
    data = [":all_cpp_files"],
    # Not sure if there's a better way to express the paths to the src/ dir
    # Drake uses the location oparator, but needs to jump through hoops to get the list of targets
    args = ["--root=src", "--linelength=100", "--counting=detailed",
            "--filter=..."] +
        ["src/%s" % f for f in glob(["**/*.cc", "**/*.h"])],
    main = "cpplint.py",
    python_version = "PY2",
)

The @google_styleguide workspace is defined like so:

new_git_repository(
    name = "google_styleguide",
    remote = "https://github.com/google/styleguide",
    commit = "26470f9ccb354ff2f6d098f831271a1833701b28",
    build_file = "@//:google_styleguide.BUILD",
)

clang-tidy

I created a custom shell script that roughly looks like this (you'll need to tune which checks you want to enable/disable):

execution_root=$(bazel info execution_root) || exit

clang-tidy \
  -warnings-as-errors=* \
  -header-filter=src/.* \
  -checks="${checks}" \
  "src/"*.cc \
  -- \
    -I "${execution_root}/external/googletest/googletest/include/" \
    -I "${execution_root}/external/absl/" \
    -I "${execution_root}/external/gsl/include/" \
    -I .
dimo414
  • 47,227
  • 18
  • 148
  • 244
  • Did you manually add BUILD file in styleguide repo. I am seeing the following: `Error in read: Unable to load package for //:google_styleguide.BUILD: BUILD file not found in any of the following directories. Add a BUILD file to a directory to mark it as a package.` – edc Feb 13 '22 at 17:23
  • It's been a little while since I wrestled with this, so I could be forgetting this, but I don't imagine I made any local changes to the Google Styleguide repo; I was just using it as a reference. – dimo414 Feb 13 '22 at 21:58
0

I needed to add file //cpplint.BUILD and set visibility for @dimo414 solution to work.

//cpplint.BUILD

package(default_visibility = ["//visibility:public"])

py_binary(
    name = "cpplint",
    srcs = ["cpplint.py"],
)

//WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "cpplint_archive",
    build_file = "@//:cpplint.BUILD",
    sha256 = "b2979ff630299293f23c52096e408f2b359e2e26cb5cdf24aed4ce53e4293468",
    strip_prefix = "cpplint-1.2.2",
    url = "https://pypi.python.org/packages/source/c/cpplint/cpplint-1.2.2.tar.gz",
)

Last is Python test target.

//solution/BUILD

py_test(
    name = "solution_cpplint_test",
    srcs = ["@cpplint_archive//:cpplint"],
    args = ["solution/%s" % f for f in glob([
        "**/*.cc",
        "**/*.h",
    ])],
    data = [":solution_filegroup"],
    main = "cpplint.py",
)

To run:

$ bazel test solution_cpplint_test
edc
  • 99
  • 1
  • 8