I would like to use bazel with clang's static analysis tool, scan-build, but it appears scan-build doesn't pick up bazel's build execution steps.
If I preface bazel build with scan-build it doesn't detect any compilation:
$ /usr/bin/scan-build-3.8 bazel build //...
scan-build: Using '/usr/lib/llvm-3.8/bin/clang' for static analysis
...compiling a bunch of stuff...
scan-build: Removing directory '/tmp/scan-build-2016-08-10-002447-6841-1' because it contains no reports.
scan-build: No bugs found.
I can force every compilation step to run scan-build by modifying CROSSTOOL as follows, but this isn't ideal as it creates a scan-build report for every file:
# Inject scan-build before clang
tool_path { name: "gcc" path: "/usr/bin/scan-build-3.8" }
compiler_flag: "/usr/lib/llvm-3.8/bin/clang"
Has anyone else looked into scan-build support?
@lberki do you have any idea?
I don't think you can work around this without telling Bazel about scan-build. Quoting its web page:
_"scan-build has little or no knowledge about how you build your code. It works by overriding the CC and CXX environment variables to (hopefully) change your build to use a "fake" compiler instead of the one that would normally build your project"_
Bazel does use the CC environment variable to look up the C++ compiler, but once it finds it, further changes to CC are not detected, unless you do a bazel clean in between.
Whereas we now have a good story about handling environment variables during actions (http://www.bazel.io/docs/designs/2016/06/21/environment.html), we haven't made up our minds yet about environment variables for environment detection.
@damienmg thinks things are fine the way they are today. @aehlig also had a strong opinion on the matter.
My goal is to get clang static analysis running regularly against our codebase. scan-build (and the associated scan-view) are handy because they give you a full report on precisely how clang static analysis discovered a problem.
If I didn't care about understanding how clang found a problem--only that there was a problem--then I can accomplish that by passing the --analyze option to clang. This produces a warning for every static analysis issue detected by clang.
Problem with --analyze is it writes an XML report into the file specified for output with -o instead of an object file. It skips compilation. So if I add --analyze to my cpp options then bazel blows up on the linker step with "file format not recognized" errors.
So is there a way to either:
clang and clang --analyze in parallel?For (1), you can try the --compile_only command line option.
For (2), the usual solution is to write your own CROSSTOOL file where the "compiler" Bazel calls is a script that calls the actual compiler twice.
I was finally able to get clang analyzer working with bazel. The trick was to build a compilation database during the build and then execute a script to convert those compile commands into clang --analyze commands.
Here are the steps I took:
Add an experimental_action_listener that generates the compilation database. Forked from this gist, but I had to fix up some json formatting that the clang tools didn't like.
Install the scan-build clang analyzer wrapper tool.
Fiddle with bazel paths and permissions for hours until it finally worked.
Readme and a scattering of files that worked for me:
https://github.com/cybrown-zoox/bazel-clang-analyzer
I was pointed to all this from this discussion thread.
Side note - I assume you could also modify the action_listener to just directly execute the clang --analyze command at the same time as the build, rather than doing this in steps.
Yes, action_listener / extra_action is intended for exactly this use case, and that's how we use it internally.
Most helpful comment
I was finally able to get clang analyzer working with bazel. The trick was to build a compilation database during the build and then execute a script to convert those compile commands into
clang --analyzecommands.Here are the steps I took:
Add an experimental_action_listener that generates the compilation database. Forked from this gist, but I had to fix up some json formatting that the clang tools didn't like.
Install the scan-build clang analyzer wrapper tool.
Fiddle with bazel paths and permissions for hours until it finally worked.
Readme and a scattering of files that worked for me:
https://github.com/cybrown-zoox/bazel-clang-analyzer
I was pointed to all this from this discussion thread.