Accept command line options via environment vars

Summary:public
Generalize command line option parsing to query an environment variable
for args, and then parse the environment and command line arguments.

Each executable uses a distinct environment variable:
  - InferAnalyze:   INFER_ARGS
  - InferJava:      INFERJAVA_ARGS
  - InferClang:     INFERCLANG_ARGS
  - InferLLVM:      INFERLLVM_ARGS
  - checkCopyright: CHECKCOPYRIGHT_ARGS

For now these variables need to be set manually.  So the usability is
still pretty bad, but is a step in the direction of enabling debugging
the analyzer on code built with buck.

Reviewed By: cristianoc, martinoluca

Differential Revision: D2987288

fb-gh-sync-id: f477611
shipit-source-id: f477611
master
Josh Berdine 9 years ago committed by Facebook Github Bot 4
parent 86304b3d9c
commit 66d865ff6a

@ -223,7 +223,7 @@ let print_usage_exit () =
let () = (* parse command-line arguments *) let () = (* parse command-line arguments *)
let f _ = let f _ =
() (* ignore anonymous arguments *) in () (* ignore anonymous arguments *) in
Arg.parse arg_desc f usage; Arg.parse "INFER_ARGS" arg_desc f usage;
if not (Sys.file_exists !Config.results_dir) then if not (Sys.file_exists !Config.results_dir) then
begin begin
L.err "ERROR: results directory %s does not exist@.@." !Config.results_dir; L.err "ERROR: results directory %s does not exist@.@." !Config.results_dir;

@ -1023,7 +1023,7 @@ module AnalysisResults = struct
if not (Filename.check_suffix arg ".specs") && arg <> "." if not (Filename.check_suffix arg ".specs") && arg <> "."
then print_usage_exit "arguments must be .specs files" then print_usage_exit "arguments must be .specs files"
else args := arg::!args in else args := arg::!args in
Arg.parse arg_desc f usage; Arg.parse "INFERPRINT_ARGS" arg_desc f usage;
if !test_filtering then if !test_filtering then
begin begin
Inferconfig.test (); Inferconfig.test ();

@ -857,6 +857,19 @@ module Arg = struct
("", Arg.Unit (fun () -> ()), " \n " ^ title ^ "\n") :: ("", Arg.Unit (fun () -> ()), " \n " ^ title ^ "\n") ::
IList.sort (fun (x, _, _) (y, _, _) -> Pervasives.compare x y) unsorted_desc' in IList.sort (fun (x, _, _) (y, _, _) -> Pervasives.compare x y) unsorted_desc' in
align dlist align dlist
let env_to_argv env =
Str.split (Str.regexp ":") env
let prepend_to_argv args =
let cl_args = match Array.to_list Sys.argv with _ :: tl -> tl | [] -> [] in
Sys.executable_name :: args @ cl_args
let parse env_var spec anon usage =
let env_args = env_to_argv (try Unix.getenv env_var with Not_found -> "") in
let env_cl_args = prepend_to_argv env_args in
Arg.parse_argv (Array.of_list env_cl_args) spec anon usage
end end
(** flags for a procedure *) (** flags for a procedure *)

@ -233,7 +233,12 @@ module Arg : sig
val align : (key * spec * doc) list -> aligned list val align : (key * spec * doc) list -> aligned list
val parse : aligned list -> anon_fun -> usage_msg -> unit (** [parse env_var arg_desc anon_fun usage_msg] prepends the decoded value of environment variable
[env_var] to [Sys.argv] and then parses the result using the standard [Arg.parse]. Therefore
arguments passed on the command line supercede those specified in the environment variable.
WARNING: If an argument appears both in the environment variable and on the command line, it
will be interpreted twice. *)
val parse : string -> aligned list -> anon_fun -> usage_msg -> unit
val usage : aligned list -> usage_msg -> unit val usage : aligned list -> usage_msg -> unit

@ -96,9 +96,6 @@ let print_usage_exit () =
Arg.usage arg_desc usage; Arg.usage arg_desc usage;
exit(1) exit(1)
let () =
Arg.parse arg_desc (fun _ -> ()) usage
let buffer_len = 16384 let buffer_len = 16384
(* This function reads the json file in fname, validates it, and encoded in the AST data structure*) (* This function reads the json file in fname, validates it, and encoded in the AST data structure*)
@ -138,7 +135,8 @@ let do_run source_path ast_path =
(Yojson.Json_error s) as exc -> Printing.log_err "%s\n" s; (Yojson.Json_error s) as exc -> Printing.log_err "%s\n" s;
raise exc raise exc
let _ = let () =
Arg.parse "INFERCLANG_ARGS" arg_desc (fun _ -> ()) usage ;
Config.print_types := true; Config.print_types := true;
if Option.is_none !CFrontend_config.source_file then if Option.is_none !CFrontend_config.source_file then
(Printing.log_err "Incorrect command line arguments\n"; (Printing.log_err "Incorrect command line arguments\n";

@ -78,7 +78,7 @@ let print_usage_exit () =
exit(1) exit(1)
let () = let () =
Arg.parse arg_desc (fun _ -> ()) usage; Arg.parse "INFERJAVA_ARGS" arg_desc (fun _ -> ()) usage;
if Config.analyze_models && !JClasspath.models_jar <> "" then if Config.analyze_models && !JClasspath.models_jar <> "" then
failwith "Not expecting model file when analyzing the models"; failwith "Not expecting model file when analyzing the models";
if not Config.analyze_models && !JClasspath.models_jar = "" then if not Config.analyze_models && !JClasspath.models_jar = "" then

@ -67,7 +67,7 @@ let store_tenv tenv =
Sil.store_tenv_to_file tenv_filename tenv Sil.store_tenv_to_file tenv_filename tenv
let () = let () =
Arg.parse arg_desc (fun _ -> ()) usage; Arg.parse "INFERLLVM_ARGS" arg_desc (fun _ -> ()) usage;
begin match !LConfig.source_filename with begin match !LConfig.source_filename with
| None -> print_usage_exit () | None -> print_usage_exit ()
| Some source_filename -> init_global_state source_filename | Some source_filename -> init_global_state source_filename

@ -275,6 +275,6 @@ let () =
let to_check = ref [] in let to_check = ref [] in
let add_file_to_check fname = let add_file_to_check fname =
to_check := fname :: !to_check in to_check := fname :: !to_check in
Arg.parse (Arg.align speclist) add_file_to_check usage_msg; Arg.parse "CHECKCOPYRIGHT_ARGS" (Arg.align speclist) add_file_to_check usage_msg;
IList.iter check_copyright (IList.rev !to_check); IList.iter check_copyright (IList.rev !to_check);
exit 0 exit 0

Loading…
Cancel
Save