Open darkcrawler01 opened 8 years ago
No current plans. If you have experience building Bazel plugins and are interested in contributing one for Infer, that would be awesome!
Infer has support for Buck which is similar to Bazel. It works by redirecting to Infer the compiler invocations. Using the same approach may work for Bazel too. The code is here: https://github.com/facebook/infer/blob/master/infer/lib/python/inferlib/bucklib.py
@jeremydubreil @sblackshear - With the last release I noticed that Infer has support for clang compilation databases. Assuming we can get Bazel to output this would that be the preferred method for integration?
[Clang] Improved support for cmake and Xcode compilation databases. Use with infer --compilation-database compile_commands.json (for cmake and Buck), or with infer --compilation-database-escaped compile_commands.json (for xcbuild and xcpretty).
@rahul-malik I would recommend using compilation dbs to integrate with Bazel. I don't think infer can reasonably support a large range of build systems "natively". Going through an intermediate compilation DB is a more scalable solution.
Note however that infer doesn't support running its Java frontend using compilation DBs yet. Let us know if that'd be helpful to add for you (are there tools out there that output Java compilation databases?).
@jvillard - Thanks! The compilation db should work well since we're only interested in analyzing our targets which are compiled with llvm/clang which already supports outputting a compilation database (I'm unaware of any Java compilation db as well).
@shs96c Is there any issue with getting the clang database out then passing that to infer capture --compilation-database compile_commands.json
?
I'd like to also check java code :)
If we're adding support for multiple languages and couldn't use a clang db, the extra actions API could be used to capture the compiler invocations:
https://docs.bazel.build/versions/master/be/extra-actions.html
@shs96c: For the Java side, could we reuse for Bazel the same strategy as used with Buck, which is to specify the path to an external javac compiler pointing to Infer? Buck basically calls Infer this way:
buck build --config tools.javac=/path/to/infer <rest of the buck command>
This option to specify an external Java compiler was originally added to Buck specifically for the integration with Infer so I don't know if there is something equivalent for Bazel.
I remember it being added very well :) There's a java_toolchain
option in
Bazel that might work:
https://docs.bazel.build/versions/master/be/java.html#java_toolchain
I'm not sure what a JavaBuilder
is in this context, but the docs suggest
it expects the javac to be a jar, not an executable.
On Thu, Sep 14, 2017 at 8:25 AM, Jeremy Dubreil notifications@github.com wrote:
@shs96c https://github.com/shs96c: For the Java side, could we reuse for Bazel the same strategy as used with Buck, which is to specify the path to an external javac compiler pointing to Infer? Buck basically calls Infer this way:
buck build --config tools.javac=/path/to/infer
This option to specify an external Java compiler was originally added to Buck specifically for the integration with Infer so I don't know if there is something equivalent for Bazel.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/facebook/infer/issues/457#issuecomment-329397095, or mute the thread https://github.com/notifications/unsubscribe-auth/AABuRW5F8kBJYBVBzbSs7Npgke60h_Gnks5siNTpgaJpZM4J2eRG .
@shs96c JavaBuilder is Bazel wrapper around Javac invocation, that does some magic:
However, in very recent Bazel version there is an easy way to use so called VanillaJavaBuilder to skip all the magic I mentioned above.
Gerrit Code Review uses this invocation to support most recent Java versions, that are not supported yet by Bazel natively. With this CL: [1] pending for review you could say something like this in gerrit tree:
$ bazel build --host_javabase=:absolute_javabase \
--define=ABSOLUTE_JAVABASE=/usr/lib64/jvm/java-11 \
--define=USE_ABSOLUTE_JAVABASE=true \
--host_java_toolchain=//:toolchain_vanilla \
--java_toolchain=//:toolchain_vanilla \
:release
Instead of passing /usr/lib64/jvm/java-11
I could pass the path to infer and that would probably solve infer integration for Bazel?
[1] https://gerrit-review.googlesource.com/c/gerrit/+/194040
If I try to pass: bazel build --define=ABSOLUTE_JAVABASE=/usr/local/bin/infer
, then it doesn't work, as Bazel tries to add bin/java
to this Java home directory:
java.io.IOException: Cannot run program "/usr/local/bin/infer/bin/java" (in directory "/home/jenkins/.cache/bazel/_bazel_jenkins/bb2dc09ec74ab7b7157cd89c2ef96641/execroot/gerrit"): error=20, Not a directory
Next attempt is to try to pass: --define=ABSOLUTE_JAVABASE=/opt/infer
and link /opt/infer/bin/java
to infer
itself:
$ /opt/infer/bin/java --version
Infer version v0.15.0
Copyright 2009 - present Facebook. All Rights Reserved.
Then calling bazel build still failing with /opt/infer-linux64-v0.15.0/lib/infer/infer/bin/infer: unknown option '-jar'.
:
$ bazel build --define=ABSOLUTE_JAVABASE=/opt/infer \
--host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
--host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
--java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla :headless
[...]
INFO: Analysed target //:headless (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
ERROR: /home/jenkins/gerrit/java/com/google/gerrit/server/BUILD:9:1: Building java/com/google/gerrit/server/libconstants.jar (1 source file) failed: Worker process did not return a WorkResponse:
---8<---8<--- Start of log, file at /home/jenkins/.cache/bazel/_bazel_jenkins/bb2dc09ec74ab7b7157cd89c2ef96641/bazel-workers/worker-9-Javac.log ---8<---8<---
/opt/infer-linux64-v0.15.0/lib/infer/infer/bin/infer: unknown option '-jar'.
Infer version v0.15.0
Copyright 2009 - present Facebook. All Rights Reserved.
Usage: infer command [options]
See `infer --help` for more information.
---8<---8<--- End of log ---8<---8<---
I think it might be easier to migrate build tool chain from Bazel to Buck to make infer
work.
@cushon Any idea, how we could hijack javac
to call infer
in Bazel driven build?
The problem is, that before switch from Buck to Bazel JGit/Gerrit community was able to run all the code base through infer
. After migration to Bazel we lost that ability ;-(
is there any update or plan for this topic? bazel
become more and more popular, it would be cool to support it.
Also interested! @martinoluca don't think you can escape from my feature requests just because I'm on the other side of the world.
An aspect to provide alternative targets would probably work too.
Gentle nudge :)
@shs96c At @muse-dev we decompose many build systems into a machine readable description of the build steps (think javac ... ; javac ... ; ...
or gcc ...
) then feed those steps to several analyzers, infer among them. It shouldn't be hard to support bazel if we could just gain some insight into how to extract the invocations. Since you seem interested in this topic perhaps you are well-versed enough in Bazel and invested enough to teach me?
@TomMD extracting build steps in that fashion sounds interesting but I presume you would be using internal APIs which historically have been changing a lot.
As pointed out in my previous comment, the inspiration could be the current implementation of VanillaJavaBuilder.java#run:[1] method that is calling vanilla javac
:
CompilationTask task =
javaCompiler.getTask(
new PrintWriter(output, true),
fileManager,
diagnosticCollector,
JavacOptions.removeBazelSpecificFlags(optionsParser.getJavacOpts()),
ImmutableList.<String>of() /*classes*/,
sources);
setProcessors(optionsParser, fileManager, task);
ok = task.call();
The idea would be to have InferJavaBuilder.java
and shell out to infer
instead of vanilla javac
.
Another question is how to teach infer
to run preprocessors for code generation? One approach would be to let javac
run the preprocessors, and then run infer
with only (second) compile task.
Moreover, new toolchain should be added to bazel
that understands new InferJavabuilder
, and invoked like this:
$ bazel build \
--define=PATH_TO_INFER=/opt/infer \
--host_java_toolchain=@bazel_tools//tools/jdk:toolchain_infer \
--java_toolchain=@bazel_tools//tools/jdk:toolchain_infer \
//...
To make it even more generic, it could be called GenericJavaBuilder.java
so that it would work with any static analyser and not just with infer
.
It's pretty straightforward to create an extra action that runs Infer. Here's a Gist link: https://gist.github.com/ulfjack/c66180584f9efb9e9768bf8999ffcd8a
Use like this:
bazel build //src/main/java/... --experimental_action_listener=//src/infer/java/com/engflow/infer --spawn_strategy=local
If anyone is still interested this for (Objective-)C(++) and wants to use compile_commands.json, we built https://github.com/hedronvision/bazel-compile-commands-extractor which should make getting a compile_commands.json from Bazel easy and fast.
(extra_actions have been deprecated, unfortunately, though that otherwise seems like a great solution for running it alongside a build.)
Does anyone have experience running infer via compile_commands.json and caching/getting fast incremental rebuilds?
https://github.com/bazelbuild/bazel