[xcodebuild] replace python integration with ocaml

Reviewed By: ngorogiannis

Differential Revision: D20416859

fbshipit-source-id: abac2c6b4
master
Martin Trojer 5 years ago committed by Facebook GitHub Bot
parent 3ceb2efe9e
commit baaf81b554

@ -1,78 +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.
import logging
import os
import subprocess
import traceback
import util
from inferlib import config, utils
MODULE_NAME = __name__
MODULE_DESCRIPTION = '''Run analysis of code built with a command like:
xcodebuild [options]
Analysis examples:
infer -- xcodebuild -target HelloWorldApp -sdk iphonesimulator
infer -- xcodebuild -workspace HelloWorld.xcworkspace -scheme HelloWorld'''
LANG = ['clang']
CLANG_WRAPPER = os.path.join(config.WRAPPERS_DIRECTORY, 'clang')
CLANGPLUSPLUS_WRAPPER = os.path.join(config.WRAPPERS_DIRECTORY, 'clang++')
def gen_instance(*args):
return XcodebuildCapture(*args)
create_argparser = util.base_argparser(MODULE_DESCRIPTION, MODULE_NAME)
class XcodebuildCapture:
def __init__(self, args, cmd):
self.args = args
self.apple_clang_path = \
subprocess.check_output(['xcrun', '--find', 'clang']).strip()
xcode_version = util.run_cmd_ignore_fail(['xcodebuild', '-version'])
apple_clang_version = util.run_cmd_ignore_fail([self.apple_clang_path,
'--version'])
logging.info('Xcode version:\n%s', xcode_version)
logging.info('clang version:\n%s', apple_clang_version)
self.cmd = cmd
def get_envvars(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-apple-clang^' + self.apple_clang_path
env_vars['INFER_ARGS'] = infer_args
return env_vars
def capture(self):
# these settings will instruct xcodebuild on which clang to use
self.cmd += ['CC={wrapper}'.format(wrapper=CLANG_WRAPPER)]
self.cmd += [
'CPLUSPLUS={wrapper}'.format(wrapper=CLANGPLUSPLUS_WRAPPER)]
# skip the ProcessPCH phase to fix the "newer/older" incompatibility
# error for the pch files generated by apple's clang and
# the open-source one
self.cmd += ['GCC_PRECOMPILE_PREFIX_HEADER=NO']
try:
env = utils.encode_env(self.get_envvars())
cmd = map(utils.encode, self.cmd)
subprocess.check_call(cmd, env=env)
return os.EX_OK
except subprocess.CalledProcessError as exc:
if self.args.debug:
traceback.print_exc()
return exc.returncode

@ -35,6 +35,23 @@ let create_process_and_wait ~prog ~args =
(Unix.Exit_or_signal.to_string_hum status) (Unix.Exit_or_signal.to_string_hum status)
let create_process_and_wait_with_output ~prog ~args =
let {Unix.Process_info.stdin; stdout; stderr; pid} = Unix.create_process ~prog ~args in
let stderr_chan = Unix.in_channel_of_descr stderr in
let stdout_chan = Unix.in_channel_of_descr stdout in
Unix.close stdin ;
match Unix.waitpid pid with
| Ok () ->
let out = In_channel.input_all stdout_chan in
let err = In_channel.input_all stderr_chan in
In_channel.close stdout_chan ; In_channel.close stderr_chan ; (out, err)
| Error _ as status ->
L.(die ExternalError)
"Error executing: %s@\n%s@\n"
(String.concat ~sep:" " (prog :: args))
(Unix.Exit_or_signal.to_string_hum status)
let pipeline ~producer_prog ~producer_args ~consumer_prog ~consumer_args = let pipeline ~producer_prog ~producer_args ~consumer_prog ~consumer_args =
let pipe_in, pipe_out = Unix.pipe () in let pipe_in, pipe_out = Unix.pipe () in
match Unix.fork () with match Unix.fork () with

@ -12,6 +12,11 @@ val create_process_and_wait : prog:string -> args:string list -> unit
execution. The standard out and error are not redirected. If the commands fails to execute, execution. The standard out and error are not redirected. If the commands fails to execute,
prints an error message and exits. *) prints an error message and exits. *)
val create_process_and_wait_with_output : prog:string -> args:string list -> string * string
(** Given an command to be executed, creates a process to execute this command, and waits for its
execution. The standard out and error are returned. If the commands fails to execute, prints an
error message and exits. *)
val print_error_and_exit : ?exit_code:int -> ('a, Format.formatter, unit, 'b) format4 -> 'a val print_error_and_exit : ?exit_code:int -> ('a, Format.formatter, unit, 'b) format4 -> 'a
(** Prints an error message to a log file, prints a message saying that the error can be found in (** Prints an error message to a log file, prints a message saying that the error can be found in
that file, and exist, with default code 1 or a given code. *) that file, and exist, with default code 1 or a given code. *)

@ -26,6 +26,7 @@ type mode =
| Maven of string * string list | Maven of string * string list
| NdkBuild of string list | NdkBuild of string list
| PythonCapture of Config.build_system * string list | PythonCapture of Config.build_system * string list
| XcodeBuild of string * string list
| XcodeXcpretty of string * string list | XcodeXcpretty of string * string list
let is_analyze_mode = function Analyze -> true | _ -> false let is_analyze_mode = function Analyze -> true | _ -> false
@ -48,6 +49,8 @@ let pp_mode fmt = function
F.fprintf fmt "PythonCapture driver mode:@\nbuild system = '%s'@\nargs = %a" F.fprintf fmt "PythonCapture driver mode:@\nbuild system = '%s'@\nargs = %a"
(Config.string_of_build_system bs) (Config.string_of_build_system bs)
Pp.cli_args args Pp.cli_args args
| XcodeBuild (prog, args) ->
F.fprintf fmt "XcodeBuild driver mode:@\nprog = '%s'@\nargs = %a" prog Pp.cli_args args
| XcodeXcpretty (prog, args) -> | XcodeXcpretty (prog, args) ->
F.fprintf fmt "XcodeXcpretty driver mode:@\nprog = '%s'@\nargs = %a" prog Pp.cli_args args F.fprintf fmt "XcodeXcpretty driver mode:@\nprog = '%s'@\nargs = %a" prog Pp.cli_args args
| Javac (_, prog, args) -> | Javac (_, prog, args) ->
@ -290,9 +293,13 @@ let capture ~changed_files = function
L.progress "Capturing in maven mode...@." ; L.progress "Capturing in maven mode...@." ;
Maven.capture ~prog ~args Maven.capture ~prog ~args
| NdkBuild build_cmd -> | NdkBuild build_cmd ->
L.progress "Capturing in ndk-build mode...@." ;
NdkBuild.capture ~build_cmd NdkBuild.capture ~build_cmd
| PythonCapture (build_system, build_cmd) -> | PythonCapture (build_system, build_cmd) ->
python_capture build_system build_cmd python_capture build_system build_cmd
| XcodeBuild (prog, args) ->
L.progress "Capturing in xcodebuild mode...@." ;
XcodeBuild.capture ~prog ~args
| XcodeXcpretty (prog, args) -> | XcodeXcpretty (prog, args) ->
L.progress "Capturing using xcodebuild and xcpretty...@." ; L.progress "Capturing using xcodebuild and xcpretty...@." ;
check_xcpretty () ; check_xcpretty () ;
@ -534,11 +541,13 @@ let mode_of_build_command build_cmd (buck_mode : BuckMode.t option) =
Maven (prog, args) Maven (prog, args)
| BXcode, _ when Config.xcpretty -> | BXcode, _ when Config.xcpretty ->
XcodeXcpretty (prog, args) XcodeXcpretty (prog, args)
| BXcode, _ ->
XcodeBuild (prog, args)
| BBuck, Some ClangFlavors -> | BBuck, Some ClangFlavors ->
BuckClangFlavor build_cmd BuckClangFlavor build_cmd
| BNdk, _ -> | BNdk, _ ->
NdkBuild build_cmd NdkBuild build_cmd
| ((BAnt | BGradle | BXcode) as build_system), _ -> | ((BAnt | BGradle) as build_system), _ ->
PythonCapture (build_system, build_cmd) ) PythonCapture (build_system, build_cmd) )

@ -23,6 +23,7 @@ type mode =
| Maven of string * string list | Maven of string * string list
| NdkBuild of string list | NdkBuild of string list
| PythonCapture of Config.build_system * string list | PythonCapture of Config.build_system * string list
| XcodeBuild of string * string list
| XcodeXcpretty of string * string list | XcodeXcpretty of string * string list
val is_analyze_mode : mode -> bool val is_analyze_mode : mode -> bool

@ -0,0 +1,50 @@
(*
* 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 L = Logging
let capture ~prog ~args =
let apple_clang =
Process.create_process_and_wait_with_output ~prog:"xcrun" ~args:["--find"; "clang"]
|> fst |> String.strip
in
let xcode_version, _ =
Process.create_process_and_wait_with_output ~prog:"xcodebuild" ~args:["-version"]
in
let apple_clang_version, _ =
Process.create_process_and_wait_with_output ~prog:apple_clang ~args:["--version"]
in
L.environment_info "Xcode version: %s@." xcode_version ;
L.environment_info "clang version: %s@." apple_clang_version ;
let args =
List.append args
[ Printf.sprintf "CC=%s" Config.wrappers_dir ^/ "clang"
; Printf.sprintf "CPLUSPLUS=%s" Config.wrappers_dir ^/ "clang++"
; "GCC_PRECOMPILE_PREFIX_HEADER=NO" ]
in
let infer_args =
Option.fold (Sys.getenv CommandLineOption.args_env_var)
~init:(Printf.sprintf "%s%c%s" "--fcp-apple-clang" CommandLineOption.env_var_sep apple_clang)
~f:(fun acc arg -> Printf.sprintf "%s%c%s" acc CommandLineOption.env_var_sep arg)
in
L.debug Capture Verbose "%s [%s] [%s]@." prog (String.concat ~sep:"," args) infer_args ;
let {Unix.Process_info.stdin; stdout; stderr; pid} =
Unix.create_process_env ~prog ~args
~env:(`Extend [(CommandLineOption.args_env_var, infer_args)])
()
in
let stdout_chan = Unix.in_channel_of_descr stdout in
let stderr_chan = Unix.in_channel_of_descr stderr in
Unix.close stdin ;
Utils.with_channel_in stdout_chan ~f:(L.progress "XCODEBUILD: %s@.") ;
Utils.with_channel_in stderr_chan ~f:(L.progress "XCODEBUILD: %s@.") ;
match Unix.waitpid pid with
| Ok () ->
In_channel.close stdout_chan ; In_channel.close stderr_chan
| Error _ as err ->
L.die ExternalError "*** capture failed to execute: %s"
(Unix.Exit_or_signal.to_string_hum err)

@ -0,0 +1,10 @@
(*
* 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 : prog:string -> args:string list -> unit
Loading…
Cancel
Save