File: dependencies.ml

package info (click to toggle)
ocaml-obuild 0.1.11-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 796 kB
  • sloc: ml: 6,570; sh: 171; ansic: 34; makefile: 11
file content (82 lines) | stat: -rw-r--r-- 2,684 bytes parent folder | download | duplicates (2)
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
open Ext.Fugue
open Ext.Filepath
open Ext.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_words_noempty v))
    ) (List.map Utils.toKV (string_lines_noempty out))

(* return the (modules list) dependency for a specific file *)
let runOcamldep dopt srcFile =
  let wrap_module_safe f =
    try Modname.wrap f
    with _ -> 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.getOcamlDep ()]
             @ (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 runCCdep srcDir files : (filename * filepath list) list =
  let args = [Prog.getCC (); "-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)