Allow .mli only modules

Closes #9
This commit is contained in:
Jeremie Dimino 2017-02-28 11:11:12 +00:00
parent 98c083db21
commit 951132023c
1 changed files with 70 additions and 55 deletions

View File

@ -301,14 +301,17 @@ module Gen(P : Params) = struct
end end
let all_rules = ref [] let all_rules = ref []
let known_targets_by_dir_so_far = ref Path.Map.empty let known_targets_by_src_dir_so_far = ref Path.Map.empty
let add_rule build = let add_rule build =
let rule = Build_interpret.Rule.make build in let rule = Build_interpret.Rule.make build in
all_rules := rule :: !all_rules; all_rules := rule :: !all_rules;
known_targets_by_dir_so_far := known_targets_by_src_dir_so_far :=
List.fold_left rule.targets ~init:!known_targets_by_dir_so_far ~f:(fun acc target -> List.fold_left rule.targets ~init:!known_targets_by_src_dir_so_far
let path = Build_interpret.Target.path target in ~f:(fun acc target ->
match Path.extract_build_context (Build_interpret.Target.path target) with
| None -> acc
| Some (_, path) ->
let dir = Path.parent path in let dir = Path.parent path in
let fn = Path.basename path in let fn = Path.basename path in
let files = let files =
@ -324,7 +327,7 @@ module Gen(P : Params) = struct
| None -> String_set.empty | None -> String_set.empty
| Some dir -> File_tree.Dir.files dir | Some dir -> File_tree.Dir.files dir
in in
match Path.Map.find src_path !known_targets_by_dir_so_far with match Path.Map.find src_path !known_targets_by_src_dir_so_far with
| None -> sources | None -> sources
| Some set -> String_set.union sources set | Some set -> String_set.union sources set
@ -1454,11 +1457,25 @@ module Gen(P : Params) = struct
let impls = parse_one_set ml_files in let impls = parse_one_set ml_files in
let intfs = parse_one_set mli_files in let intfs = parse_one_set mli_files in
String_map.merge impls intfs ~f:(fun name ml_fname mli_fname -> String_map.merge impls intfs ~f:(fun name ml_fname mli_fname ->
let ml_fname =
match ml_fname with match ml_fname with
| None -> | None ->
die "module %s in %s doesn't have a corresponding .ml file" let mli_fname = Option.value_exn mli_fname in
let ml_fname = String.sub mli_fname ~pos:0 ~len:(String.length mli_fname - 1) in
Format.eprintf
"@{<warning>Warning@}: module %s in %s doesn't have a corresponding\
.ml file.\n\
I'm setting up a rule for copying %s to %s.\n"
name (Path.to_string dir) name (Path.to_string dir)
| Some ml_fname -> mli_fname ml_fname;
let dir = Path.append ctx.build_dir dir in
add_rule
(Build.copy
~src:(Path.relative dir mli_fname)
~dst:(Path.relative dir ml_fname));
ml_fname
| Some ml_fname -> ml_fname
in
Some Some
{ Module. { Module.
name name
@ -1472,44 +1489,42 @@ module Gen(P : Params) = struct
+-----------------------------------------------------------------+ *) +-----------------------------------------------------------------+ *)
let rules { src_dir; ctx_dir; stanzas } = let rules { src_dir; ctx_dir; stanzas } =
let files = lazy ( (* Interpret user rules and other simple stanzas first in order to populate the known
let src_files = target table, which is needed for guessing the list of modules. *)
match File_tree.find_dir P.file_tree src_dir with List.iter stanzas ~f:(fun stanza ->
| None -> String_set.empty let dir = ctx_dir in
| Some dir -> File_tree.Dir.files dir match (stanza : Stanza.t) with
in | Rule rule -> user_rule rule ~dir
let files_produced_by_rules = | Ocamllex conf -> ocamllex_rules conf ~dir
List.concat_map stanzas ~f:(fun stanza -> | Ocamlyacc conf -> ocamlyacc_rules conf ~dir
| Alias alias -> alias_rules alias ~dir
| Library _ | Executables _ | Provides _ | Install _ -> ());
let files = lazy (
let files = sources_and_targets_known_so_far ~src_path:src_dir in
(* Manually add files generated by the (select ...) dependencies since we haven't
interpreted libraries and executables yet. *)
List.fold_left stanzas ~init:files ~f:(fun acc stanza ->
match (stanza : Stanza.t) with match (stanza : Stanza.t) with
| Rule rule -> rule.targets
| Ocamllex conf -> List.map conf.names ~f:(fun name -> name ^ ".ml")
| Ocamlyacc conf -> List.concat_map conf.names ~f:(fun name ->
[ name ^ ".ml"; name ^ ".mli" ])
| Library { buildable; _ } | Executables { buildable; _ } -> | Library { buildable; _ } | Executables { buildable; _ } ->
List.filter_map buildable.libraries ~f:(function List.fold_left buildable.libraries ~init:acc ~f:(fun acc dep ->
| Direct _ -> None match (dep : Jbuild_types.Lib_dep.t) with
| Select s -> Some s.result_fn) | Direct _ -> acc
| _ -> []) | Select s -> String_set.add s.result_fn acc)
|> String_set.of_list | _ -> acc)
in ) in
String_set.union src_files files_produced_by_rules)
in
let all_modules = lazy ( let all_modules = lazy (
guess_modules ~dir:src_dir guess_modules ~dir:src_dir
~files:(Lazy.force files)) ~files:(Lazy.force files))
in in
let some x = Some x in
let none () = None in
List.filter_map stanzas ~f:(fun stanza -> List.filter_map stanzas ~f:(fun stanza ->
let dir = ctx_dir in let dir = ctx_dir in
match (stanza : Stanza.t) with match (stanza : Stanza.t) with
| Library lib -> library_rules lib ~dir ~all_modules:(Lazy.force all_modules) ~files:(Lazy.force files) |> some | Library lib ->
| Executables exes -> executables_rules exes ~dir ~all_modules:(Lazy.force all_modules) |> some Some (library_rules lib ~dir
| Rule rule -> user_rule rule ~dir |> none ~all_modules:(Lazy.force all_modules) ~files:(Lazy.force files))
| Ocamllex conf -> ocamllex_rules conf ~dir |> none | Executables exes ->
| Ocamlyacc conf -> ocamlyacc_rules conf ~dir |> none Some (executables_rules exes ~dir ~all_modules:(Lazy.force all_modules))
| Alias alias -> alias_rules alias ~dir |> none | _ -> None)
| Provides _ | Install _ -> () |> none)
|> merge_dot_merlin ~dir:ctx_dir |> merge_dot_merlin ~dir:ctx_dir
let () = List.iter P.stanzas ~f:rules let () = List.iter P.stanzas ~f:rules