[config] migrate help to use man pages

Summary:
Glorious, glorious man pages.

This changes a bunch of things that were hard to break up from the diff, so the
resulting diff is big.

Use `Cmdliner.Manpage` to format man pages (and also format a bit ourselves
since it is so stubborn).

As a bonus, introduce the following subcommands:

```
infer run ... # same as default mode with -- before
infer capture ... # -a capture
infer compile ... # -a compile
infer analyze ... # InferAnalyze
infer report ... # InferPrint
infer diff ... # this one is not new
infer clang ... # InferClang, not that you should use it
```

The man pages can still be improved a lot. Notable missing sections:
`ENVIRONMENT`, stuff about .inferconfig, some example usage, `DESCRIPTION`, ...

Reviewed By: jberdine

Differential Revision: D4921083

fbshipit-source-id: 9602230
master
Jules Villard 8 years ago committed by Facebook Github Bot
parent ebd5ec0013
commit 709376945f

@ -2,6 +2,7 @@ S src/**
B _build/infer/** B _build/infer/**
PKG ANSITerminal PKG ANSITerminal
PKG atdgen PKG atdgen
PKG cmdliner
PKG core PKG core
PKG javalib PKG javalib
PKG oUnit PKG oUnit

@ -40,7 +40,7 @@ OCAMLBUILD_OPTIONS = \
-tag-line "<*{clang/clang_ast_*,backend/jsonbug_*,checkers/stacktree_*}>: warn(-27-32-34-35-39)" \ -tag-line "<*{clang/clang_ast_*,backend/jsonbug_*,checkers/stacktree_*}>: warn(-27-32-34-35-39)" \
-tag-line "<*/{,*/}*.{ml,re}{,i}>: package(ppx_compare)" \ -tag-line "<*/{,*/}*.{ml,re}{,i}>: package(ppx_compare)" \
-tag thread \ -tag thread \
-pkgs ANSITerminal,atdgen,core,extlib,oUnit,str,unix,xmlm,yojson,zip -pkgs ANSITerminal,atdgen,cmdliner,core,extlib,oUnit,str,unix,xmlm,yojson,zip
ifeq ($(ENABLE_OCAML_BINANNOT),yes) ifeq ($(ENABLE_OCAML_BINANNOT),yes)
OCAMLBUILD_OPTIONS += -cflags -bin-annot OCAMLBUILD_OPTIONS += -cflags -bin-annot

@ -182,7 +182,7 @@ let resolve_infer_eradicate_conflict
let source_file = SourceFile.UNSAFE.from_string issue.file in let source_file = SourceFile.UNSAFE.from_string issue.file in
let filters = filters_of_analyzer Config.Eradicate in let filters = filters_of_analyzer Config.Eradicate in
filters.path_filter source_file in filters.path_filter source_file in
Config.equal_analyzer analyzer Config.Infer && Config.equal_analyzer analyzer Config.BiAbduction &&
String.equal issue.bug_type (Localise.to_issue_id Localise.null_dereference) && String.equal issue.bug_type (Localise.to_issue_id Localise.null_dereference) &&
file_is_whitelisted () in file_is_whitelisted () in
let filter issues = List.filter ~f:(Fn.non should_discard_issue) issues in let filter issues = List.filter ~f:(Fn.non should_discard_issue) issues in
@ -198,7 +198,7 @@ let do_filter
~(skip_duplicated_types: bool): Differential.t = ~(skip_duplicated_types: bool): Differential.t =
if Config.filtering then ( if Config.filtering then (
diff diff
|> (if Config.equal_analyzer Config.analyzer Config.Infer then |> (if Config.equal_analyzer Config.analyzer Config.BiAbduction then
skip_anonymous_class_renamings skip_anonymous_class_renamings
else Fn.id) else Fn.id)
|> (if skip_duplicated_types then |> (if skip_duplicated_types then

@ -28,7 +28,7 @@ let register_perf_stats_report () => {
let () = { let () = {
Logging.set_log_file_identifier Logging.set_log_file_identifier
CommandLineOption.(Infer Analysis) (Option.map f::Filename.basename Config.cluster_cmdline); CommandLineOption.Analyze (Option.map f::Filename.basename Config.cluster_cmdline);
if Config.print_builtins { if Config.print_builtins {
Builtin.print_and_exit () Builtin.print_and_exit ()
}; };

@ -265,11 +265,11 @@ let should_report (issue_kind: Exceptions.err_kind) issue_type error_desc eclass
switch Config.analyzer { switch Config.analyzer {
| Eradicate | Eradicate
| Tracing => true | Tracing => true
| Capture | BiAbduction
| CaptureOnly
| Checkers | Checkers
| Compile | CompileOnly
| Crashcontext | Crashcontext
| Infer
| Linters => false | Linters => false
}; };
if analyzer_is_whitelisted { if analyzer_is_whitelisted {
@ -787,9 +787,7 @@ module Report = {
module Summary = { module Summary = {
let pp_summary_out summary => { let pp_summary_out summary => {
let proc_name = Specs.get_proc_name summary; let proc_name = Specs.get_proc_name summary;
if Config.quiet { if (CLOpt.equal_command Config.command CLOpt.Report && not Config.quiet) {
()
} else {
L.stdout "Procedure: %a@\n%a@." Typ.Procname.pp proc_name Specs.pp_summary_text summary L.stdout "Procedure: %a@\n%a@." Typ.Procname.pp proc_name Specs.pp_summary_text summary
} }
}; };
@ -1313,3 +1311,5 @@ let main ::report_csv ::report_json => {
}; };
print_issues formats_by_report_kind print_issues formats_by_report_kind
}; };
let main_from_config () => main report_csv::Config.bugs_csv report_json::Config.bugs_json;

@ -9,3 +9,5 @@
open! IStd; open! IStd;
let main: report_csv::option string => report_json::option string => unit; let main: report_csv::option string => report_json::option string => unit;
let main_from_config: unit => unit;

@ -8,4 +8,4 @@
*/ */
open! IStd; open! IStd;
let () = InferPrint.main report_csv::Config.bugs_csv report_json::Config.bugs_json; let () = InferPrint.main_from_config ();

@ -24,8 +24,8 @@ let pp_prolog fmt clusters =
let compilation_dbs_cmd = let compilation_dbs_cmd =
List.map ~f:infer_flag_of_compilation_db !Config.clang_compilation_dbs List.map ~f:infer_flag_of_compilation_db !Config.clang_compilation_dbs
|> String.concat ~sep:" " |> escape in |> String.concat ~sep:" " |> escape in
F.fprintf fmt "INFERANALYZE= %s --results-dir '%s' %s \n@." F.fprintf fmt "INFERANALYZE = '%s' --results-dir '%s' %s@\n@\n"
(Config.bin_dir ^/ (Config.exe_name Analyze)) (Config.(bin_dir ^/ infer_analyze_exe_name))
(escape Config.results_dir) (escape Config.results_dir)
compilation_dbs_cmd; compilation_dbs_cmd;
F.fprintf fmt "CLUSTERS="; F.fprintf fmt "CLUSTERS=";
@ -35,8 +35,8 @@ let pp_prolog fmt clusters =
F.fprintf fmt "%a " Cluster.pp_cluster_name (i+1)) F.fprintf fmt "%a " Cluster.pp_cluster_name (i+1))
clusters; clusters;
F.fprintf fmt "@.@.default: test@.@.all: test@.@."; F.fprintf fmt "@\n@\ndefault: test@\n@\nall: test@\n@\n";
F.fprintf fmt "test: $(CLUSTERS)@."; F.fprintf fmt "test: $(CLUSTERS)@\n";
if Config.show_progress_bar then F.fprintf fmt "\t@@echo@\n@." if Config.show_progress_bar then F.fprintf fmt "\t@@echo@\n@."
let pp_epilog fmt () = let pp_epilog fmt () =

@ -373,9 +373,9 @@ let analyze driver_mode =
| _ when Config.maven -> | _ when Config.maven ->
(* Called from Maven, only do capture. *) (* Called from Maven, only do capture. *)
false, false false, false
| _, (Capture | Compile) -> | _, (CaptureOnly | CompileOnly) ->
false, false false, false
| _, (Infer | Eradicate | Checkers | Tracing | Crashcontext) -> | _, (BiAbduction | Checkers | Crashcontext | Eradicate | Tracing) ->
true, true true, true
| _, Linters -> | _, Linters ->
false, true in false, true in
@ -493,7 +493,7 @@ let infer_mode () =
remove_results_dir () ; remove_results_dir () ;
create_results_dir () ; create_results_dir () ;
(* re-set log files, as default files were in results_dir removed above *) (* re-set log files, as default files were in results_dir removed above *)
if not Config.buck_cache_mode then L.set_log_file_identifier CLOpt.(Infer Driver) None; if not Config.buck_cache_mode then L.set_log_file_identifier CLOpt.Run None;
if Config.print_builtins then Builtin.print_and_exit () ; if Config.print_builtins then Builtin.print_and_exit () ;
if CLOpt.is_originator then L.do_out "%s@\n" Config.version_string ; if CLOpt.is_originator then L.do_out "%s@\n" Config.version_string ;
if Config.debug_mode || Config.stats_mode then log_infer_args driver_mode ; if Config.debug_mode || Config.stats_mode then log_infer_args driver_mode ;
@ -545,6 +545,7 @@ let differential_mode () =
Differential.to_files diff out_path Differential.to_files diff out_path
let () = let () =
match Config.final_parse_action with match Config.command with
| Differential -> differential_mode () | Report -> InferPrint.main_from_config ()
| ReportDiff -> differential_mode ()
| _ -> infer_mode () | _ -> infer_mode ()

@ -0,0 +1,272 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
module CLOpt = CommandLineOption
type data = { long: string; command_doc: CLOpt.command_doc }
let inferconfig_env_var = "INFERCONFIG"
(** Name of the infer configuration file *)
let inferconfig_file = ".inferconfig"
let command_to_long = CLOpt.[
Analyze, "analyze"; Capture, "capture"; Clang, "clang"; Compile, "compile"; Report, "report";
ReportDiff, "reportdiff"; Run, "run";
]
let long_of_command =
List.Assoc.find_exn ~equal:CLOpt.equal_command command_to_long
let exe_name_of_command cmd =
let long = long_of_command cmd in
(* InferClang is special because it's not really a user-facing executable *)
if CLOpt.equal_command cmd CLOpt.Clang then "InferClang"
else "infer-" ^ long
let mk_command_doc ~see_also:see_also_commands ?and_also ?environment:environment_opt
?files:files_opt ~synopsis =
let section = 1 in
let see_also =
let exe_names = List.map see_also_commands ~f:(fun cmd ->
let exe = exe_name_of_command cmd in
Printf.sprintf "$(b,%s)(%d)" (Cmdliner.Manpage.escape exe) section) in
let suffix = match and_also with None -> "" | Some msg -> " " ^ msg in
[`P (String.concat ~sep:", " exe_names ^ suffix)] in
let environment = Option.value environment_opt
~default:[`I (Printf.sprintf "$(b,%s), $(b,%s), $(b,%s)"
CLOpt.args_env_var inferconfig_env_var CLOpt.strict_mode_env_var,
Printf.sprintf "See the %s section in the manual of $(b,infer)(%d)."
Cmdliner.Manpage.s_environment section)] in
let files = Option.value files_opt
~default:[`I (Printf.sprintf "$(b,%s)" inferconfig_file,
Printf.sprintf "See the %s section in the manual of $(b,infer)(%d)."
Cmdliner.Manpage.s_files section)] in
CLOpt.mk_command_doc ~section ~version:Version.versionString
~date:Version.man_pages_last_modify_date ~synopsis:[`Pre synopsis] ~environment ~files ~see_also
let analyze =
mk_command_doc ~title:"Infer Analysis"
~short_description:"analyze the files captured by infer"
~synopsis:"$(b,infer) $(b,analyze) $(i,[options])\n\
$(b,infer) $(i,[options])"
~description:[`P "Analyze the files captured in the project results directory and report."]
~see_also:CLOpt.[Report; Run]
let capture =
mk_command_doc ~title:"Infer Compilation Capture"
~short_description:"capture source files for later analysis"
~synopsis:"$(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,buck) $(i,...)\n\
$(b,infer) $(b,capture) $(b,--flavors) $(i,[options]) $(b,--) $(b,buck) $(i,...)\n\
$(b,infer) $(b,capture) $(b,--buck-compilation-database) $(i,[no-]deps) \
$(i,[options]) $(b,--) $(b,buck) $(i,...)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--compilation-database) $(i,file)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--compilation-database-escaped) \
$(i,file)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,gradle)/$(b,gradlew) \
$(i,...)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,javac) $(i,...)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,make)/$(b,clang)/$(b,gcc) \
$(i,...)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,mvn)/$(b,mvnw) \
$(i,...)\n\
$(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,ndk-build) $(i,...)\n\
$(b,infer) $(b,capture) $(i,[--no-xcpretty]) $(i,[options]) $(b,--) \
$(b,xcodebuild) $(i,...)"
~description:[
`P "Capture the build command or compilation database specified on the command line: infer \
intercepts calls to the compiler to read source files, translate them into infer's \
intermediate representation, and store the result of the translation in the results \
directory.";
]
~see_also:CLOpt.[Analyze;Compile;Run]
let clang =
mk_command_doc ~title:"Infer Clang Capture"
~short_description:"internal tool to capture clang commands"
~synopsis:"$(b,InferClang) $(i,[clang options])"
~description:[`P "This is used internally by other infer commands. You shouldn't need to call \
this directly."]
~options:[`P "Accepts the same command line options as $(b,clang)(1) (but still reads infer \
options from the environment)."]
~see_also:CLOpt.[Capture]
let compile =
mk_command_doc ~title:"Infer Project Compilation"
~short_description:"compile project from within the infer environment"
~synopsis:"$(b,infer) $(b,compile) $(b,--) $(i,[compile command])"
~description:[
`P "Intercepts compilation commands similarly to $(b,infer-capture), but simply execute \
these compilation commands and do not perform any translation of the source files. This \
can be useful to configure build systems or for debugging purposes.";
]
~examples:[
`P "$(b,cmake)(1) hardcodes the absolute paths to the compiler inside the Makefiles it \
generates, which defeats the later capture of compilation commands by infer. Thus, to \
capture a CMake project, one should configure the project from within the infer build \
environment, for instance:";
`Pre " \
mkdir build && cd build\n \
infer compile -- cmake ..\n \
infer capture -- make";
`P "The same solution can be used for projects whose \"./configure\" script hardcodes the \
paths to the compilers, for instance:";
`Pre " \
infer compile -- ./configure\n \
infer capture -- make";
`P "Another solution for CMake projects is to use CMake's compilation databases, for \
instance:";
`Pre " \
mkdir build && cd build\n \
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..\n \
infer capture --compilation-database compile_commands.json";
]
~see_also:CLOpt.[Capture]
let infer = mk_command_doc ~title:"Infer Static Analyzer"
~short_description:"static analysis for Java and C/C++/Objective-C/Objective-C++"
~synopsis:"$(b,infer) $(b,analyze) $(i,[options])\n\
$(b,infer) $(b,capture) $(i,[options])\n\
$(b,infer) $(b,compile) $(i,[options])\n\
$(b,infer) $(b,report) $(i,[options])\n\
$(b,infer) $(b,reportdiff) $(i,[options])\n\
$(b,infer) $(b,run) $(i,[options])\n\
$(b,infer) $(b,--compilation-database[-escaped]) $(i,file) $(i,[options])\n\
$(b,infer) $(i,[options]) $(b,--) $(b,compile command)\n\
$(b,infer) $(i,[options])"
~description:[
`P "Infer is a static analyzer. Given a collection of source files written in Java or in \
languages of the C family, and a command to build them, infer produces a list of \
potential issues.";
`P "Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this \
manual. See their respective manuals for more information about each.";
]
~options:[
`P "If a compilation command is specified via the $(b,--) option or one of the \
$(b,--clang-compilation-database[-escaped]) options, $(b,infer) behaves as \
$(b,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1).";
`P "See the manuals of individual infer commands for details about their supported options.";
`P "Every infer command accepts the arguments from all the other infer commands. The same \
option may affect and thus be list in the manual of several commands.";
`P (Printf.sprintf
"Options are read from the $(b,%s) file, then from the $(b,%s) environment variable, \
then from the command line. Options in $(b,%s) take precedence over options in \
$(b,%s), and options passed on the command line take precedence over options in \
$(b,%s). See the $(i,%s) and $(i,%s) sections of this manual for more information."
inferconfig_file CLOpt.args_env_var
CLOpt.args_env_var
inferconfig_file
CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files
);
]
~environment:[
`P (Printf.sprintf
"Extra arguments may be passed to all infer commands using the $(b,%s) \
environment variable (see the $(i,%s) section). $(b,%s) is expected to contain a \
string of %c-separated options. For instance, calling `%s=--debug^--print-logs infer` \
is equivalent to calling `infer --debug --print-logs`."
CLOpt.args_env_var
Cmdliner.Manpage.s_options CLOpt.args_env_var
CLOpt.env_var_sep CLOpt.args_env_var
);
`P (Printf.sprintf
"$(b,%s): Tells infer where to find the %s file. (See the %s section)"
inferconfig_env_var inferconfig_file Cmdliner.Manpage.s_files
);
`P (Printf.sprintf
"If $(b,%s) is set to \"1\", then infer commands will exit with an error code in some \
cases when otherwise a simple warning would be emitted on stderr, for instance if a \
deprecated form of an option is used."
CLOpt.strict_mode_env_var
);
]
~files:[
`P (Printf.sprintf
"$(b,%s) can be used to store infer options. Its format is that of a JSON \
record, where fields are infer long-form options, without their leading \"--\", and \
values depend on the type of the option:" inferconfig_file);
`Noblank;
`P "- for switches options, the value is a JSON boolean (true or false, without quotes)";
`Noblank;
`P "- for integers, the value is a JSON integer (without quotes)";
`Noblank;
`P "- string options have string values";
`Noblank;
`P (Printf.sprintf "- path options have string values, and are interpreted relative to the \
location of the %s file" inferconfig_file);
`Noblank;
`P "- cumulative options are JSON arrays of the appropriate type";
`P (Printf.sprintf "Infer will look for an $(b,%s) file in the current directory, then its \
parent, etc., stopping at the first $(b,%s) file found."
inferconfig_file inferconfig_file);
`P "Example:";
`Pre " {\
\n \"cxx\": false,\
\n \"infer-blacklist-files-containing\": [\"@generated\",\"@Generated\"]\
\n }";
]
~see_also:(List.filter ~f:(function | CLOpt.Clang -> false | _ -> true) CLOpt.all_commands)
~and_also:", $(b,inferTraceBugs)"
"infer"
let report =
mk_command_doc ~title:"Infer Reporting"
~short_description:"compute and manipulate infer results"
~synopsis:"$(b,infer) $(b,report) $(i,[options]) [$(i,file.specs)...]"
~description:[
`P "Read, convert, and print .specs files in the results directory. Each spec is printed to \
standard output unless option -q is used.";
`P "If no specs file are passed on the command line, process all the .specs in the results \
directory.";
]
~see_also:CLOpt.[ReportDiff; Run]
let reportdiff =
mk_command_doc ~title:"Infer Report Difference"
~short_description:"compute the differences between two infer reports"
~synopsis:"$(b,infer) $(b,reportdiff) $(b,--report-current) $(i,file) \
$(b,--report-previous) $(i,file) $(i,[options])"
~description:[
`P "Given two infer reports $(i,previous) and $(i,current), compute the following three \
reports and store them inside the \"differential/\" subdirectory of the results \
directory:";
`Noblank; `P "- $(b,introduced.json) contains the issues found in $(i,current) but not \
$(i,previous);";
`Noblank; `P "- $(b,fixed.json) contains the issues found in $(i,previous) but not \
$(i,current);";
`Noblank; `P "- $(b,preexisting.json) contains the issues found in both $(i,previous) and \
$(i,current).";
`P "All three files follow the same format as normal infer reports.";
]
~see_also:CLOpt.[Report]
let run =
mk_command_doc ~title:"Infer Analysis of a Project"
~short_description:"capture source files, analyze, and report"
~synopsis:"$(b,infer) $(b,run) $(i,[options])\n\
$(b,infer) $(i,[options]) $(b,--) $(i,compile command)"
~description:[
`P "Calling \"$(b,infer) $(b,run) $(i,[options])\" is equivalent to performing the following \
sequence of commands:";
`Pre "$(b,infer) $(b,capture) $(i,[options])\n\
$(b,infer) $(b,analyze) $(i,[options])";
]
~see_also:CLOpt.[Analyze; Capture; Report]
let command_to_data =
let mk cmd mk_doc =
let long = long_of_command cmd in
let command_doc = mk_doc (exe_name_of_command cmd) in
cmd, { long; command_doc } in
CLOpt.[mk Analyze analyze; mk Capture capture; mk Clang clang; mk Compile compile;
mk Report report; mk ReportDiff reportdiff; mk Run run]
let data_of_command command =
List.Assoc.find_exn ~equal:CLOpt.equal_command command_to_data command

@ -0,0 +1,19 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
module CLOpt = CommandLineOption
type data = { long: string; command_doc: CLOpt.command_doc }
val inferconfig_env_var : string
val inferconfig_file : string
val infer : CLOpt.command_doc
val data_of_command : CLOpt.command -> data

File diff suppressed because it is too large Load Diff

@ -14,18 +14,30 @@ open! IStd
(** Print to stderr in case of error, fails in strict mode *) (** Print to stderr in case of error, fails in strict mode *)
val warnf : ('a, Format.formatter, unit) format -> 'a val warnf : ('a, Format.formatter, unit) format -> 'a
(** a section is a part of infer that can be affected by an infer option *) type parse_mode =
type section = | InferCommand (** parse arguments as arguments for infer *)
Analysis | BufferOverrun | Checkers | Clang | Crashcontext | Driver | Java | Print | Javac (** parse arguments passed to the Java compiler *)
| NoParse (** all arguments are anonymous arguments, no parsing is attempted *)
[@@deriving compare] [@@deriving compare]
val all_sections : section list (** Main modes of operation for infer *)
type command =
type 'a parse = Differential | Infer of 'a | Javac | NoParse | Analyze (** analyze previously captured source files *)
| Capture (** capture compilation commands and translate source files into infer's intermediate
language *)
| Clang (** run and accept the same arguments as the clang compiler, may also capture the source
files compiled, and may also not actually compile the files depending on other options
*)
| Compile (** set up the infer environment then run the compilation commands without capturing the
source files *)
| Report (** post-process infer results and reports *)
| ReportDiff (** compute the difference of two infer reports *)
| Run (** orchestrate the capture, analysis, and reporting of a compilation command *)
[@@deriving compare]
type parse_mode = section list parse [@@deriving compare] val equal_command : command -> command -> bool
type parse_action = section parse [@@deriving compare] val all_commands : command list
val is_originator : bool val is_originator : bool
@ -43,15 +55,15 @@ val init_work_dir : string
- [f] specifies a transformation to be performed on the parsed value before setting the config - [f] specifies a transformation to be performed on the parsed value before setting the config
variable variable
- [symbols] is an association list sometimes used in place of [f] - [symbols] is an association list sometimes used in place of [f]
- [parse_mode] declares which parse mode the option is for. In the case of Infer, that includes - [parse_mode] declares which parse mode the option is for
the sections for which the option should be included in the external documentation (--help), - [in_help] indicates the man pages in which the command should be documented, as generated by
otherwise it appears only in --help-full calling infer with --help. Otherwise it appears only in --help-full.
- [meta] is a meta-variable naming the parsed value for documentation purposes - [meta] is a meta-variable naming the parsed value for documentation purposes
- a documentation string - a documentation string
*) *)
type 'a t = type 'a t =
?deprecated:string list -> long:string -> ?short:char -> ?deprecated:string list -> long:string -> ?short:char ->
?parse_mode:parse_mode -> ?meta:string -> string -> ?parse_mode:parse_mode -> ?in_help:(command * string) list -> ?meta:string -> string ->
'a 'a
(** [mk_set variable value] defines a command line option which sets [variable] to [value]. *) (** [mk_set variable value] defines a command line option which sets [variable] to [value]. *)
@ -128,43 +140,80 @@ val mk_anon : unit -> string list ref
reverse order they appeared on the command line. For example, calling [mk_rest] and parsing reverse order they appeared on the command line. For example, calling [mk_rest] and parsing
[exe -opt1 -opt2 -- arg1 arg2] will result in the returned ref containing [arg2; arg1]. *) [exe -opt1 -opt2 -- arg1 arg2] will result in the returned ref containing [arg2; arg1]. *)
val mk_rest : val mk_rest :
?parse_mode:parse_mode -> string -> ?parse_mode:parse_mode-> ?in_help:(command * string) list -> string ->
string list ref string list ref
(** [mk_rest_actions doc ~usage command_to_parse_action] defines a [string list ref] of the command (** [mk_rest_actions doc ~usage command_to_parse_mode] defines a [string list ref] of the command
line arguments following ["--"], in the reverse order they appeared on the command line. [usage] line arguments following ["--"], in the reverse order they appeared on the command line. [usage]
is the usage message in case of parse errors or if --help is passed. For example, calling is the usage message in case of parse errors or if --help is passed. For example, calling
[mk_action] and parsing [exe -opt1 -opt2 -- arg1 arg2] will result in the returned ref [mk_action] and parsing [exe -opt1 -opt2 -- arg1 arg2] will result in the returned ref
containing [arg2; arg1]. Additionally, the first arg following ["--"] is passed to containing [arg2; arg1]. Additionally, the first arg following ["--"] is passed to
[command_to_parse_action] to obtain the parse action that will be used to parse the remaining [command_to_parse_mode] to obtain the parse action that will be used to parse the remaining
arguments. *) arguments. *)
val mk_rest_actions : val mk_rest_actions :
?parse_mode:parse_mode -> string -> ?parse_mode:parse_mode -> ?in_help:(command * string) list -> string ->
usage:string -> (string -> parse_action) usage:string -> (string -> parse_mode)
-> string list ref -> string list ref
type command_doc
(** When the option is found on the command line, either as [--long] or [name], the current parse
action is discarded and the following arguments are parsed using [parse_action]. [name] defaults (** [mk_command_doc ~title ~section ~version ~short_description ~synopsis ~description ~see_also
to [long]. *) command_exe] records information about a command that is used to create its man page. A lot of
val mk_switch_parse_action : parse_action -> usage:string -> ?deprecated:string list -> the concepts are taken from man-pages(7).
long:string -> ?name:string -> ?parse_mode:section list parse -> ?meta:string -> string -> unit
- [command_exe] is the name of the command, preferably an executable that selects the command
- [title] will be the title of the manual
- [section] will be the section of the manual (the number 7 in man-pages(7))
- [version] is the version string of the command
- [date] is the date of the last modification of the manual
- [short_description] is a one-line description of the command
- [options] if specified, will populate the OPTIONS section; otherwise, the options are taken
from the command's
- All the other [section_name] options correspond to the contents of the section [section_name].
Some are mandatory and some are not.
*)
val mk_command_doc : title:string -> section:int -> version:string -> date:string ->
short_description:string -> synopsis:Cmdliner.Manpage.block list ->
description:Cmdliner.Manpage.block list ->
?options:Cmdliner.Manpage.block list ->
?exit_status:Cmdliner.Manpage.block list ->
?environment:Cmdliner.Manpage.block list ->
?files:Cmdliner.Manpage.block list ->
?notes:Cmdliner.Manpage.block list ->
?bugs:Cmdliner.Manpage.block list ->
?examples:Cmdliner.Manpage.block list ->
see_also:Cmdliner.Manpage.block list ->
string -> command_doc
(** [mk_subcommand command ~long command_doc] defines the subcommand [command]. A subcommand is
activated by passing [--long], [name], or any [-key] for [key] in [deprecated] on the command
line. [name] defaults to [long]. A man page is automatically generated for [command] based on
the information in [command_doc]. *)
val mk_subcommand : command -> ?accept_unknown_args:bool ->
?deprecated:string list -> long:string -> ?name:string ->
?parse_mode:parse_mode -> ?in_help:(command * string) list -> command_doc -> unit
(** environment variable use to pass arguments from parent to child processes *) (** environment variable use to pass arguments from parent to child processes *)
val args_env_var : string val args_env_var : string
val strict_mode_env_var : string
(** separator of argv elements when encoded into environment variables *) (** separator of argv elements when encoded into environment variables *)
val env_var_sep : char val env_var_sep : char
(** [extend_env_args args] appends [args] to those passed via [args_env_var] *) (** [extend_env_args args] appends [args] to those passed via [args_env_var] *)
val extend_env_args : string list -> unit val extend_env_args : string list -> unit
(** [parse ~usage parse_action] parses command line arguments as specified by preceding calls to the (** [parse ~usage parse_mode command] parses command line arguments as specified by preceding calls
[mk_*] functions, and returns a function that prints the usage message and help text then exits. to the [mk_*] functions, and returns:
- the command selected by the user on the command line, except if [command] is not None in which
case it is considered "pre-selected" for the user;
- a function that prints the usage message and help text then exits with the code passed as
argument.
The decoded values of the inferconfig file [config_file], if provided, are parsed, followed by The decoded values of the inferconfig file [config_file], if provided, are parsed, followed by
the decoded values of the environment variable [args_env_var], followed by [Sys.argv] if the decoded values of the environment variable [args_env_var], followed by [Sys.argv] if
[parse_action] is one that should parse command line arguments (this is defined in the [parse_mode] is one that should parse command line arguments (this is defined in the
implementation of this module). Therefore arguments passed on the command line supersede those implementation of this module). Therefore arguments passed on the command line supersede those
specified in the environment variable, which themselves supersede those passed via the config specified in the environment variable, which themselves supersede those passed via the config
file. file.
@ -172,7 +221,12 @@ val extend_env_args : string list -> unit
WARNING: An argument will be interpreted as many times as it appears in all of the config file, WARNING: An argument will be interpreted as many times as it appears in all of the config file,
the environment variable, and the command line. The [args_env_var] is set to the set of options the environment variable, and the command line. The [args_env_var] is set to the set of options
parsed in [args_env_var] and on the command line. *) parsed in [args_env_var] and on the command line. *)
val parse : ?config_file:string -> usage:Arg.usage_msg -> parse_action -> parse_action * (int -> 'a) val parse : ?config_file:string -> usage:Arg.usage_msg -> parse_mode -> command option
-> command option * (int -> 'a)
(** [is_env_var_set var] is true if $[var]=1 *) (** [is_env_var_set var] is true if $[var]=1 *)
val is_env_var_set : string -> bool val is_env_var_set : string -> bool
(** Display the manual of [command] to the user, or [command_doc] if [command] is None. If
[internal_section] is true, add a section about internal (hidden) options. *)
val show_manual : ?internal_section:string -> command_doc -> command option -> unit

File diff suppressed because it is too large Load Diff

@ -10,16 +10,14 @@
open! IStd open! IStd
module CLOpt = CommandLineOption
(** Configuration values: either constant, determined at compile time, or set at startup (** Configuration values: either constant, determined at compile time, or set at startup
time by system calls, environment variables, or command line options *) time by system calls, environment variables, or command line options *)
type exe = Analyze | Clang | Driver | Print [@@deriving compare]
val exe_name : exe -> string
(** Various kind of analyzers *)
type analyzer = type analyzer =
| Capture | Compile | Infer | Eradicate | Checkers | Tracing | Crashcontext | Linters | BiAbduction | CaptureOnly | CompileOnly | Eradicate | Checkers | Tracing | Crashcontext
| Linters
[@@deriving compare] [@@deriving compare]
val equal_analyzer : analyzer -> analyzer -> bool val equal_analyzer : analyzer -> analyzer -> bool
@ -101,6 +99,8 @@ val frontend_stats_dir_name : string
val global_tenv_filename : string val global_tenv_filename : string
val idempotent_getters : bool val idempotent_getters : bool
val incremental_procs : bool val incremental_procs : bool
val infer_exe_name : string
val infer_analyze_exe_name : string
val infer_py_argparse_error_exit_code : int val infer_py_argparse_error_exit_code : int
val initial_analysis_time : float val initial_analysis_time : float
val ivar_attributes : string val ivar_attributes : string
@ -200,6 +200,7 @@ val clang_frontend_do_lint : bool
val clang_ignore_regex : string option val clang_ignore_regex : string option
val clang_include_to_override_regex : string option val clang_include_to_override_regex : string option
val cluster_cmdline : string option val cluster_cmdline : string option
val command : CLOpt.command
val compute_analytics : bool val compute_analytics : bool
val continue_capture : bool val continue_capture : bool
val default_linters : bool val default_linters : bool
@ -235,7 +236,6 @@ val file_renamings : string option
val filter_paths : bool val filter_paths : bool
val filter_report_paths : string option val filter_report_paths : string option
val filtering : bool val filtering : bool
val final_parse_action : CommandLineOption.parse_action
val flavors : bool val flavors : bool
val from_json_report : string option val from_json_report : string option
val frontend_debug : bool val frontend_debug : bool
@ -288,7 +288,6 @@ val no_translate_libs : bool
val objc_memory_model_on : bool val objc_memory_model_on : bool
val only_footprint : bool val only_footprint : bool
val out_file_cmdline : string val out_file_cmdline : string
val parse_action : CommandLineOption.parse_action
val pmd_xml : bool val pmd_xml : bool
val precondition_stats : bool val precondition_stats : bool
val print_logs : bool val print_logs : bool

@ -29,15 +29,12 @@ let dup_formatter fmt1 fmt2 =
Format.pp_set_formatter_output_functions fmt1 out_string flush Format.pp_set_formatter_output_functions fmt1 out_string flush
(** Name of dir for logging the output in the specific executable *) (** Name of dir for logging the output in the specific executable *)
let log_dir_of_action (action : CLOpt.parse_action) = match action with let log_dir_of_command (command : CLOpt.command) = match command with
| Infer (Analysis | BufferOverrun | Checkers | Crashcontext) -> "analyze" | Analyze -> "analyze"
| Differential -> "differential" | Capture | Clang | Compile -> "capture"
| Infer Driver -> "driver" | Report -> "report"
| Infer Clang | ReportDiff -> "reportdiff"
| Infer Java | Run -> "driver"
| NoParse
| Javac -> "capture"
| Infer Print -> "print"
let stdout_err_log_files = let stdout_err_log_files =
(((lazy F.std_formatter), (lazy Pervasives.stdout), (((lazy F.std_formatter), (lazy Pervasives.stdout),
@ -54,8 +51,8 @@ let close_log_file fmt chan file =
Out_channel.close c Out_channel.close c
) )
let create_log_file action name_prefix outerr = let create_log_file command name_prefix outerr =
let log_dir = Config.results_dir ^/ Config.log_dir_name ^/ log_dir_of_action action in let log_dir = Config.results_dir ^/ Config.log_dir_name ^/ log_dir_of_command command in
let config_name = match outerr with let config_name = match outerr with
| `Out -> Config.out_file_cmdline | `Out -> Config.out_file_cmdline
| `Err -> Config.err_file_cmdline in | `Err -> Config.err_file_cmdline in
@ -83,34 +80,36 @@ let create_log_file action name_prefix outerr =
"log files flushing"; "log files flushing";
(file_fmt, chan, file) (file_fmt, chan, file)
let should_setup_log_files (action : CLOpt.parse_action) = match action with let should_setup_log_files (command : CLOpt.command) = match command with
| Infer Analysis | Analyze | Capture | Clang | Compile ->
| Infer Clang -> Config.debug_mode || Config.stats_mode Config.debug_mode || Config.stats_mode
| Infer Driver -> true | Run ->
| _ -> false true
| Report | ReportDiff ->
false
let create_outerr_log_files exe prefix_opt = let create_outerr_log_files command prefix_opt =
let lazy3 x = (lazy (fst3 (Lazy.force x)), let lazy3 x = (lazy (fst3 (Lazy.force x)),
lazy (snd3 (Lazy.force x)), lazy (snd3 (Lazy.force x)),
lazy (trd3 (Lazy.force x))) in lazy (trd3 (Lazy.force x))) in
if should_setup_log_files exe then if should_setup_log_files command then
let name_prefix = match prefix_opt with let name_prefix = match prefix_opt with
| Some name -> name ^ "-" | Some name -> name ^ "-"
| None -> "" in | None -> "" in
(lazy (create_log_file exe name_prefix `Out) |> lazy3, (lazy (create_log_file command name_prefix `Out) |> lazy3,
lazy (create_log_file exe name_prefix `Err) |> lazy3) lazy (create_log_file command name_prefix `Err) |> lazy3)
else else
stdout_err_log_files stdout_err_log_files
let ((out_formatter, out_chan, out_file), let ((out_formatter, out_chan, out_file),
(err_formatter, err_chan, err_file)) = (err_formatter, err_chan, err_file)) =
let (o_fmt, o_c, o_f), (e_fmt, e_c, e_f) = let (o_fmt, o_c, o_f), (e_fmt, e_c, e_f) =
create_outerr_log_files Config.parse_action None in create_outerr_log_files Config.command None in
((ref o_fmt, ref o_c, ref o_f), ((ref o_fmt, ref o_c, ref o_f),
(ref e_fmt, ref e_c, ref e_f)) (ref e_fmt, ref e_c, ref e_f))
let set_log_file_identifier exe prefix_opt = let set_log_file_identifier command prefix_opt =
let (o_fmt, o_c, o_f), (e_fmt, e_c, e_f) = create_outerr_log_files exe prefix_opt in let (o_fmt, o_c, o_f), (e_fmt, e_c, e_f) = create_outerr_log_files command prefix_opt in
(* close previous log files *) (* close previous log files *)
close_log_file !out_formatter !out_chan !out_file; close_log_file !out_formatter !out_chan !out_file;
close_log_file !err_formatter !err_chan !err_file; close_log_file !err_formatter !err_chan !err_file;

@ -73,7 +73,7 @@ val set_delayed_prints : print_action list -> unit
val reset_delayed_prints : unit -> unit val reset_delayed_prints : unit -> unit
(** Set a custom identifier to be part of the filename of the current logfiles. *) (** Set a custom identifier to be part of the filename of the current logfiles. *)
val set_log_file_identifier : CommandLineOption.parse_action -> string option -> unit val set_log_file_identifier : CommandLineOption.command -> string option -> unit
(** print to the current out stream, as specified in set_log_file_identifier (** print to the current out stream, as specified in set_log_file_identifier
(note: only prints in debug or in stats mode) *) (note: only prints in debug or in stats mode) *)

@ -49,7 +49,7 @@ let register_perf_stats_report source_file => {
let init_global_state_for_capture_and_linters source_file => { let init_global_state_for_capture_and_linters source_file => {
Logging.set_log_file_identifier Logging.set_log_file_identifier
CLOpt.(Infer Clang) (Some (Filename.basename (SourceFile.to_abs_path source_file))); CLOpt.Clang (Some (Filename.basename (SourceFile.to_abs_path source_file)));
register_perf_stats_report source_file; register_perf_stats_report source_file;
Config.curr_language := Config.Clang; Config.curr_language := Config.Clang;
DB.Results_dir.init source_file; DB.Results_dir.init source_file;
@ -165,7 +165,7 @@ let cc1_capture clang_cmd => {
}; };
Logging.out "@\n*** Beginning capture of file %s ***@\n" source_path; Logging.out "@\n*** Beginning capture of file %s ***@\n" source_path;
if ( if (
Config.equal_analyzer Config.analyzer Config.Compile || Config.equal_analyzer Config.analyzer Config.CompileOnly ||
CLocation.is_file_blacklisted source_path CLocation.is_file_blacklisted source_path
) { ) {
Logging.out "@\n Skip the analysis of source file %s@\n@\n" source_path; Logging.out "@\n Skip the analysis of source file %s@\n@\n" source_path;
@ -179,7 +179,7 @@ let cc1_capture clang_cmd => {
source_path (fun chan_in => run_and_validate_clang_frontend (`Pipe chan_in)) clang_cmd source_path (fun chan_in => run_and_validate_clang_frontend (`Pipe chan_in)) clang_cmd
}; };
/* reset logging to stop capturing log output into the source file's log */ /* reset logging to stop capturing log output into the source file's log */
Logging.set_log_file_identifier CLOpt.(Infer Clang) None; Logging.set_log_file_identifier CLOpt.Capture None;
() ()
} }
}; };

@ -47,11 +47,11 @@ let add_flavor_to_target target =
add "uber-compilation-database" add "uber-compilation-database"
| Some `NoDeps, _ -> | Some `NoDeps, _ ->
add "compilation-database" add "compilation-database"
| None, Compile -> | None, CompileOnly ->
target target
| None, (Linters | Capture) -> | None, (Linters | CaptureOnly) ->
add "infer-capture-all" add "infer-capture-all"
| None, (Checkers | Infer) -> | None, (BiAbduction | Checkers) ->
add "infer" add "infer"
| None, (Eradicate | Tracing | Crashcontext) -> | None, (Eradicate | Tracing | Crashcontext) ->
failwithf "Analyzer %s is Java-only; not supported with Buck flavors" failwithf "Analyzer %s is Java-only; not supported with Buck flavors"

@ -81,6 +81,6 @@ let compile compiler build_prog build_args =
let capture compiler ~prog ~args = let capture compiler ~prog ~args =
let verbose_out_file = compile compiler prog args in let verbose_out_file = compile compiler prog args in
if Config.analyzer <> Config.Compile then if Config.analyzer <> Config.CompileOnly then
JMain.from_verbose_out verbose_out_file; JMain.from_verbose_out verbose_out_file;
if not (Config.debug_mode || Config.stats_mode) then Unix.unlink verbose_out_file if not (Config.debug_mode || Config.stats_mode) then Unix.unlink verbose_out_file

@ -33,7 +33,7 @@ let infer_profile = lazy
\n </plugins>\ \n </plugins>\
\n </build>\ \n </build>\
\n </profile>\ \n </profile>\
" infer_profile_name (Config.(bin_dir ^/ string_of_analyzer Infer))) " infer_profile_name (Config.(bin_dir ^/ infer_exe_name)))
let pom_worklist = ref [CLOpt.init_work_dir] let pom_worklist = ref [CLOpt.init_work_dir]

@ -502,7 +502,7 @@ let test_resolve_infer_eradicate_conflict =
(* [(test_name, analyzer, expected_hashes); ...] *) (* [(test_name, analyzer, expected_hashes); ...] *)
[ [
("test_resolve_infer_eradicate_conflict_runs_with_infer_analyzer", ("test_resolve_infer_eradicate_conflict_runs_with_infer_analyzer",
Config.Infer, Config.BiAbduction,
([1], [11], [4])); ([1], [11], [4]));
("test_resolve_infer_eradicate_conflict_skips_with_checkers_analyzer", ("test_resolve_infer_eradicate_conflict_skips_with_checkers_analyzer",
Config.Checkers, Config.Checkers,

@ -28,6 +28,7 @@ ocaml-version: [ >= "4.04.0" ]
depends: [ depends: [
"ANSITerminal" {>="0.7"} "ANSITerminal" {>="0.7"}
"atdgen" {>="1.6.0"} "atdgen" {>="1.6.0"}
"cmdliner" {>="1.0.0"}
"core" {<"v0.9"} "core" {<"v0.9"}
"conf-autoconf" "conf-autoconf"
"ctypes" {>="0.9.2"} "ctypes" {>="0.9.2"}

@ -6,6 +6,7 @@ biniou = 1.0.12
camlp4 = 4.04+1 camlp4 = 4.04+1
camlzip = 1.07 camlzip = 1.07
camomile = 0.8.5 camomile = 0.8.5
cmdliner = 1.0.0
conf-autoconf = 0.1 conf-autoconf = 0.1
conf-m4 = 1 conf-m4 = 1
conf-pkg-config = 1.0 conf-pkg-config = 1.0

@ -1,6 +1,7 @@
(* load dependencies *) (* load dependencies *)
#use "topfind";; #use "topfind";;
#thread;; #thread;;
#require "cmdliner";;
#require "core.top";; #require "core.top";;
#require "ctypes";; #require "ctypes";;
#require "ctypes.stubs";; #require "ctypes.stubs";;

Loading…
Cancel
Save