[buck] replace python buck integration with ocaml

Reviewed By: jvillard

Differential Revision: D20248852

fbshipit-source-id: c842ccadf
master
Martin Trojer 5 years ago committed by Facebook Github Bot
parent ca06b7840c
commit 284c6fdb3b

@ -1,253 +0,0 @@
# 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.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import logging
import os
import shutil
import subprocess
import tempfile
import traceback
import time
from inferlib import config, issues, utils
from . import util
import re
MODULE_NAME = __name__
MODULE_DESCRIPTION = '''Run analysis of code built with a command like:
buck [options] [target]
Analysis examples:
infer --buck-clang -- buck build HelloWorld'''
LANG = ['clang']
KEEP_GOING_OPTION = "--keep-going"
def gen_instance(*args):
return BuckAnalyzer(*args)
def string_in_quotes(value):
return value.strip('\'')
def create_argparser(group_name=MODULE_NAME):
"""This defines the set of arguments that get added by this module to the
set of global args defined in the infer top-level module
Do not use this function directly, it should be invoked by the infer
top-level module"""
parser = argparse.ArgumentParser(add_help=False)
group = parser.add_argument_group(
'{grp} module'.format(grp=MODULE_NAME),
description=MODULE_DESCRIPTION,
)
group.add_argument('--xcode-developer-dir',
help='Specify the path to Xcode developer directory ')
group.add_argument('--blacklist-regex',
help='Specify the regex for files to skip during '
'the analysis')
group.add_argument('--Xbuck', action='append', default=[],
type=string_in_quotes,
help='Pass values as command-line arguments to '
'invocations of `buck build`.'
'NOTE: value should be wrapped in single quotes')
group.add_argument('--buck-merge-all-deps',
action='store_true',
help='Find and merge all deps produced by buck')
return parser
class BuckAnalyzer:
def __init__(self, args, cmd):
self.args = args
self.cmd = cmd
self.keep_going = KEEP_GOING_OPTION in self.args.Xbuck
util.log_java_version()
logging.info(util.run_cmd_ignore_fail(['buck', '--version']))
def capture(self):
try:
return self.capture_with_flavors()
except subprocess.CalledProcessError as exc:
if self.args.debug:
traceback.print_exc()
return exc.returncode
def create_cxx_buck_configuration_args(self):
# return a string that can be passed in input to buck
# and configures the paths to infer/clang/plugin/xcode
facebook_clang_plugins_root = config.FCP_DIRECTORY
clang_path = os.path.join(
facebook_clang_plugins_root,
'clang',
'install',
'bin',
'clang',
)
plugin_path = os.path.join(
facebook_clang_plugins_root,
'libtooling',
'build',
'FacebookClangPlugin.dylib',
)
args = [
'--config',
'client.id=infer.clang',
'--config',
'*//infer.infer_bin={bin}'
.format(bin=config.BIN_DIRECTORY),
'--config',
'*//infer.clang_compiler={clang}'.format(clang=clang_path),
'--config',
'*//infer.clang_plugin={plugin}'.format(plugin=plugin_path),
'--config',
'*//cxx.pch_enabled=false',
'--config', # Infer doesn't support C++ modules yet (T35656509)
'*//cxx.modules_default=false',
'--config',
'*//cxx.modules=False',
] + self.args.Xbuck
if self.args.xcode_developer_dir is not None:
args.append('--config')
args.append('apple.xcode_developer_dir={devdir}'.format(
devdir=self.args.xcode_developer_dir))
if self.args.blacklist_regex:
args.append('--config')
args.append('*//infer.blacklist_regex={regex}'.format(
regex=self.args.blacklist_regex))
return args
def _get_analysis_result_paths(self):
# TODO(8610738): Make targets extraction smarter
buck_results_cmd = [
self.cmd[0],
'targets',
'--show-output'
] + self.cmd[2:] + self.create_cxx_buck_configuration_args()
buck_results_cmd = \
[x for x in buck_results_cmd if x != KEEP_GOING_OPTION]
proc = subprocess.Popen(buck_results_cmd, stdout=subprocess.PIPE)
(buck_output, _) = proc.communicate()
if proc.returncode != 0:
return None
# remove target name prefixes from each line and split them into a list
out = [os.path.join(self.args.project_root, x.split(None, 1)[1])
for x in buck_output.strip().split('\n')]
return [os.path.dirname(x)
if os.path.isfile(x) else x
for x in out if os.path.exists(x)]
@staticmethod
def _merge_infer_dep_files(root_paths, merged_out_path):
potential_dep_files = [os.path.join(p, config.INFER_BUCK_DEPS_FILENAME)
for p in root_paths]
dep_files = filter(os.path.exists, potential_dep_files)
utils.merge_and_dedup_files_into_path(dep_files, merged_out_path)
@staticmethod
def _find_deps_and_merge(merged_out_path):
"""This function is used to compute the infer-deps.txt file that
contains the location of the infer-out folders with the captured
files created by buck. This is needed when keep-going is passed
to buck and there are compilation failures, because in that case
buck doesn't create this file."""
infer_out_folders = []
start_time = time.time()
print('finding captured files in buck-out...')
for root, dirs, files in os.walk(config.BUCK_OUT_GEN):
regex = re.compile('.*infer-out.*')
folders = \
[os.path.join(root, d) for d in dirs if re.match(regex, d)]
for d in folders:
if d not in infer_out_folders:
infer_out_folders.append(d)
with open(merged_out_path, 'w') as fmerged_out_path:
for dir in infer_out_folders:
fmerged_out_path.write('\t' + '\t' + dir + '\n')
elapsed_time = time.time() - start_time
print('time elapsed in finding captured files in buck-out: % 6.2fs'
% elapsed_time)
def _find_depsfiles_and_merge(self, merge_out_path):
""" Sometimes buck targets --show-output gets confused and returns a
folder that doesn't contain infer-deps.txt. This can happen with on
for example objc targes with a certain combination of BUCK modes and
flavours. This function will walk buck-out and find infer-deps.txt
It will merge ALL infer-deps.txt in buck-out, so you might want
to do a buck clean first."""
fs = []
for root, dirs, files in os.walk(config.BUCK_OUT_GEN):
fs += [os.path.dirname(os.path.join(root, f)) for f in files
if f == config.INFER_BUCK_DEPS_FILENAME]
self._merge_infer_dep_files(fs, merge_out_path)
def _move_buck_out(self):
""" If keep-going is passed, we may need to compute the infer-deps
file with the paths to the captured files. To make sure that
this is done in a consistent way, we need to start the analysis
with an empty buck-out folder."""
if not os.path.exists(config.BUCK_OUT_TRASH):
os.makedirs(config.BUCK_OUT_TRASH)
tmp = tempfile.mkdtemp(
dir=config.BUCK_OUT_TRASH,
prefix=config.BUCK_OUT)
print('moving files in ' + config.BUCK_OUT + ' to ' + tmp)
for filename in os.listdir(config.BUCK_OUT):
if filename != config.TRASH:
shutil.move(os.path.join(config.BUCK_OUT, filename), tmp)
def _run_buck_with_flavors(self):
env_vars = utils.read_env()
infer_args = env_vars['INFER_ARGS']
if infer_args != '':
infer_args += '^' # '^' must be CommandLineOption.env_var_sep
infer_args += '--fcp-syntax-only'
env_vars['INFER_ARGS'] = infer_args
env = utils.encode_env(env_vars)
command = self.cmd
command += ['-j', str(self.args.multicore)]
if self.args.load_average is not None:
command += ['-L', str(self.args.load_average)]
command += self.create_cxx_buck_configuration_args()
try:
subprocess.check_call(command, env=env)
return os.EX_OK
except subprocess.CalledProcessError as e:
if self.keep_going:
print('Buck failed, but continuing the analysis '
'because --keep-going was passed')
return -1
else:
raise e
def capture_with_flavors(self):
if self.keep_going and not self.args.continue_capture:
self._move_buck_out()
ret = self._run_buck_with_flavors()
if not ret == os.EX_OK and not self.keep_going:
return ret
result_paths = self._get_analysis_result_paths()
if result_paths is None:
# huho, the Buck command to extract results paths failed
return os.EX_SOFTWARE
merged_deps_path = os.path.join(
self.args.infer_out, config.INFER_BUCK_DEPS_FILENAME)
if (not ret == os.EX_OK and self.keep_going):
self._find_deps_and_merge(merged_deps_path)
elif self.args.buck_merge_all_deps:
self._find_depsfiles_and_merge(merged_deps_path)
else:
self._merge_infer_dep_files(result_paths, merged_deps_path)
return os.EX_OK

@ -155,6 +155,8 @@ let bound_error_allowed_in_procedure_call = true
let buck_infer_deps_file_name = "infer-deps.txt"
let buck_out_gen = "buck-out" ^/ "gen"
let buck_results_dir_name = "infer"
let captured_dir_name = "captured"
@ -414,6 +416,12 @@ let bin_dir =
Filename.dirname (Utils.realpath Sys.executable_name)
let fcp_dir =
bin_dir ^/ Filename.parent_dir_name ^/ Filename.parent_dir_name ^/ "facebook-clang-plugins"
let clang_plugin_path = fcp_dir ^/ "libtooling" ^/ "build" ^/ "FacebookClangPlugin.dylib"
let lib_dir = bin_dir ^/ Filename.parent_dir_name ^/ "lib"
let etc_dir = bin_dir ^/ Filename.parent_dir_name ^/ "etc"

@ -27,8 +27,6 @@ type build_system =
type scheduler = File | Restart | SyntacticCallGraph [@@deriving equal]
val equal_build_system : build_system -> build_system -> bool
val build_system_of_exe_name : string -> build_system
val string_of_build_system : build_system -> string
@ -65,6 +63,8 @@ val clang_initializer_prefix : string
val clang_inner_destructor_prefix : string
val clang_plugin_path : string
val classnames_dir_name : string
val classpath : string option
@ -87,6 +87,8 @@ val events_dir_name : string
val fail_on_issue_exit_code : int
val fcp_dir : string
val frontend_stats_dir_name : string
val global_tenv_filename : string
@ -250,6 +252,8 @@ val buck_mode : BuckMode.t option
val buck_out : string option
val buck_out_gen : string
val buck_targets_blacklist : string list
val bufferoverrun : bool

@ -26,12 +26,31 @@ let find_files ~path ~extension =
traverse_dir_aux files full_path
| _ ->
files
| exception Unix.Unix_error (ENOENT, _, _) ->
files
in
Sys.fold_dir ~init ~f:(aux dir_path) dir_path
in
traverse_dir_aux [] path
let fold_folders ~init ~f ~path =
let rec traverse_dir_aux acc dir_path =
let aux base_path acc' rel_path =
let full_path = base_path ^/ rel_path in
match (Unix.stat full_path).Unix.st_kind with
| Unix.S_DIR ->
traverse_dir_aux (f acc' full_path) full_path
| _ ->
acc'
| exception Unix.Unix_error (ENOENT, _, _) ->
acc'
in
Sys.fold_dir ~init:acc ~f:(aux dir_path) dir_path
in
traverse_dir_aux init path
(** read a source file and return a list of lines, or None in case of error *)
let read_file fname =
let res = ref [] in

@ -14,6 +14,9 @@ val initial_times : Unix.process_times
val find_files : path:string -> extension:string -> string list
(** recursively traverse a path for files ending with a given extension *)
val fold_folders : init:'acc -> f:('acc -> string -> 'acc) -> path:string -> 'acc
(** recursively traverse a path for folders, returning resuls by a given fold function *)
val string_crc_hex32 : string -> string
(** Compute a 32-character hexadecimal crc using the Digest module *)

@ -15,13 +15,6 @@ type t =
; quoting_style: ClangQuotes.style
; is_driver: bool }
let fcp_dir =
Config.bin_dir ^/ Filename.parent_dir_name ^/ Filename.parent_dir_name ^/ "facebook-clang-plugins"
(** path of the plugin to load in clang *)
let plugin_path = fcp_dir ^/ "libtooling" ^/ "build" ^/ "FacebookClangPlugin.dylib"
(** name of the plugin to use *)
let plugin_name = "BiniouASTExporter"
@ -148,7 +141,7 @@ let filter_and_replace_unsupported_args ?(replace_options_arg = fun _ s -> s) ?(
let clang_cc1_cmd_sanitizer cmd =
let replace_args arg = function
| Some override_regex when Str.string_match override_regex arg 0 ->
fcp_dir ^/ "clang" ^/ "install" ^/ "lib" ^/ "clang" ^/ "9.0.0" ^/ "include"
Config.fcp_dir ^/ "clang" ^/ "install" ^/ "lib" ^/ "clang" ^/ "9.0.0" ^/ "include"
| _ ->
arg
in
@ -175,7 +168,7 @@ let clang_cc1_cmd_sanitizer cmd =
match libcxx_include_to_override_regex with
| Some libcxx_include_to_override_regex
when Str.string_match libcxx_include_to_override_regex arg 0 ->
fcp_dir ^/ "clang" ^/ "install" ^/ "include" ^/ "c++" ^/ "v1"
Config.fcp_dir ^/ "clang" ^/ "install" ^/ "include" ^/ "c++" ^/ "v1"
| _ ->
arg )
| _ ->
@ -250,7 +243,7 @@ let with_plugin_args args =
argv_cons "-cc1"
|> List.rev_append
[ "-load"
; plugin_path
; Config.clang_plugin_path
; (* (t7400979) this is a workaround to avoid that clang crashes when the -fmodules flag and the
YojsonASTExporter plugin are used. Since the -plugin argument disables the generation of .o
files, we invoke apple clang again to generate the expected artifacts. This will keep

@ -339,3 +339,109 @@ let filter_compatible subcommand args =
List.filter args ~f:(fun arg -> not (String.equal blacklist arg))
| _ ->
args
let capture_buck_args =
let clang_path =
List.fold ["clang"; "install"; "bin"; "clang"] ~init:Config.fcp_dir ~f:Filename.concat
in
List.append
[ "--show-output"
; "--config"
; "client.id=infer.clang"
; "--config"
; Printf.sprintf "*//infer.infer_bin=%s" Config.bin_dir
; "--config"
; Printf.sprintf "*//infer.clang_compiler=%s" clang_path
; "--config"
; Printf.sprintf "*//infer.clang_plugin=%s" Config.clang_plugin_path
; "--config"
; "*//cxx.pch_enabled=false"
; "--config"
; (* Infer doesn't support C++ modules yet (T35656509) *)
"*//cxx.modules_default=false"
; "--config"
; "*//cxx.modules=false" ]
( List.rev_append Config.buck_build_args
( if not (List.is_empty Config.buck_blacklist) then
[ "--config"
; Printf.sprintf "*//infer.blacklist_regex=(%s)"
(String.concat ~sep:")|(" Config.buck_blacklist) ]
else [] )
@ ( match Config.xcode_developer_dir with
| Some d ->
["--config"; Printf.sprintf "apple.xcode_developer_dir=%s" d]
| None ->
[] )
@ (if Config.keep_going then ["--keep-going"] else [])
@ ["-j"; Int.to_string Config.jobs]
@ match Config.load_average with Some l -> ["-L"; Float.to_string l] | None -> [] )
let run_buck_build prog buck_build_args =
L.debug Capture Verbose "%s %s@." prog (List.to_string ~f:Fn.id buck_build_args) ;
let {Unix.Process_info.stdin; stdout; stderr; pid} =
Unix.create_process ~prog ~args:buck_build_args
in
let buck_stderr = Unix.in_channel_of_descr stderr in
let buck_stdout = Unix.in_channel_of_descr stdout in
Utils.with_channel_in buck_stderr ~f:(L.progress "BUCK: %s@.") ;
Unix.close stdin ;
In_channel.close buck_stderr ;
(* Process a line of buck stdout output, in this case the result of '--show-output'
These paths (may) contain a 'infer-deps.txt' file, which we will later merge
*)
let process_buck_line acc line =
L.debug Capture Verbose "BUCK OUT: %s@." line ;
match String.split ~on:' ' line with
| [_; target_path] ->
let filename = Config.project_root ^/ target_path ^/ Config.buck_infer_deps_file_name in
if PolyVariantEqual.(Sys.file_exists filename = `Yes) then filename :: acc else acc
| _ ->
L.die ExternalError "Couldn't parse buck target output: %s" line
in
match Unix.waitpid pid with
| Ok () ->
let res = In_channel.fold_lines buck_stdout ~init:[] ~f:process_buck_line in
In_channel.close buck_stdout ; res
| Error _ as err ->
L.die ExternalError "*** capture failed to execute: %s"
(Unix.Exit_or_signal.to_string_hum err)
let merge_deps_files depsfiles =
let buck_out = Config.project_root ^/ Config.buck_out_gen in
let depslines, depsfiles =
match (depsfiles, Config.keep_going, Config.buck_merge_all_deps) with
| [], true, _ ->
let infouts =
Utils.fold_folders ~init:[] ~path:buck_out ~f:(fun acc dir ->
if
String.is_substring dir ~substring:"infer-out"
&& PolyVariantEqual.(
Sys.file_exists @@ dir ^/ ResultsDatabase.database_filename = `Yes)
then Printf.sprintf "\t\t%s" dir :: acc
else acc )
in
(infouts, depsfiles)
| [], _, true ->
let files = Utils.find_files ~path:buck_out ~extension:Config.buck_infer_deps_file_name in
([], files)
| _ ->
([], depsfiles)
in
depslines
@ List.fold depsfiles ~init:[] ~f:(fun acc file ->
List.rev_append acc (Utils.with_file_in file ~f:In_channel.input_lines) )
|> List.dedup_and_sort ~compare:String.compare
let clang_flavor_capture ~prog ~buck_build_cmd =
if Config.keep_going && not Config.continue_capture then
Process.create_process_and_wait ~prog ~args:["clean"] ;
let depsfiles = run_buck_build prog (buck_build_cmd @ capture_buck_args) in
let deplines = merge_deps_files depsfiles in
let infer_out_depsfile = Config.(results_dir ^/ buck_infer_deps_file_name) in
Utils.with_file_out infer_out_depsfile ~f:(fun out_chan ->
Out_channel.output_lines out_chan deplines ) ;
()

@ -32,3 +32,6 @@ val store_args_in_file : string list -> string list
val filter_compatible : [> `Targets] -> string list -> string list
(** keep only the options compatible with the given Buck subcommand *)
val clang_flavor_capture : prog:string -> buck_build_cmd:string list -> unit
(** do a buck/clang flavor capture given the prog and build command (buck args) *)

@ -16,6 +16,7 @@ module F = Format
(* based on the build_system and options passed to infer, we run in different driver modes *)
type mode =
| Analyze
| BuckClangFlavor of string list
| BuckGenrule of string
| BuckGenruleMaster of string list
| BuckCompilationDB of BuckMode.clang_compilation_db_deps * string * string list
@ -31,6 +32,8 @@ let is_analyze_mode = function Analyze -> true | _ -> false
let pp_mode fmt = function
| Analyze ->
F.fprintf fmt "Analyze driver mode"
| BuckClangFlavor args ->
F.fprintf fmt "BuckClangFlavor driver mode: args = %a" Pp.cli_args args
| BuckGenrule prog ->
F.fprintf fmt "BuckGenRule driver mode:@\nprog = '%s'" prog
| BuckGenruleMaster build_cmd ->
@ -187,12 +190,12 @@ let capture_with_compilation_database db_files =
CaptureCompilationDatabase.capture_files_in_database compilation_database
let python_capture build_system build_cmd =
let buck_capture build_cmd =
register_perf_stats_report PerfStats.TotalFrontend ;
let in_buck_mode = Config.equal_build_system build_system BBuck in
let build_cmd_opt =
let prog_build_cmd_opt =
let prog, buck_args = (List.hd_exn build_cmd, List.tl_exn build_cmd) in
match Config.buck_mode with
| Some ClangFlavors when in_buck_mode ->
| Some ClangFlavors ->
(* let children infer processes know that they are inside Buck *)
let infer_args_with_buck =
String.concat
@ -200,7 +203,6 @@ let python_capture build_system build_cmd =
(Option.to_list (Sys.getenv CLOpt.args_env_var) @ ["--buck"])
in
Unix.putenv ~key:CLOpt.args_env_var ~data:infer_args_with_buck ;
let prog, buck_args = (List.hd_exn build_cmd, List.tl_exn build_cmd) in
let {Buck.command; rev_not_targets; targets} =
Buck.add_flavors_to_buck_arguments ClangFlavors ~filter_kind:`Auto ~extra_flavors:[]
buck_args
@ -209,37 +211,36 @@ let python_capture build_system build_cmd =
else
let all_args = List.rev_append rev_not_targets targets in
let updated_buck_cmd =
[prog; command]
@ List.rev_append Config.buck_build_args_no_inline (Buck.store_args_in_file all_args)
command
:: List.rev_append Config.buck_build_args_no_inline (Buck.store_args_in_file all_args)
in
Logging.(debug Capture Quiet)
"Processed buck command '%a'@\n" (Pp.seq F.pp_print_string) updated_buck_cmd ;
Some updated_buck_cmd
Some (prog, updated_buck_cmd)
| _ ->
Some build_cmd
Some (prog, build_cmd)
in
Option.iter build_cmd_opt ~f:(fun updated_build_cmd ->
Option.iter prog_build_cmd_opt ~f:(fun (prog, buck_build_cmd) ->
L.progress "Capturing in buck mode...@." ;
if Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode then (
RunState.set_merge_capture true ; RunState.store () ) ;
Buck.clang_flavor_capture ~prog ~buck_build_cmd ) ;
PerfStats.get_reporter PerfStats.TotalFrontend ()
let python_capture build_system build_cmd =
register_perf_stats_report PerfStats.TotalFrontend ;
L.progress "Capturing in %s mode...@." (Config.string_of_build_system build_system) ;
let infer_py = Config.lib_dir ^/ "python" ^/ "infer.py" in
let args =
List.rev_append Config.anon_args
( ( match (build_system, Config.buck_blacklist) with
| Config.BBuck, _ :: _ ->
["--blacklist-regex"; "(" ^ String.concat ~sep:")|(" Config.buck_blacklist ^ ")"]
| _ ->
[] )
@ (if not Config.continue_capture then [] else ["--continue"])
( (if not Config.continue_capture then [] else ["--continue"])
@ ( match Config.force_integration with
| None ->
[]
| Some tool ->
["--force-integration"; Config.string_of_build_system tool] )
@ (match Config.java_jar_compiler with None -> [] | Some p -> ["--java-jar-compiler"; p])
@ ( match List.rev Config.buck_build_args with
| args when in_buck_mode ->
List.map ~f:(fun arg -> ["--Xbuck"; "'" ^ arg ^ "'"]) args |> List.concat
| _ ->
[] )
@ (if not Config.debug_mode then [] else ["--debug"])
@ (if Config.filtering then [] else ["--no-filtering"])
@ "-j" :: string_of_int Config.jobs
@ -249,16 +250,10 @@ let python_capture build_system build_cmd =
@ (if not Config.quiet then [] else ["--quiet"])
@ "--out" :: Config.results_dir
::
( match Config.xcode_developer_dir with
| None ->
[]
| Some d ->
["--xcode-developer-dir"; d] )
(match Config.xcode_developer_dir with None -> [] | Some d -> ["--xcode-developer-dir"; d])
@ (if not Config.buck_merge_all_deps then [] else ["--buck-merge-all-deps"])
@ ("--" :: updated_build_cmd) )
@ ("--" :: build_cmd) )
in
if in_buck_mode && Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode then (
RunState.set_merge_capture true ; RunState.store () ) ;
run_command ~prog:infer_py ~args
~cleanup:(function
| Error (`Exit_non_zero exit_code)
@ -268,12 +263,14 @@ let python_capture build_system build_cmd =
| status ->
command_error_handling ~always_die:true ~prog:infer_py ~args status )
() ;
PerfStats.get_reporter PerfStats.TotalFrontend () )
PerfStats.get_reporter PerfStats.TotalFrontend ()
let capture ~changed_files = function
| Analyze ->
()
| BuckClangFlavor build_cmd ->
buck_capture build_cmd
| BuckCompilationDB (deps, prog, args) ->
L.progress "Capturing using Buck's compilation database...@." ;
let json_cdb =
@ -391,8 +388,7 @@ let error_nothing_to_analyze mode =
let analyze_and_report ?suppress_console_report ~changed_files mode =
let should_analyze, should_report =
match (Config.command, mode) with
| _, PythonCapture (BBuck, _)
when not (Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode) ->
| _, BuckClangFlavor _ when not (Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode) ->
(* In Buck mode when compilation db is not used, analysis is invoked from capture if buck flavors are not used *)
(false, false)
| _ when Config.infer_is_clang || Config.infer_is_javac ->
@ -409,7 +405,7 @@ let analyze_and_report ?suppress_console_report ~changed_files mode =
| _ when Config.merge ->
(* [--merge] overrides other behaviors *)
true
| PythonCapture (BBuck, _)
| BuckClangFlavor _
when Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode
&& InferCommand.equal Run Config.command ->
(* if doing capture + analysis of buck with flavors, we always need to merge targets before the analysis phase *)
@ -532,7 +528,7 @@ let mode_of_build_command build_cmd (buck_mode : BuckMode.t option) =
L.user_warning
"WARNING: the linters require --buck-compilation-database to be set.@ Alternatively, \
set --no-linters to disable them and this warning.@." ;
PythonCapture (BBuck, build_cmd)
BuckClangFlavor build_cmd
| BBuck, Some JavaGenruleMaster ->
BuckGenruleMaster build_cmd
| BClang, _ ->
@ -547,7 +543,8 @@ let mode_of_build_command build_cmd (buck_mode : BuckMode.t option) =
Maven (prog, args)
| BXcode, _ when Config.xcpretty ->
XcodeXcpretty (prog, args)
| (BBuck as build_system), Some ClangFlavors
| BBuck, Some ClangFlavors ->
BuckClangFlavor build_cmd
| ((BAnt | BGradle | BNdk | BXcode) as build_system), _ ->
PythonCapture (build_system, build_cmd) )

@ -13,6 +13,7 @@ open! IStd
(** based on the build_system and options passed to infer, we run in different driver modes *)
type mode =
| Analyze
| BuckClangFlavor of string list
| BuckGenrule of string
| BuckGenruleMaster of string list
| BuckCompilationDB of BuckMode.clang_compilation_db_deps * string * string list

Loading…
Cancel
Save