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,22 +301,25 @@ 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 ->
let dir = Path.parent path in match Path.extract_build_context (Build_interpret.Target.path target) with
let fn = Path.basename path in | None -> acc
let files = | Some (_, path) ->
match Path.Map.find dir acc with let dir = Path.parent path in
| None -> String_set.singleton fn let fn = Path.basename path in
| Some set -> String_set.add fn set let files =
in match Path.Map.find dir acc with
Path.Map.add acc ~key:dir ~data:files) | None -> String_set.singleton fn
| Some set -> String_set.add fn set
in
Path.Map.add acc ~key:dir ~data:files)
let sources_and_targets_known_so_far ~src_path = let sources_and_targets_known_so_far ~src_path =
let sources = let sources =
@ -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,62 +1457,74 @@ 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 ->
match ml_fname with let ml_fname =
| None -> match ml_fname with
die "module %s in %s doesn't have a corresponding .ml file" | None ->
name (Path.to_string dir) let mli_fname = Option.value_exn mli_fname in
| Some ml_fname -> let ml_fname = String.sub mli_fname ~pos:0 ~len:(String.length mli_fname - 1) in
Some Format.eprintf
{ Module. "@{<warning>Warning@}: module %s in %s doesn't have a corresponding\
name .ml file.\n\
; ml_fname = ml_fname I'm setting up a rule for copying %s to %s.\n"
; mli_fname = mli_fname name (Path.to_string dir)
; obj_name = "" 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
{ Module.
name
; ml_fname = ml_fname
; mli_fname = mli_fname
; obj_name = ""
})
(* +-----------------------------------------------------------------+ (* +-----------------------------------------------------------------+
| Stanza | | Stanza |
+-----------------------------------------------------------------+ *) +-----------------------------------------------------------------+ *)
let rules { src_dir; ctx_dir; stanzas } = let rules { src_dir; ctx_dir; stanzas } =
(* Interpret user rules and other simple stanzas first in order to populate the known
target table, which is needed for guessing the list of modules. *)
List.iter stanzas ~f:(fun stanza ->
let dir = ctx_dir in
match (stanza : Stanza.t) with
| Rule rule -> user_rule rule ~dir
| Ocamllex conf -> ocamllex_rules conf ~dir
| Ocamlyacc conf -> ocamlyacc_rules conf ~dir
| Alias alias -> alias_rules alias ~dir
| Library _ | Executables _ | Provides _ | Install _ -> ());
let files = lazy ( let files = lazy (
let src_files = let files = sources_and_targets_known_so_far ~src_path:src_dir in
match File_tree.find_dir P.file_tree src_dir with (* Manually add files generated by the (select ...) dependencies since we haven't
| None -> String_set.empty interpreted libraries and executables yet. *)
| Some dir -> File_tree.Dir.files dir List.fold_left stanzas ~init:files ~f:(fun acc stanza ->
in match (stanza : Stanza.t) with
let files_produced_by_rules = | Library { buildable; _ } | Executables { buildable; _ } ->
List.concat_map stanzas ~f:(fun stanza -> List.fold_left buildable.libraries ~init:acc ~f:(fun acc dep ->
match (stanza : Stanza.t) with match (dep : Jbuild_types.Lib_dep.t) with
| Rule rule -> rule.targets | Direct _ -> acc
| Ocamllex conf -> List.map conf.names ~f:(fun name -> name ^ ".ml") | Select s -> String_set.add s.result_fn acc)
| Ocamlyacc conf -> List.concat_map conf.names ~f:(fun name -> | _ -> acc)
[ name ^ ".ml"; name ^ ".mli" ]) ) in
| Library { buildable; _ } | Executables { buildable; _ } ->
List.filter_map buildable.libraries ~f:(function
| Direct _ -> None
| Select s -> Some s.result_fn)
| _ -> [])
|> String_set.of_list
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