[clang] Integration with xcpretty and compilation database

Reviewed By: jberdine

Differential Revision: D4112287

fbshipit-source-id: f02d424
master
Dulma Churchill 8 years ago committed by Facebook Github Bot
parent 21a568aba8
commit b792d04fbd

@ -90,6 +90,18 @@ let run_command cmd_list after_wait =
exit exit_code exit exit_code
) )
let check_xcpretty () =
let open Core.Std in
let exit_code = Unix.system "xcpretty --version" in
match exit_code with
| Ok () -> ()
| Error _ ->
Logging.stderr
"@.xcpretty not found in the path. Please, install xcpretty \
for a more robust integration with xcodebuild. Otherwise use the option \
--no-xcpretty.@.@.";
Unix.exit_immediately 1
let capture build_cmd build_mode = let capture build_cmd build_mode =
let analyze_cmd = "analyze" in let analyze_cmd = "analyze" in
let is_analyze_cmd cmd = let is_analyze_cmd cmd =
@ -98,6 +110,12 @@ let capture build_cmd build_mode =
| _ -> false in | _ -> false in
let build_cmd = let build_cmd =
match build_mode with match build_mode with
| Xcode when Config.xcpretty ->
check_xcpretty ();
let json_cdb =
CaptureCompilationDatabase.get_compilation_database_files_xcodebuild () in
CaptureCompilationDatabase.capture_files_in_database json_cdb;
[analyze_cmd]
| Buck when Option.is_some Config.use_compilation_database -> | Buck when Option.is_some Config.use_compilation_database ->
let json_cdb = CaptureCompilationDatabase.get_compilation_database_files_buck () in let json_cdb = CaptureCompilationDatabase.get_compilation_database_files_buck () in
CaptureCompilationDatabase.capture_files_in_database json_cdb; CaptureCompilationDatabase.capture_files_in_database json_cdb;

@ -1269,6 +1269,13 @@ and xcode_developer_dir =
~exes:CLOpt.[Toplevel] ~exes:CLOpt.[Toplevel]
~meta:"XCODE_DEVELOPER_DIR" "Specify the path to Xcode developer directory (Buck flavors only)" ~meta:"XCODE_DEVELOPER_DIR" "Specify the path to Xcode developer directory (Buck flavors only)"
and xcpretty =
CLOpt.mk_bool ~long:"xcpretty"
~default:true
~exes:CLOpt.[Toplevel]
"Infer will use xcpretty together with xcodebuild to analyze an iOS app. xcpretty just needs \
to be in the path, infer command is still just infer -- <xcodebuild command>. (Recommended)"
and xml_specs = and xml_specs =
CLOpt.mk_bool ~deprecated:["xml"] ~long:"xml-specs" CLOpt.mk_bool ~deprecated:["xml"] ~long:"xml-specs"
"Export specs into XML files file1.xml ... filen.xml" "Export specs into XML files file1.xml ... filen.xml"
@ -1504,6 +1511,7 @@ and worklist_mode = !worklist_mode
and write_dotty = !write_dotty and write_dotty = !write_dotty
and write_html = !write_html and write_html = !write_html
and xcode_developer_dir = !xcode_developer_dir and xcode_developer_dir = !xcode_developer_dir
and xcpretty = !xcpretty
and xml_specs = !xml_specs and xml_specs = !xml_specs

@ -267,6 +267,7 @@ val worklist_mode : int
val write_dotty : bool val write_dotty : bool
val write_html : bool val write_html : bool
val xcode_developer_dir : string option val xcode_developer_dir : string option
val xcpretty : bool
val xml_specs : bool val xml_specs : bool

@ -111,3 +111,34 @@ let run_jobs_in_parallel jobs_stack gen_cmd cmd_to_string =
run_job (); run_job ();
Logging.stdout ".\n%!"; Logging.stdout ".\n%!";
Logging.out "Waited for %d jobs" !waited_for_jobs Logging.out "Waited for %d jobs" !waited_for_jobs
let pipeline ~producer_prog ~producer_args ~consumer_prog ~consumer_args =
let open Core.Std in
let pipe_in, pipe_out = Unix.pipe () in
match Unix.fork () with
| `In_the_child ->
(* redirect producer's stdout to pipe_out *)
Unix.dup2 ~src:pipe_out ~dst:Unix.stdout ;
(* close producer's copy of pipe ends *)
Unix.close pipe_out ;
Unix.close pipe_in ;
(* exec producer *)
never_returns (Unix.exec ~prog:producer_prog ~args:producer_args ())
| `In_the_parent producer_pid ->
match Unix.fork () with
| `In_the_child ->
(* redirect consumer's stdin to pipe_in *)
Unix.dup2 ~src:pipe_in ~dst:Unix.stdin ;
(* close consumer's copy of pipe ends *)
Unix.close pipe_out ;
Unix.close pipe_in ;
(* exec consumer *)
never_returns (Unix.exec ~prog:consumer_prog ~args:consumer_args ())
| `In_the_parent consumer_pid ->
(* close parent's copy of pipe ends *)
Unix.close pipe_out ;
Unix.close pipe_in ;
(* wait for children *)
let producer_status = Unix.waitpid producer_pid in
let consumer_status = Unix.waitpid consumer_pid in
(producer_status, consumer_status)

@ -35,3 +35,7 @@ val print_unix_error : string -> exn -> unit
printing information about the job's status. *) printing information about the job's status. *)
val run_jobs_in_parallel : 'a Stack.t -> val run_jobs_in_parallel : 'a Stack.t ->
('a -> (string option * string * string array * string array)) -> ('a -> string) -> unit ('a -> (string option * string * string array * string array)) -> ('a -> string) -> unit
(** Pipeline producer program into consumer program *)
val pipeline : producer_prog:string -> producer_args:string list -> consumer_prog:string ->
consumer_args:string list -> Core.Std.Unix.Exit_or_signal.t * Core.Std.Unix.Exit_or_signal.t

@ -155,6 +155,29 @@ let get_compilation_database_files_buck () =
let cmd = String.concat " " cmd in let cmd = String.concat " " cmd in
Process.print_error_and_exit "Incorrect buck command: %s. Please use buck build <targets>" cmd Process.print_error_and_exit "Incorrect buck command: %s. Please use buck build <targets>" cmd
(** Compute the compilation database files. *)
let get_compilation_database_files_xcodebuild () =
let cmd_and_args = IList.rev Config.rest in
let temp_dir = Config.results_dir // "clang" in
create_dir temp_dir;
let tmp_file = Filename.temp_file ~temp_dir:temp_dir "cdb" ".json" in
let xcodebuild_cmd, xcodebuild_args =
match cmd_and_args with
| [] -> failwith("Build command cannot be empty")
| cmd :: _ -> cmd, cmd_and_args in
let xcpretty_cmd = "xcpretty" in
let xcpretty_cmd_args =
[xcpretty_cmd; "--report"; "json-compilation-database"; "--output"; tmp_file] in
let producer_status, consumer_status =
Process.pipeline ~producer_prog:xcodebuild_cmd ~producer_args:xcodebuild_args
~consumer_prog:xcpretty_cmd ~consumer_args:xcpretty_cmd_args in
match producer_status, consumer_status with
| Ok (), Ok () -> [tmp_file]
| _ ->
Logging.stderr "There was an error executing the build command";
exit 1
let capture_files_in_database db_json_files = let capture_files_in_database db_json_files =
let changed_files = read_files_to_compile () in let changed_files = read_files_to_compile () in
let compilation_database = CompilationDatabase.empty () in let compilation_database = CompilationDatabase.empty () in

@ -12,7 +12,11 @@
is passed, we only capture the files there *) is passed, we only capture the files there *)
val capture_files_in_database : string list -> unit val capture_files_in_database : string list -> unit
(** Gets the compilation database files that contain the compilation given by the (** Get the compilation database files that contain the compilation given by the
buck command. It will be the compilation of the passed targets only or also buck command. It will be the compilation of the passed targets only or also
the dependencies according to the flag --use-compilation-database deps | no-deps *) the dependencies according to the flag --use-compilation-database deps | no-deps *)
val get_compilation_database_files_buck : unit -> string list val get_compilation_database_files_buck : unit -> string list
(** Get the compilation database files that contain the compilation given by the
xcodebuild command, using xcpretty. *)
val get_compilation_database_files_xcodebuild : unit -> string list

Loading…
Cancel
Save