Make odoc work with multiple libraries defined in the same dir
This commit is contained in:
parent
815c332dc5
commit
6cce747141
|
@ -48,7 +48,7 @@ let cmt_file t ~dir (kind : Ml_kind.t) =
|
||||||
| Impl -> Some (Path.relative dir (t.obj_name ^ ".cmt"))
|
| Impl -> Some (Path.relative dir (t.obj_name ^ ".cmt"))
|
||||||
| Intf -> Option.map t.intf ~f:(fun _ -> Path.relative dir (t.obj_name ^ ".cmti"))
|
| Intf -> Option.map t.intf ~f:(fun _ -> Path.relative dir (t.obj_name ^ ".cmti"))
|
||||||
|
|
||||||
let odoc_file t ~dir = Path.relative dir (t.obj_name ^ ".odoc")
|
let odoc_file t ~doc_dir = Path.relative doc_dir (t.obj_name ^ ".odoc")
|
||||||
|
|
||||||
let cmti_file t ~dir =
|
let cmti_file t ~dir =
|
||||||
match t.intf with
|
match t.intf with
|
||||||
|
|
|
@ -31,7 +31,7 @@ val cm_source : t -> dir:Path.t -> Cm_kind.t -> Path.t option
|
||||||
val cm_file : t -> dir:Path.t -> Cm_kind.t -> Path.t
|
val cm_file : t -> dir:Path.t -> Cm_kind.t -> Path.t
|
||||||
val cmt_file : t -> dir:Path.t -> Ml_kind.t -> Path.t option
|
val cmt_file : t -> dir:Path.t -> Ml_kind.t -> Path.t option
|
||||||
|
|
||||||
val odoc_file : t -> dir:Path.t -> Path.t
|
val odoc_file : t -> doc_dir:Path.t -> Path.t
|
||||||
|
|
||||||
(** Either the .cmti, or .cmt if the module has no interface *)
|
(** Either the .cmti, or .cmt if the module has no interface *)
|
||||||
val cmti_file : t -> dir:Path.t -> Path.t
|
val cmti_file : t -> dir:Path.t -> Path.t
|
||||||
|
|
126
src/odoc.ml
126
src/odoc.ml
|
@ -9,18 +9,27 @@ let ( ++ ) = Path.relative
|
||||||
let get_odoc sctx = SC.resolve_program sctx "odoc" ~hint:"opam install odoc"
|
let get_odoc sctx = SC.resolve_program sctx "odoc" ~hint:"opam install odoc"
|
||||||
let odoc_ext = ".odoc"
|
let odoc_ext = ".odoc"
|
||||||
|
|
||||||
module Mld = struct
|
module Mld : sig
|
||||||
type t = {
|
type t
|
||||||
name : string; (** source file name without the extension. *)
|
val create : name:string -> t
|
||||||
odoc_input_name : string;
|
|
||||||
odoc_file_name : string;
|
|
||||||
}
|
|
||||||
|
|
||||||
let odoc_file ~dir {odoc_file_name; _} =
|
val odoc_file : doc_dir:Path.t -> t -> Path.t
|
||||||
Path.relative dir odoc_file_name
|
val odoc_input : doc_dir:Path.t -> t -> Path.t
|
||||||
|
|
||||||
let odoc_input ~dir {odoc_input_name; _} =
|
val html_filename : t -> string
|
||||||
Path.relative dir odoc_input_name
|
end = struct
|
||||||
|
type t = string (** source file name without the extension. *)
|
||||||
|
|
||||||
|
let create ~name = name
|
||||||
|
|
||||||
|
let odoc_file ~doc_dir t =
|
||||||
|
Path.relative doc_dir (sprintf "page-%s%s" t odoc_ext)
|
||||||
|
|
||||||
|
let odoc_input ~doc_dir t =
|
||||||
|
Path.relative doc_dir (sprintf "%s-generated.mld" t)
|
||||||
|
|
||||||
|
let html_filename t =
|
||||||
|
sprintf "%s.html" t
|
||||||
end
|
end
|
||||||
|
|
||||||
module Module_or_mld = struct
|
module Module_or_mld = struct
|
||||||
|
@ -28,16 +37,25 @@ module Module_or_mld = struct
|
||||||
| Mld of Mld.t
|
| Mld of Mld.t
|
||||||
| Module of Module.t
|
| Module of Module.t
|
||||||
|
|
||||||
let odoc_file ~dir = function
|
let odoc_file ~doc_dir = function
|
||||||
| Mld m -> Mld.odoc_file ~dir m
|
| Mld m -> Mld.odoc_file ~doc_dir m
|
||||||
| Module m -> Module.odoc_file ~dir m
|
| Module m -> Module.odoc_file ~doc_dir m
|
||||||
|
|
||||||
let odoc_input ~dir = function
|
let odoc_input ~dir ~doc_dir = function
|
||||||
| Mld m -> Mld.odoc_input ~dir m
|
| Mld m -> Mld.odoc_input ~doc_dir m
|
||||||
| Module m -> Module.cmti_file m ~dir
|
| Module m -> Module.cmti_file m ~dir
|
||||||
|
|
||||||
|
let html_dir ~doc_dir = function
|
||||||
|
| Mld _ -> doc_dir
|
||||||
|
| Module m -> doc_dir ++ String.capitalize_ascii m.obj_name
|
||||||
|
|
||||||
|
let html_file ~doc_dir t =
|
||||||
|
match t with
|
||||||
|
| Mld m -> html_dir ~doc_dir t ++ Mld.html_filename m
|
||||||
|
| Module _ -> html_dir ~doc_dir t ++ "index.html"
|
||||||
end
|
end
|
||||||
|
|
||||||
let module_or_mld_deps (m : Module_or_mld.t) ~dir ~dep_graph ~modules =
|
let module_or_mld_deps (m : Module_or_mld.t) ~dir ~doc_dir ~dep_graph ~modules =
|
||||||
Build.dyn_paths
|
Build.dyn_paths
|
||||||
(dep_graph
|
(dep_graph
|
||||||
>>^ fun graph ->
|
>>^ fun graph ->
|
||||||
|
@ -47,46 +65,42 @@ let module_or_mld_deps (m : Module_or_mld.t) ~dir ~dep_graph ~modules =
|
||||||
List.map (Utils.find_deps ~dir graph m.name)
|
List.map (Utils.find_deps ~dir graph m.name)
|
||||||
~f:(fun name ->
|
~f:(fun name ->
|
||||||
let m = Utils.find_module ~dir modules name in
|
let m = Utils.find_module ~dir modules name in
|
||||||
Module.odoc_file m ~dir))
|
Module.odoc_file m ~doc_dir))
|
||||||
|
|
||||||
let compile sctx (m : Module_or_mld.t) ~odoc ~dir ~includes ~dep_graph
|
let compile sctx (m : Module_or_mld.t) ~odoc ~dir ~includes ~dep_graph
|
||||||
~modules ~lib_unique_name =
|
~doc_dir ~modules ~lib_unique_name =
|
||||||
let context = SC.context sctx in
|
let context = SC.context sctx in
|
||||||
let odoc_file = Module_or_mld.odoc_file m ~dir in
|
let odoc_file = Module_or_mld.odoc_file m ~doc_dir in
|
||||||
SC.add_rule sctx
|
SC.add_rule sctx
|
||||||
(module_or_mld_deps m ~dir ~dep_graph ~modules
|
(module_or_mld_deps m ~doc_dir ~dir ~dep_graph ~modules
|
||||||
>>>
|
>>>
|
||||||
includes
|
includes
|
||||||
>>>
|
>>>
|
||||||
Build.run ~context ~dir odoc ~extra_targets:[odoc_file]
|
Build.run ~context ~dir:doc_dir odoc
|
||||||
[ A "compile"
|
[ A "compile"
|
||||||
; A "-I"; Path dir
|
; A "-I"; Path dir
|
||||||
; Dyn (fun x -> x)
|
; Dyn (fun x -> x)
|
||||||
; As ["--pkg"; lib_unique_name]
|
; As ["--pkg"; lib_unique_name]
|
||||||
; A "-o"; Path odoc_file
|
; A "-o"; Target odoc_file
|
||||||
; Dep (Module_or_mld.odoc_input m ~dir)
|
; Dep (Module_or_mld.odoc_input m ~dir ~doc_dir)
|
||||||
]);
|
]);
|
||||||
(m, odoc_file)
|
(m, odoc_file)
|
||||||
|
|
||||||
let to_html sctx (m : Module_or_mld.t) odoc_file ~doc_dir ~odoc ~dir ~includes
|
let to_html sctx (m : Module_or_mld.t) odoc_file ~doc_dir ~odoc ~dir ~includes
|
||||||
~lib_unique_name ~(lib : Library.t) =
|
~(lib : Library.t) =
|
||||||
let context = SC.context sctx in
|
let context = SC.context sctx in
|
||||||
let to_remove, html_dir, html_file, jbuilder_keep =
|
let html_dir = Module_or_mld.html_dir ~doc_dir m in
|
||||||
|
let html_file = Module_or_mld.html_file ~doc_dir m in
|
||||||
|
let to_remove, jbuilder_keep =
|
||||||
match m with
|
match m with
|
||||||
| Mld m ->
|
| Mld _ -> html_file, []
|
||||||
let html_dir = doc_dir ++ lib_unique_name in
|
| Module _ ->
|
||||||
let html_file = html_dir ++ (m.Mld.name ^ ".html") in
|
|
||||||
html_file, html_dir, html_file, []
|
|
||||||
| Module m ->
|
|
||||||
let html_dir = doc_dir ++ lib_unique_name ++ String.capitalize_ascii m.obj_name in
|
|
||||||
let html_file = html_dir ++ "index.html" in
|
|
||||||
let jbuilder_keep =
|
let jbuilder_keep =
|
||||||
Build.create_file (html_dir ++ Config.jbuilder_keep_fname)
|
Build.create_file (html_dir ++ Config.jbuilder_keep_fname) in
|
||||||
in
|
html_dir, [jbuilder_keep]
|
||||||
html_dir, html_dir, html_file, [jbuilder_keep]
|
|
||||||
in
|
in
|
||||||
SC.add_rule sctx
|
SC.add_rule sctx
|
||||||
(SC.Libs.static_file_deps (dir, lib) ~ext:odoc_ext
|
(SC.Doc.static_deps sctx (dir, lib)
|
||||||
>>>
|
>>>
|
||||||
includes
|
includes
|
||||||
>>>
|
>>>
|
||||||
|
@ -95,9 +109,9 @@ let to_html sctx (m : Module_or_mld.t) odoc_file ~doc_dir ~odoc ~dir ~includes
|
||||||
:: Build.mkdir html_dir
|
:: Build.mkdir html_dir
|
||||||
:: Build.run ~context ~dir odoc ~extra_targets:[html_file]
|
:: Build.run ~context ~dir odoc ~extra_targets:[html_file]
|
||||||
[ A "html"
|
[ A "html"
|
||||||
; A "-I"; Path dir
|
; A "-I"; Path doc_dir
|
||||||
; Dyn (fun x -> x)
|
; Dyn (fun x -> x)
|
||||||
; A "-o"; Path doc_dir
|
; A "-o"; Path (Path.parent doc_dir)
|
||||||
; Dep odoc_file
|
; Dep odoc_file
|
||||||
]
|
]
|
||||||
:: jbuilder_keep
|
:: jbuilder_keep
|
||||||
|
@ -109,11 +123,11 @@ let all_mld_files sctx ~(lib : Library.t) ~lib_name ~modules ~dir files =
|
||||||
let all_files =
|
let all_files =
|
||||||
if List.mem "index.mld" ~set:files then files else "index.mld" :: files
|
if List.mem "index.mld" ~set:files then files else "index.mld" :: files
|
||||||
in
|
in
|
||||||
|
let doc_dir = SC.Doc.dir sctx (dir, lib) in
|
||||||
List.map all_files ~f:(fun file ->
|
List.map all_files ~f:(fun file ->
|
||||||
let name = Filename.chop_extension file in
|
let name = Filename.chop_extension file in
|
||||||
let odoc_input_name = sprintf "%s-generated.mld" name in
|
let mld = Mld.create ~name in
|
||||||
let odoc_file_name = sprintf "page-%s%s" name odoc_ext in
|
let generated_mld = Mld.odoc_input ~doc_dir mld in
|
||||||
let generated_mld = dir ++ odoc_input_name in
|
|
||||||
let source_mld = dir ++ file in
|
let source_mld = dir ++ file in
|
||||||
SC.add_rule sctx
|
SC.add_rule sctx
|
||||||
(Build.if_file_exists source_mld
|
(Build.if_file_exists source_mld
|
||||||
|
@ -133,20 +147,18 @@ let all_mld_files sctx ~(lib : Library.t) ~lib_name ~modules ~dir files =
|
||||||
(String_map.keys modules |> String.concat ~sep:" "))))
|
(String_map.keys modules |> String.concat ~sep:" "))))
|
||||||
>>>
|
>>>
|
||||||
Build.write_file_dyn generated_mld);
|
Build.write_file_dyn generated_mld);
|
||||||
{ Mld. name; odoc_file_name; odoc_input_name }
|
mld
|
||||||
)
|
)
|
||||||
|
|
||||||
let doc_dir ~context = Path.relative context.Context.build_dir "_doc"
|
|
||||||
|
|
||||||
let css_file ~doc_dir = doc_dir ++ "odoc.css"
|
let css_file ~doc_dir = doc_dir ++ "odoc.css"
|
||||||
|
|
||||||
let toplevel_index ~doc_dir = doc_dir ++ "index.html"
|
let toplevel_index ~doc_dir = doc_dir ++ "index.html"
|
||||||
|
|
||||||
let setup_library_rules sctx (lib : Library.t) ~dir ~modules ~mld_files
|
let setup_library_rules sctx (lib : Library.t) ~dir ~modules ~mld_files
|
||||||
~requires ~(dep_graph:Ocamldep.dep_graph) =
|
~requires ~(dep_graph:Ocamldep.dep_graph) =
|
||||||
|
let doc_dir = SC.Doc.dir sctx (dir, lib) in
|
||||||
let lib_unique_name = SC.unique_library_name sctx (Internal (dir, lib)) in
|
let lib_unique_name = SC.unique_library_name sctx (Internal (dir, lib)) in
|
||||||
let lib_name = Library.best_name lib in
|
let lib_name = Library.best_name lib in
|
||||||
let context = SC.context sctx in
|
|
||||||
let dep_graph =
|
let dep_graph =
|
||||||
Build.memoize "odoc deps"
|
Build.memoize "odoc deps"
|
||||||
((* Use the dependency graph given by ocamldep. However, when a module has no
|
((* Use the dependency graph given by ocamldep. However, when a module has no
|
||||||
|
@ -163,8 +175,7 @@ let setup_library_rules sctx (lib : Library.t) ~dir ~modules ~mld_files
|
||||||
let includes =
|
let includes =
|
||||||
Build.memoize "includes"
|
Build.memoize "includes"
|
||||||
(requires
|
(requires
|
||||||
>>>
|
>>> SC.Doc.deps sctx
|
||||||
SC.Libs.file_deps sctx ~ext:odoc_ext
|
|
||||||
>>^ Lib.include_flags)
|
>>^ Lib.include_flags)
|
||||||
in
|
in
|
||||||
let mld_files =
|
let mld_files =
|
||||||
|
@ -173,17 +184,15 @@ let setup_library_rules sctx (lib : Library.t) ~dir ~modules ~mld_files
|
||||||
let mld_and_odoc_files =
|
let mld_and_odoc_files =
|
||||||
List.map mld_files ~f:(fun m ->
|
List.map mld_files ~f:(fun m ->
|
||||||
compile sctx ~odoc ~dir ~includes ~dep_graph ~modules
|
compile sctx ~odoc ~dir ~includes ~dep_graph ~modules
|
||||||
~lib_unique_name (Mld m))
|
~doc_dir ~lib_unique_name (Mld m))
|
||||||
in
|
in
|
||||||
let modules_and_odoc_files =
|
let modules_and_odoc_files =
|
||||||
List.map (String_map.values modules) ~f:(fun m ->
|
List.map (String_map.values modules) ~f:(fun m ->
|
||||||
compile sctx ~odoc ~dir ~includes ~dep_graph ~modules
|
compile sctx ~odoc ~dir ~includes ~dep_graph ~modules
|
||||||
~lib_unique_name (Module m))
|
~doc_dir ~lib_unique_name (Module m))
|
||||||
in
|
in
|
||||||
let inputs_and_odoc_files = modules_and_odoc_files @ mld_and_odoc_files in
|
let inputs_and_odoc_files = modules_and_odoc_files @ mld_and_odoc_files in
|
||||||
SC.Libs.setup_file_deps_alias sctx ~ext:odoc_ext (dir, lib)
|
SC.Doc.setup_deps sctx (dir, lib) (List.map inputs_and_odoc_files ~f:snd);
|
||||||
(List.map inputs_and_odoc_files ~f:snd);
|
|
||||||
let doc_dir = doc_dir ~context in
|
|
||||||
(*
|
(*
|
||||||
let modules_and_odoc_files =
|
let modules_and_odoc_files =
|
||||||
if lib.wrapped then
|
if lib.wrapped then
|
||||||
|
@ -195,17 +204,17 @@ let setup_library_rules sctx (lib : Library.t) ~dir ~modules ~mld_files
|
||||||
in*)
|
in*)
|
||||||
let html_files =
|
let html_files =
|
||||||
List.map inputs_and_odoc_files ~f:(fun (m, odoc_file) ->
|
List.map inputs_and_odoc_files ~f:(fun (m, odoc_file) ->
|
||||||
to_html sctx m odoc_file ~doc_dir ~odoc ~dir ~includes ~lib
|
to_html sctx m odoc_file ~doc_dir ~odoc ~dir ~includes ~lib)
|
||||||
~lib_unique_name)
|
|
||||||
in
|
in
|
||||||
|
let doc_root = SC.Doc.root sctx in
|
||||||
SC.add_alias_deps sctx (Build_system.Alias.doc ~dir)
|
SC.add_alias_deps sctx (Build_system.Alias.doc ~dir)
|
||||||
(css_file ~doc_dir
|
(css_file ~doc_dir:doc_root
|
||||||
:: toplevel_index ~doc_dir
|
:: toplevel_index ~doc_dir:doc_root
|
||||||
:: html_files)
|
:: html_files)
|
||||||
|
|
||||||
let setup_css_rule sctx =
|
let setup_css_rule sctx =
|
||||||
let context = SC.context sctx in
|
let context = SC.context sctx in
|
||||||
let doc_dir = doc_dir ~context in
|
let doc_dir = SC.Doc.root sctx in
|
||||||
SC.add_rule sctx
|
SC.add_rule sctx
|
||||||
(Build.run ~context
|
(Build.run ~context
|
||||||
~dir:context.build_dir
|
~dir:context.build_dir
|
||||||
|
@ -256,8 +265,7 @@ let setup_toplevel_index_rule sctx =
|
||||||
</html>
|
</html>
|
||||||
|} list_items
|
|} list_items
|
||||||
in
|
in
|
||||||
let context = SC.context sctx in
|
let doc_dir = SC.Doc.root sctx in
|
||||||
let doc_dir = doc_dir ~context in
|
|
||||||
SC.add_rule sctx @@ Build.write_file (toplevel_index ~doc_dir) html
|
SC.add_rule sctx @@ Build.write_file (toplevel_index ~doc_dir) html
|
||||||
|
|
||||||
let gen_rules sctx ~dir rest =
|
let gen_rules sctx ~dir rest =
|
||||||
|
|
|
@ -366,6 +366,30 @@ module Libs = struct
|
||||||
Alias.dep (lib_files_alias lib ~ext)
|
Alias.dep (lib_files_alias lib ~ext)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Doc = struct
|
||||||
|
let root t = Path.relative t.context.Context.build_dir "_doc"
|
||||||
|
|
||||||
|
let dir t lib =
|
||||||
|
let name = unique_library_name t (Lib.Internal lib) in
|
||||||
|
Path.relative (root t) name
|
||||||
|
|
||||||
|
let alias t ((_, lib) as ilib) =
|
||||||
|
let doc_dir = dir t ilib in
|
||||||
|
Alias.make (sprintf "odoc-%s%s-all" lib.name ".odoc") ~dir:doc_dir
|
||||||
|
|
||||||
|
let deps t =
|
||||||
|
Build.dyn_paths (Build.arr (
|
||||||
|
List.fold_left ~init:[] ~f:(fun acc (lib : Lib.t) ->
|
||||||
|
match lib with
|
||||||
|
| External _ -> acc
|
||||||
|
| Internal lib -> (Alias.stamp_file (alias t lib)) :: acc
|
||||||
|
)))
|
||||||
|
|
||||||
|
let static_deps t lib = Alias.dep (alias t lib)
|
||||||
|
|
||||||
|
let setup_deps t lib files = add_alias_deps t (alias t lib) files
|
||||||
|
end
|
||||||
|
|
||||||
module Deps = struct
|
module Deps = struct
|
||||||
open Build.O
|
open Build.O
|
||||||
open Dep_conf
|
open Dep_conf
|
||||||
|
|
|
@ -164,6 +164,18 @@ module Deps : sig
|
||||||
-> (unit, Path.t list) Build.t
|
-> (unit, Path.t list) Build.t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Doc : sig
|
||||||
|
val root : t -> Path.t
|
||||||
|
|
||||||
|
val dir : t -> Lib.Internal.t -> Path.t
|
||||||
|
|
||||||
|
val deps : t -> (Lib.t list, Lib.t list) Build.t
|
||||||
|
|
||||||
|
val static_deps : t -> Lib.Internal.t -> ('a, 'a) Build.t
|
||||||
|
|
||||||
|
val setup_deps : t -> Lib.Internal.t -> Path.t list -> unit
|
||||||
|
end
|
||||||
|
|
||||||
(** Interpret action written in jbuild files *)
|
(** Interpret action written in jbuild files *)
|
||||||
module Action : sig
|
module Action : sig
|
||||||
type targets =
|
type targets =
|
||||||
|
|
Loading…
Reference in New Issue