[clang] Create separate module for compilation database

Summary:
Move compilation database into separate module which loads said database from json file.
It will allow to load database from json file without calling buck.

Reviewed By: dulmarod

Differential Revision: D4049255

fbshipit-source-id: b2fa29f
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent 644c7d716a
commit d7a0e706df

@ -0,0 +1,54 @@
(*
* Copyright (c) 2016 - 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! Utils
type compilation_data = {
dir : string;
command : string;
args : string list;
}
type t = compilation_data StringMap.t ref
let empty () = ref StringMap.empty
let get_size database = StringMap.cardinal !database
let iter database f = StringMap.iter f !database
let find database key = StringMap.find key !database
(** Parse the compilation database json file into the compilationDatabase
map. The json file consists of an array of json objects that contain the file
to be compiled, the directory to be compiled in, and the compilation command as a list
and as a string. We pack this information into the compilationDatabase map, and remove the
clang invocation part, because we will use a clang wrapper. *)
let decode_json_file (database : t) should_add_file json_path =
let json = Yojson.Basic.from_file json_path in
let parse_argument compilation_argument =
match compilation_argument with
| `String arg -> arg
| _ -> failwith ("Json file doesn't have the expected format") in
let rec parse_json json =
match json with
| `List arguments ->
IList.iter parse_json arguments
| `Assoc [ ("directory", `String dir);
("file", `String file_path);
("arguments", `List compilation_arguments);
("command", `String _) ] ->
(match IList.map parse_argument compilation_arguments with
| [] -> failwith ("Command cannot be empty")
| command :: args when should_add_file file_path ->
let compilation_data = { dir; command; args;} in
database := StringMap.add file_path compilation_data !database
| _ -> ())
| _ ->
failwith ("Json file doesn't have the expected format") in
parse_json json

@ -0,0 +1,28 @@
(*
* Copyright (c) 2016 - 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! Utils
type t
type compilation_data = {
dir : string;
command : string;
args : string list;
}
val empty : unit -> t
val get_size : t -> int
val iter : t -> (string -> compilation_data -> unit) -> unit
val find : t -> string -> compilation_data
val decode_json_file : t -> (string -> bool) -> string -> unit

@ -8,13 +8,6 @@
*)
open! Utils
module YBU = Yojson.Basic.Util
type compilation_data = {
dir : string;
command : string;
args : string list;
}
let capture_text =
if Config.analyzer = Some Config.Linters then "linting"
@ -50,45 +43,6 @@ let read_files_to_compile () =
DB.SourceFileSet.add file changed_files)
changed_files lines
(** Add file to compilation database, only if it is in changed_files. *)
let add_file_to_compilation_database file_path cmd_options changed_files compilation_database =
let add_file =
match Config.changed_files_index with
| Some _ -> DB.SourceFileSet.mem (DB.source_file_from_string file_path) changed_files
| None -> true in
if add_file then
compilation_database := StringMap.add file_path cmd_options !compilation_database
(** Parse the compilation database json file into the compilationDatabase
map. The json file consists of an array of json objects that contain the file
to be compiled, the directory to be compiled in, and the compilation command as a list
and as a string. We pack this information into the compilationDatabase map, and remove the
clang invocation part, because we will use a clang wrapper. *)
let decode_compilation_database changed_files compilation_database _ path =
let json = Yojson.Basic.from_file path in
let parse_argument compilation_argument =
match compilation_argument with
| `String arg -> arg
| _ -> failwith ("Json file doesn't have the expected format") in
let rec parse_json json =
match json with
| `List arguments ->
IList.iter parse_json arguments
| `Assoc [ ("directory", `String dir);
("file", `String file_path);
("arguments", `List compilation_arguments);
("command", `String _) ] ->
(match IList.map parse_argument compilation_arguments with
| [] -> failwith ("Command cannot be empty")
| command :: args ->
let compilation_data = { dir; command; args;} in
add_file_to_compilation_database file_path compilation_data changed_files
compilation_database)
| _ ->
failwith ("Json file doesn't have the expected format") in
parse_json json
(** The buck targets are assumed to start with //, aliases are not supported. *)
let check_args_for_targets args =
if not (IList.exists (Utils.string_is_prefix "//") args) then
@ -113,7 +67,7 @@ let create_files_stack compilation_database =
let stack = Stack.create () in
let add_to_stack file _ =
Stack.push file stack in
StringMap.iter add_to_stack !compilation_database;
CompilationDatabase.iter compilation_database add_to_stack;
stack
let swap_command cmd =
@ -143,7 +97,7 @@ let replace_clang_arg arg =
let run_compilation_file compilation_database file =
try
let compilation_data = StringMap.find file !compilation_database in
let compilation_data = CompilationDatabase.find compilation_database file in
Unix.chdir compilation_data.dir;
let wrapper_cmd = swap_command compilation_data.command in
let replaced_args = IList.map replace_clang_arg compilation_data.args |> IList.flatten in
@ -156,7 +110,7 @@ let run_compilation_file compilation_database file =
Process.print_error_and_exit "Failed to find compilation data for %s \n%!" file
let run_compilation_database compilation_database =
let number_of_files = StringMap.cardinal !compilation_database in
let number_of_files = CompilationDatabase.get_size compilation_database in
Logging.out "Starting %s %d files \n%!" capture_text number_of_files;
Logging.stdout "Starting %s %d files \n%!" capture_text number_of_files;
let jobsStack = create_files_stack compilation_database in
@ -188,9 +142,13 @@ let get_compilation_database changed_files =
(fun target file -> StringMap.add target file compilation_database_files) in
(* Map from targets to json output *)
let compilation_database_files = IList.fold_left scan_output StringMap.empty lines in
let compilation_database = ref StringMap.empty in
let compilation_database = CompilationDatabase.empty () in
let should_add_file file_path =
match Config.changed_files_index with
| Some _ -> DB.SourceFileSet.mem (DB.source_file_from_string file_path) changed_files
| None -> true in
StringMap.iter
(decode_compilation_database changed_files compilation_database)
(fun _ file -> CompilationDatabase.decode_json_file compilation_database should_add_file file)
compilation_database_files;
compilation_database
with Unix.Unix_error (err, _, _) ->

Loading…
Cancel
Save