diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index bb482f399..693239672 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -236,7 +236,7 @@ let initial_analysis_time = Unix.time () (* Resolve symlinks to get to the real executable. The real executable is located in [bin_dir] below, which allows us to find [lib_dir], [models_dir], etc., relative to it. *) let real_exe_name = - Core.Std.Filename.realpath Sys.executable_name + realpath Sys.executable_name let current_exe = if !Sys.interactive then CLOpt.Interactive @@ -402,7 +402,7 @@ let init_work_dir, is_originator = Sys.getcwd () with _ -> Sys.getcwd () in - let real_cwd = Core.Std.Filename.realpath cwd in + let real_cwd = realpath cwd in Unix.putenv "INFER_CWD" real_cwd; (real_cwd, true) @@ -1465,7 +1465,6 @@ and print_types = !print_types and print_using_diff = !print_using_diff and procs_csv = !procs_csv and procs_xml = !procs_xml -and project_root_realpath = Core.Std.Filename.realpath project_root and quandary = !quandary and quiet = !quiet and reactive_mode = !reactive diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 5f8f62f88..fe1d4b422 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -228,7 +228,6 @@ val print_using_diff : bool val procs_csv : string option val procs_xml : string option val project_root : string -val project_root_realpath : string val quandary : bool val quiet : bool val reactive_mode : bool diff --git a/infer/src/base/Utils.ml b/infer/src/base/Utils.ml index d7fe70d69..76e290fa2 100644 --- a/infer/src/base/Utils.ml +++ b/infer/src/base/Utils.ml @@ -662,3 +662,12 @@ let rec create_path path = | Unix.Unix_error (Unix.ENOENT, _, _) -> create_path (Filename.dirname path); create_dir path + +let realpath_cache = Hashtbl.create 1023 + +let realpath path = + try Hashtbl.find realpath_cache path + with Not_found -> + let realpath = Core.Std.Filename.realpath path in + Hashtbl.add realpath_cache path realpath; + realpath diff --git a/infer/src/base/Utils.mli b/infer/src/base/Utils.mli index 4c76c4224..d6c8ed8cf 100644 --- a/infer/src/base/Utils.mli +++ b/infer/src/base/Utils.mli @@ -298,3 +298,7 @@ val create_dir : string -> unit (** [create_path path] will create a directory at [path], creating all the parent directories if non-existing *) val create_path : string -> unit + +(** [realpath path] returns path with all symbolic links resolved. It caches results of previous + calls to avoid expensive system calls *) +val realpath : string -> string diff --git a/infer/src/clang/cLocation.ml b/infer/src/clang/cLocation.ml index b862628e0..ce8ceb26a 100644 --- a/infer/src/clang/cLocation.ml +++ b/infer/src/clang/cLocation.ml @@ -30,21 +30,14 @@ let clang_to_sil_location trans_unit_ctx clang_loc = Location.{line; col; file} let file_in_project file = - (* Look at file paths before resolving them to real paths. Do it to - improve performance of most likely case when calling realpath is not needed *) - let file_in_project, used_project_root, used_file = - if string_is_prefix Config.project_root file then - true, Config.project_root, file - else if string_is_prefix Config.project_root_realpath file then - true, Config.project_root_realpath, file - else - let real_root = Config.project_root_realpath in - let real_file = Core.Std.Filename.realpath file in - string_is_prefix real_root real_file, real_root, real_file in + (* IMPORTANT: results of realpath are cached to not ruin performance *) + let real_root = realpath Config.project_root in + let real_file = realpath file in + let file_in_project = string_is_prefix real_root real_file in let paths = Config.skip_translation_headers in let file_should_be_skipped = IList.exists - (fun path -> string_is_prefix (Filename.concat used_project_root path) used_file) + (fun path -> string_is_prefix (Filename.concat real_root path) real_file) paths in file_in_project && not (file_should_be_skipped)