From 66d865ff6ad083c62cec5ebd2e60d0c730b813b0 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Wed, 16 Mar 2016 14:42:21 -0700 Subject: [PATCH] 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 --- infer/src/backend/inferanalyze.ml | 2 +- infer/src/backend/inferprint.ml | 2 +- infer/src/backend/utils.ml | 13 +++++++++++++ infer/src/backend/utils.mli | 7 ++++++- infer/src/clang/cMain.ml | 6 ++---- infer/src/java/jMain.ml | 2 +- infer/src/llvm/lMain.ml | 2 +- infer/src/scripts/checkCopyright.ml | 2 +- 8 files changed, 26 insertions(+), 10 deletions(-) diff --git a/infer/src/backend/inferanalyze.ml b/infer/src/backend/inferanalyze.ml index 9f9adb39c..a056fb382 100644 --- a/infer/src/backend/inferanalyze.ml +++ b/infer/src/backend/inferanalyze.ml @@ -223,7 +223,7 @@ let print_usage_exit () = let () = (* parse command-line arguments *) let f _ = () (* 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 begin L.err "ERROR: results directory %s does not exist@.@." !Config.results_dir; diff --git a/infer/src/backend/inferprint.ml b/infer/src/backend/inferprint.ml index 9c933f6de..a00a13eae 100644 --- a/infer/src/backend/inferprint.ml +++ b/infer/src/backend/inferprint.ml @@ -1023,7 +1023,7 @@ module AnalysisResults = struct if not (Filename.check_suffix arg ".specs") && arg <> "." then print_usage_exit "arguments must be .specs files" else args := arg::!args in - Arg.parse arg_desc f usage; + Arg.parse "INFERPRINT_ARGS" arg_desc f usage; if !test_filtering then begin Inferconfig.test (); diff --git a/infer/src/backend/utils.ml b/infer/src/backend/utils.ml index 69e3694d2..2deb3f9bd 100644 --- a/infer/src/backend/utils.ml +++ b/infer/src/backend/utils.ml @@ -857,6 +857,19 @@ module Arg = struct ("", Arg.Unit (fun () -> ()), " \n " ^ title ^ "\n") :: IList.sort (fun (x, _, _) (y, _, _) -> Pervasives.compare x y) unsorted_desc' in 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 (** flags for a procedure *) diff --git a/infer/src/backend/utils.mli b/infer/src/backend/utils.mli index bc843701f..537d14130 100644 --- a/infer/src/backend/utils.mli +++ b/infer/src/backend/utils.mli @@ -233,7 +233,12 @@ module Arg : sig 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 diff --git a/infer/src/clang/cMain.ml b/infer/src/clang/cMain.ml index d386dd324..7c73b3489 100644 --- a/infer/src/clang/cMain.ml +++ b/infer/src/clang/cMain.ml @@ -96,9 +96,6 @@ let print_usage_exit () = Arg.usage arg_desc usage; exit(1) -let () = - Arg.parse arg_desc (fun _ -> ()) usage - let buffer_len = 16384 (* 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; raise exc -let _ = +let () = + Arg.parse "INFERCLANG_ARGS" arg_desc (fun _ -> ()) usage ; Config.print_types := true; if Option.is_none !CFrontend_config.source_file then (Printing.log_err "Incorrect command line arguments\n"; diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index 24257a08d..a5c1aee8e 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -78,7 +78,7 @@ let print_usage_exit () = exit(1) let () = - Arg.parse arg_desc (fun _ -> ()) usage; + Arg.parse "INFERJAVA_ARGS" arg_desc (fun _ -> ()) usage; if Config.analyze_models && !JClasspath.models_jar <> "" then failwith "Not expecting model file when analyzing the models"; if not Config.analyze_models && !JClasspath.models_jar = "" then diff --git a/infer/src/llvm/lMain.ml b/infer/src/llvm/lMain.ml index 633d3d234..27b588da6 100644 --- a/infer/src/llvm/lMain.ml +++ b/infer/src/llvm/lMain.ml @@ -67,7 +67,7 @@ let store_tenv tenv = Sil.store_tenv_to_file tenv_filename tenv let () = - Arg.parse arg_desc (fun _ -> ()) usage; + Arg.parse "INFERLLVM_ARGS" arg_desc (fun _ -> ()) usage; begin match !LConfig.source_filename with | None -> print_usage_exit () | Some source_filename -> init_global_state source_filename diff --git a/infer/src/scripts/checkCopyright.ml b/infer/src/scripts/checkCopyright.ml index 66e0ec7e3..656caff9c 100644 --- a/infer/src/scripts/checkCopyright.ml +++ b/infer/src/scripts/checkCopyright.ml @@ -275,6 +275,6 @@ let () = let to_check = ref [] in let add_file_to_check fname = 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); exit 0