1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
open Filepath
open Compat
exception BuildDepAnalyzeFailed of string
exception BuildCDepAnalyzeFailed of string
exception DependencyMissing of string
exception DependenciesMissing of string list
exception DependencyFailedParsing of string
type dependency = Libname.t * Expr.t option
type cdependency = string * Expr.t option
type dep_opt = {
dep_includes : filepath list;
dep_pp : Pp.t;
}
let parse_output_KsemiVs onNonKV mapFstTy mapSndTys out =
List.map
(fun (k, mv) ->
match mv with
| None -> onNonKV k
| Some v -> (mapFstTy k, List.map mapSndTys (String_utils.words_noempty v)))
(List.map Utils.toKV (String_utils.lines_noempty out))
(* return the (modules list) dependency for a specific file *)
let run_ocamldep dopt srcFile =
let wrap_module_safe f =
try Modname.wrap f
with Modname.InvalidModuleName _ | Modname.EmptyModuleName ->
raise (BuildDepAnalyzeFailed ("ocamldep returned a bad module name " ^ f))
in
let fileType = Filetype.of_filepath srcFile in
let baseFile = fp_to_string srcFile in
let files =
if fileType = Filetype.FileML then
[ baseFile; baseFile ^ "i" ]
else
[ baseFile ]
in
let args =
[ Prog.get_ocamldep () ]
@ Utils.to_include_path_options dopt.dep_includes
@ Pp.to_params dopt.dep_pp @ [ "-modules" ] @ files
in
match Process.run args with
| Process.Failure er -> raise (BuildDepAnalyzeFailed er)
| Process.Success (out, _, _) ->
List.map snd
(parse_output_KsemiVs
(fun _ -> raise (BuildDepAnalyzeFailed ("assumption failed: " ^ out)))
fp wrap_module_safe out)
(* TODO
* gcc escape spaces in filename with a \, tweak strings_words_noempty
* to take that in consideration.
*)
let joinLines s =
let s = bytes_of_string s in
let s_end = bytes_length s in
let rec replace start =
try
let index = bytes_index_from s start '\\' in
if index < s_end - 1 then
if bytes_get s (index + 1) = '\n' then begin
bytes_set s index ' ';
bytes_set s (index + 1) ' ';
replace (index + 2)
end
else
replace (index + 1)
else
s
with Not_found -> s
in
bytes_to_string (replace 0)
let run_ccdep srcDir files : (filename * filepath list) list =
let args = [ Prog.get_cc (); "-MM" ] @ List.map (fun fn -> fp_to_string (srcDir </> fn)) files in
match Process.run args with
| Process.Failure err -> raise (BuildCDepAnalyzeFailed err)
| Process.Success (out, _, _) ->
parse_output_KsemiVs
(fun _ -> raise (BuildCDepAnalyzeFailed "missing semicolon in gcc dependency output"))
fn fp (joinLines out)
|