[buck-java-flavor] integrate with buck using java flavor

Summary: New, experimental for now, integration with buck on Java using the `#infer-java-capture` flavor.

Reviewed By: artempyanykh

Differential Revision: D22187748

fbshipit-source-id: 62cdafe6b
master
Nikos Gorogiannis 4 years ago committed by Facebook GitHub Bot
parent 270918fea7
commit 697f9c0a47

@ -182,7 +182,7 @@ endif
ifneq ($(BUCK),no)
BUILD_SYSTEMS_TESTS += genrulecapture
BUILD_SYSTEMS_TESTS += genrulecapture buck_java_flavor
endif
ifneq ($(MVN),no)
BUILD_SYSTEMS_TESTS += mvn

@ -143,6 +143,16 @@ BUCK OPTIONS
Activates: Buck integration for Java targets. (Conversely:
--no-buck-java)
--buck-java-flavor
Activates: Buck integration for Java which uses the buck flavor
#infer-java-capture instead of genrules like buck-java.
(Conversely: --no-buck-java-flavor)
--buck-java-flavor-suppress-config
Activates: Suppress setting buck config values for the infer
binary and its version in the buck-java-flavor integration.
(Conversely: --no-buck-java-flavor-suppress-config)
--buck-merge-all-deps
Activates: Find and merge all infer dependencies produced by buck.
Use this flag if infer doesn't find any files to analyze after a

@ -158,6 +158,17 @@ OPTIONS
Activates: Buck integration for Java targets. (Conversely:
--no-buck-java) See also infer-capture(1).
--buck-java-flavor
Activates: Buck integration for Java which uses the buck flavor
#infer-java-capture instead of genrules like buck-java.
(Conversely: --no-buck-java-flavor) See also infer-capture(1).
--buck-java-flavor-suppress-config
Activates: Suppress setting buck config values for the infer
binary and its version in the buck-java-flavor integration.
(Conversely: --no-buck-java-flavor-suppress-config)
See also infer-capture(1).
--buck-merge-all-deps
Activates: Find and merge all infer dependencies produced by buck.
Use this flag if infer doesn't find any files to analyze after a

@ -158,6 +158,17 @@ OPTIONS
Activates: Buck integration for Java targets. (Conversely:
--no-buck-java) See also infer-capture(1).
--buck-java-flavor
Activates: Buck integration for Java which uses the buck flavor
#infer-java-capture instead of genrules like buck-java.
(Conversely: --no-buck-java-flavor) See also infer-capture(1).
--buck-java-flavor-suppress-config
Activates: Suppress setting buck config values for the infer
binary and its version in the buck-java-flavor integration.
(Conversely: --no-buck-java-flavor-suppress-config)
See also infer-capture(1).
--buck-merge-all-deps
Activates: Find and merge all infer dependencies produced by buck.
Use this flag if infer doesn't find any files to analyze after a

@ -24,24 +24,25 @@ type t =
| CombinedGenrule
| ClangFlavors
| ClangCompilationDB of clang_compilation_db_deps
| JavaFlavor
| JavaGenruleMaster
let is_java_genrule_master_or_combined = function
| JavaGenruleMaster | CombinedGenrule ->
true
| ClangFlavors | ClangCompilationDB _ ->
| ClangFlavors | ClangCompilationDB _ | JavaFlavor ->
false
let is_clang_compilation_db = function
| ClangCompilationDB _ ->
true
| ClangFlavors | JavaGenruleMaster | CombinedGenrule ->
| ClangFlavors | JavaGenruleMaster | CombinedGenrule | JavaFlavor ->
false
let is_clang_flavors = function
| ClangFlavors ->
true
| ClangCompilationDB _ | JavaGenruleMaster | CombinedGenrule ->
| ClangCompilationDB _ | JavaGenruleMaster | CombinedGenrule | JavaFlavor ->
false

@ -17,6 +17,7 @@ type t =
| CombinedGenrule
| ClangFlavors
| ClangCompilationDB of clang_compilation_db_deps
| JavaFlavor
| JavaGenruleMaster
val is_java_genrule_master_or_combined : t -> bool

@ -703,6 +703,13 @@ and buck_compilation_database_depth =
~meta:"int"
and buck_java_flavor_suppress_config =
CLOpt.mk_bool ~long:"buck-java-flavor-suppress-config" ~default:false
~in_help:InferCommand.[(Capture, manual_buck)]
"Suppress setting buck config values for the infer binary and its version in the \
buck-java-flavor integration."
and buck_merge_all_deps =
CLOpt.mk_bool ~long:"buck-merge-all-deps" ~default:false
~in_help:InferCommand.[(Capture, manual_buck)]
@ -749,6 +756,12 @@ and buck_mode =
~f:(set_mode `CombinedGenrule)
"Buck integration for clang-based and Java targets."
|> ignore ;
CLOpt.mk_bool ~long:"buck-java-flavor"
~in_help:InferCommand.[(Capture, manual_buck)]
~f:(set_mode `JavaFlavor)
"Buck integration for Java which uses the buck flavor #infer-java-capture instead of genrules \
like buck-java."
|> ignore ;
buck_mode
@ -2638,6 +2651,8 @@ and buck_build_args_no_inline = !buck_build_args_no_inline
and buck_cache_mode = (!buck || !genrule_mode) && not !debug
and buck_java_flavor_suppress_config = !buck_java_flavor_suppress_config
and buck_merge_all_deps = !buck_merge_all_deps
and buck_mode : BuckMode.t option =
@ -2656,6 +2671,8 @@ and buck_mode : BuckMode.t option =
Some (ClangCompilationDB (DepsUpToDepth depth))
| `CombinedGenrule, _ ->
Some CombinedGenrule
| `JavaFlavor, _ ->
Some JavaFlavor
and buck_targets_blacklist = !buck_targets_blacklist

@ -53,6 +53,8 @@ val bin_dir : string
val bound_error_allowed_in_procedure_call : bool
val buck_java_flavor_suppress_config : bool
val clang_exe_aliases : string list
val clang_initializer_prefix : string

@ -83,6 +83,8 @@ module Target = struct
add_flavor_internal target "compilation-database"
| ClangFlavors, Compile | JavaGenruleMaster, _ | CombinedGenrule, _ ->
target
| JavaFlavor, _ ->
add_flavor_internal target "infer-java-capture"
| ClangFlavors, _ ->
add_flavor_internal target "infer-capture-all"
end
@ -197,7 +199,7 @@ let get_accepted_buck_kinds_pattern (mode : BuckMode.t) =
"^(apple|cxx)_(binary|library|test)$"
| ClangFlavors ->
"^(apple|cxx)_(binary|library)$"
| JavaGenruleMaster ->
| JavaGenruleMaster | JavaFlavor ->
"^(java|android)_library$"
@ -216,6 +218,12 @@ let config =
let get_java_genrule_config () =
["infer.version=" ^ Version.versionString; "infer.mode=capture"]
in
let get_java_flavor_config () =
if Config.buck_java_flavor_suppress_config then []
else
[ "infer_java.version=" ^ Version.versionString
; Printf.sprintf "infer_java.binary=%s/infer" Config.bin_dir ]
in
let get_flavors_config () =
[ "client.id=infer.clang"
; Printf.sprintf "*//infer.infer_bin=%s" Config.bin_dir
@ -241,6 +249,8 @@ let config =
match (buck_mode : BuckMode.t) with
| JavaGenruleMaster ->
get_java_genrule_config ()
| JavaFlavor ->
get_java_flavor_config ()
| ClangFlavors ->
get_flavors_config ()
| CombinedGenrule ->
@ -256,7 +266,7 @@ let resolve_pattern_targets (buck_mode : BuckMode.t) targets =
|> ( match buck_mode with
| ClangFlavors | ClangCompilationDB NoDependencies ->
Fn.id
| CombinedGenrule | ClangCompilationDB DepsAllDepths | JavaGenruleMaster ->
| CombinedGenrule | ClangCompilationDB DepsAllDepths | JavaGenruleMaster | JavaFlavor ->
Query.deps None
| ClangCompilationDB (DepsUpToDepth depth) ->
Query.deps (Some depth) )
@ -347,7 +357,7 @@ let parse_command_and_targets (buck_mode : BuckMode.t) original_buck_args =
match (buck_mode, parsed_args) with
| ClangFlavors, {pattern_targets= []; alias_targets= []; normal_targets} ->
normal_targets
| ( (ClangFlavors | CombinedGenrule | JavaGenruleMaster | ClangCompilationDB _)
| ( (ClangFlavors | CombinedGenrule | JavaGenruleMaster | ClangCompilationDB _ | JavaFlavor)
, {pattern_targets; alias_targets; normal_targets} ) ->
pattern_targets |> List.rev_append alias_targets |> List.rev_append normal_targets
|> resolve_pattern_targets buck_mode

@ -7,5 +7,8 @@
open! IStd
val infer_deps_of_build_report : string -> unit
(** parse a buck build report and construct resulting [infer-deps.txt] *)
val capture : BuckMode.t -> string list -> unit
(** do genrule capture with the given buck command line *)

@ -0,0 +1,39 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
module L = Logging
let capture build_cmd =
let prog, buck_cmd = (List.hd_exn build_cmd, List.tl_exn build_cmd) in
L.progress "Querying buck for java flavor capture targets...@." ;
let time0 = Mtime_clock.counter () in
let BuckFlavors.{command; rev_not_targets; targets} =
BuckFlavors.add_flavors_to_buck_arguments JavaFlavor ~extra_flavors:[] buck_cmd
in
L.progress "Found %d java flavor capture targets in %a.@." (List.length targets) Mtime.Span.pp
(Mtime_clock.count time0) ;
let all_args = List.rev_append rev_not_targets targets in
let build_report_file =
Filename.temp_file ~in_dir:(ResultsDir.get_path Temporary) "buck_build_report" ".json"
in
let updated_buck_cmd =
(* make buck tell us where in buck-out are the capture directories for merging *)
(prog :: command :: "--build-report" :: build_report_file :: Buck.config JavaFlavor)
@ List.rev_append Config.buck_build_args_no_inline (Buck.store_args_in_file all_args)
in
L.(debug Capture Quiet)
"Processed buck command '%a'@." (Pp.seq F.pp_print_string) updated_buck_cmd ;
if List.is_empty targets then L.external_warning "WARNING: found no buck targets to analyze.@."
else
let time0 = Mtime_clock.counter () in
Buck.wrap_buck_call ~label:"build" updated_buck_cmd |> ignore ;
BuckGenrule.infer_deps_of_build_report build_report_file ;
L.progress "Java flavor capture took %a.@." Mtime.Span.pp (Mtime_clock.count time0) ;
ResultsDir.RunState.set_merge_capture true ;
()

@ -0,0 +1,11 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
val capture : string list -> unit
(** do java capture using flavors with the given buck command line *)

@ -22,6 +22,7 @@ type mode =
| BuckCompilationDB of {deps: BuckMode.clang_compilation_db_deps; prog: string; args: string list}
| BuckGenrule of {prog: string}
| BuckGenruleMaster of {build_cmd: string list}
| BuckJavaFlavor of {build_cmd: string list}
| Clang of {compiler: Clang.compiler; prog: string; args: string list}
| ClangCompilationDB of {db_files: [`Escaped of string | `Raw of string] list}
| Gradle of {prog: string; args: string list}
@ -49,6 +50,8 @@ let pp_mode fmt = function
F.fprintf fmt "BuckGenRule driver mode:@\nprog = '%s'" prog
| BuckGenruleMaster {build_cmd} ->
F.fprintf fmt "BuckGenrule driver mode:@\nbuild command = %a" Pp.cli_args build_cmd
| BuckJavaFlavor {build_cmd} ->
F.fprintf fmt "BuckJavaFlavor driver mode:@\nbuild command = %a" Pp.cli_args build_cmd
| Clang {prog; args} ->
F.fprintf fmt "Clang driver mode:@\nprog = '%s'@\nargs = %a" prog Pp.cli_args args
| ClangCompilationDB _ ->
@ -137,6 +140,9 @@ let capture ~changed_files = function
| BuckGenruleMaster {build_cmd} ->
L.progress "Capturing for BuckGenruleMaster integration...@." ;
BuckGenrule.capture JavaGenruleMaster build_cmd
| BuckJavaFlavor {build_cmd} ->
L.progress "Capturing for BuckJavaFlavor integration...@." ;
BuckJavaFlavor.capture build_cmd
| Clang {compiler; prog; args} ->
if CLOpt.is_originator then L.progress "Capturing in make/cc mode...@." ;
Clang.capture compiler ~prog ~args
@ -258,7 +264,7 @@ let analyze_and_report ?suppress_console_report ~changed_files mode =
&& InferCommand.equal Run Config.command ->
(* if doing capture + analysis of buck with flavors, we always need to merge targets before the analysis phase *)
true
| Analyze | BuckGenruleMaster _ | BuckCombinedGenrule _ ->
| Analyze | BuckGenruleMaster _ | BuckCombinedGenrule _ | BuckJavaFlavor _ ->
ResultsDir.RunState.get_merge_capture ()
| _ ->
false
@ -348,7 +354,7 @@ let assert_supported_build_system build_system =
(`Clang, "buck with flavors")
| Some (ClangCompilationDB _) ->
(`Clang, "buck compilation database")
| Some JavaGenruleMaster ->
| Some (JavaGenruleMaster | JavaFlavor) ->
(`Java, Config.string_of_build_system build_system)
in
assert_supported_mode analyzer build_string
@ -386,6 +392,8 @@ let mode_of_build_command build_cmd (buck_mode : BuckMode.t option) =
BuckClangFlavor {build_cmd}
| BBuck, Some JavaGenruleMaster ->
BuckGenruleMaster {build_cmd}
| BBuck, Some JavaFlavor ->
BuckJavaFlavor {build_cmd}
| BBuck, Some ClangFlavors ->
BuckClangFlavor {build_cmd}
| BClang, _ ->

@ -19,6 +19,7 @@ type mode =
| BuckCompilationDB of {deps: BuckMode.clang_compilation_db_deps; prog: string; args: string list}
| BuckGenrule of {prog: string}
| BuckGenruleMaster of {build_cmd: string list}
| BuckJavaFlavor of {build_cmd: string list}
| Clang of {compiler: Clang.compiler; prog: string; args: string list}
| ClangCompilationDB of {db_files: [`Escaped of string | `Raw of string] list}
| Gradle of {prog: string; args: string list}

@ -0,0 +1,6 @@
[project]
ignore = .git, .ml, .mli
[java]
source_level = 8
target_level = 8

@ -0,0 +1,21 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
TESTS_DIR = ../..
ROOT_DIR = $(TESTS_DIR)/../..
BUCK_TARGET = //module2:module2
CLEAN_EXTRA = buck-out
SOURCES = $(shell find . -name '*.java')
INFERPRINT_OPTIONS = --issues-tests
INFER_OPTIONS = --buck-java-flavor --debug-exceptions
include $(TESTS_DIR)/infer.make
$(INFER_OUT)/report.json: $(MAKEFILE_LIST) $(SOURCES)
$(QUIET) $(REMOVE_DIR) buck-out && \
$(call silent_on_success,Testing java flavor integration in $(TEST_REL_DIR),\
$(INFER_BIN) --results-dir $(@D) $(INFER_OPTIONS) -- buck build --no-cache $(BUCK_TARGET))

@ -0,0 +1,7 @@
java_library(
name='annotations',
srcs=['ThreadSafe.java'],
visibility=[
'PUBLIC'
],
)

@ -0,0 +1,9 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package genrulecapture.annotations;
public @interface ThreadSafe {}

@ -0,0 +1,2 @@
module2/Class2.java, genrulecapture.module2.Class2.get():int, 22, THREAD_SAFETY_VIOLATION, no_bucket, WARNING, [<Read trace>,call to int Class1.get(),access to `this.c.x`,<Write trace>,call to void Class1.set(int),access to `this.c.x`]
module2/Class2.java, genrulecapture.module2.Class2.set(int):void, 18, THREAD_SAFETY_VIOLATION, no_bucket, WARNING, [call to void Class1.set(int),access to `this.c.x`]

@ -0,0 +1,10 @@
java_library(
name='module1',
srcs=glob(["*.java"]),
deps=[
'//annotations:annotations',
],
visibility=[
'PUBLIC'
],
)

@ -0,0 +1,20 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package genrulecapture.module1;
public class Class1 {
int x;
public void set(int d) {
x = d;
}
public int get() {
return x;
}
}

@ -0,0 +1,9 @@
java_library(
name='module2',
srcs=glob(["*.java"]),
deps=[
'//module1:module1',
'//annotations:annotations',
'//module3:module3',
]
)

@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package genrulecapture.module2;
import genrulecapture.annotations.ThreadSafe;
import genrulecapture.module1.Class1;
@ThreadSafe
public class Class2 {
Class1 c;
void set(int x) {
c.set(x);
}
int get() {
return c.get();
}
}

@ -0,0 +1,9 @@
cxx_library(
name = 'module3',
visibility = [
'PUBLIC',
],
srcs = [
'some_c_code.c',
],
)

@ -0,0 +1,13 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdlib.h>
void some_c_func() {
int* s = NULL;
*s = 42;
}
Loading…
Cancel
Save