1 (***********************************************************************)
4 (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *)
6 (* Copyright 2007 Institut National de Recherche en Informatique et *)
7 (* en Automatique. All rights reserved. This file is distributed *)
8 (* under the terms of the Q Public License version 1.0. *)
10 (***********************************************************************)
12 (* $Id: ocaml_utils.ml,v 1.3.2.3 2007-11-21 18:29:37 ertai Exp $ *)
13 (* Original author: Nicolas Pouillard *)
17 open Pathname.Operators
24 module S
= Set.Make
(String
)
26 let stdlib_dir = lazy begin
28 let ocamlc_where = sprintf
"%s/ocamlc.where" (Pathname.pwd
/ !Options.build_dir
) in
29 let () = Command.execute ~quiet
:true (Cmd
(S
[!Options.ocamlc
; A
"-where"; Sh
">"; P
ocamlc_where])) in
30 String.chomp
(read_file
ocamlc_where)
33 let module_name_of_filename f
= String.capitalize
(Pathname.remove_extensions f
)
34 let module_name_of_pathname x
=
35 module_name_of_filename (Pathname.to_string
(Pathname.basename x
))
38 if !Options.nostdlib
then false
40 let x'
= !*stdlib_dir/((String.uncapitalize
x)-.-"cmi") in
43 let non_dependencies = ref []
44 let non_dependency m1 m2
=
45 (* non_dependency was not supposed to accept pathnames without extension. *)
46 if String.length
(Pathname.get_extensions m1
) = 0 then
47 invalid_arg
"non_dependency: no extension";
48 non_dependencies := (m1
, m2
) :: !non_dependencies
50 let path_importance path
x =
51 if List.mem
(path
, x) !non_dependencies
52 || (List.mem
x !Options.ignore_list
) then begin
53 let () = dprintf
3 "This module (%s) is ignored by %s" x path
in
56 else if ignore_stdlib x then `just_try
else `mandatory
58 let expand_module include_dirs module_name exts
=
59 let dirname = Pathname.dirname module_name
in
60 let basename = Pathname.basename module_name
in
61 let module_name_cap = dirname/(String.capitalize
basename) in
62 let module_name_uncap = dirname/(String.uncapitalize
basename) in
63 List.fold_right
begin fun include_dir
->
64 List.fold_right
begin fun ext acc
->
65 include_dir
/(module_name_uncap-.-ext
) ::
66 include_dir
/(module_name_cap-.-ext
) :: acc
70 let string_list_of_file file
=
71 with_input_file file
begin fun ic
->
72 Lexers.blank_sep_strings
(Lexing.from_channel ic
)
74 let print_path_list = Pathname.print_path_list
76 let ocaml_ppflags tags
=
77 let flags = Flags.of_tags
(tags
++"ocaml"++"pp") in
78 let reduced = Command.reduce
flags in
79 if reduced = N
then N
else S
[A
"-pp"; Quote
reduced]
81 let ocaml_add_include_flag x acc
=
82 if x = Pathname.current_dir_name
then acc
else A
"-I" :: A
x :: acc
84 let ocaml_include_flags path
=
85 S
(List.fold_right
ocaml_add_include_flag (Pathname.include_dirs_of
(Pathname.dirname path
)) [])
87 let info_libraries = Hashtbl.create
103
89 let libraries = Hashtbl.create
103
91 try Hashtbl.find
libraries m
with Not_found
-> []
92 let use_lib m lib
= Hashtbl.replace
libraries m
(lib
:: libraries_of m
)
94 let ocaml_lib ?
(extern
=false) ?
(byte
=true) ?
(native
=true) ?dir ?tag_name libpath
=
97 | Some dir
-> S
[A
"-I"; P dir
; x]
103 | None
-> "use_" ^
Pathname.basename libpath
105 Hashtbl.replace
info_libraries tag_name (libpath
, extern
);
108 flag
["ocaml"; tag_name; "link"; "byte"] (add_dir (A
(libpath^
".cma")));
110 flag
["ocaml"; tag_name; "link"; "native"] (add_dir (A
(libpath^
".cmxa")));
112 if not byte
&& not native
then
113 invalid_arg
"ocaml_lib: ~byte:false or ~native:false only works with ~extern:true";
117 | Some dir
-> flag
["ocaml"; tag_name; "compile"] (S
[A
"-I"; P dir
])
119 let cmi_of = Pathname.update_extensions
"cmi"
121 exception Ocamldep_error
of string
123 let read_path_dependencies =
124 let path_dependencies = Hashtbl.create
103 in
126 let module_name = module_name_of_pathname path
in
127 let depends = path
-.-"depends" in
128 with_input_file
depends begin fun ic
->
129 let ocamldep_output =
130 try Lexers.ocamldep_output (Lexing.from_channel ic
)
131 with Lexers.Error msg
-> raise
(Ocamldep_error
(Printf.sprintf
"Ocamldep.ocamldep: bad output (%s)" msg
)) in
133 List.fold_right
begin fun (path
, deps) acc
->
134 let module_name'
= module_name_of_pathname path
in
135 if module_name'
= module_name
136 then List.union
deps acc
137 else raise
(Ocamldep_error
(Printf.sprintf
"Ocamldep.ocamldep: multiple files in ocamldep output (%s not expected)" path
))
138 end ocamldep_output [] in
140 if !Options.nostdlib
&& not
(Tags.mem
"nopervasives" (tags_of_pathname path
)) then
143 let deps'
= List.fold_right
begin fun dep acc
->
144 match path_importance path dep
with
146 | (`just_try
| `mandatory
) as importance
-> (importance
, dep
) :: acc
148 Hashtbl.replace
path_dependencies path
149 (List.union
(try Hashtbl.find
path_dependencies path
with Not_found
-> []) deps'
);
154 let path_dependencies_of = memo
read_path_dependencies