Skip to content

Commit 3f69941

Browse files
committed
Driver: Compile assets, following convention
1 parent 5741d4b commit 3f69941

File tree

11 files changed

+256
-123
lines changed

11 files changed

+256
-123
lines changed

src/driver/compile.ml

Lines changed: 93 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
type compiled = Odoc_unit.t
44

5-
let mk_byhash (pkgs : Odoc_unit.intf Odoc_unit.unit list) =
5+
let mk_byhash (pkgs : Odoc_unit.t list) =
66
List.fold_left
7-
(fun acc (u : Odoc_unit.intf Odoc_unit.unit) ->
7+
(fun acc (u : Odoc_unit.t) ->
88
match u.Odoc_unit.kind with
9-
| `Intf { hash; _ } -> Util.StringMap.add hash u acc)
9+
| `Intf { hash; _ } as kind -> Util.StringMap.add hash { u with kind } acc
10+
| _ -> acc)
1011
Util.StringMap.empty pkgs
1112

1213
let init_stats (units : Odoc_unit.t list) =
@@ -78,93 +79,98 @@ let find_partials odoc_dir : Odoc_unit.intf Odoc_unit.unit Util.StringMap.t * _
7879
| Error _ -> (* odoc_dir doesn't exist...? *) (Util.StringMap.empty, tbl)
7980

8081
let compile ?partial ~partial_dir ?linked_dir:_ (all : Odoc_unit.t list) =
81-
(* let linked_dir = Option.value linked_dir ~default:output_dir in *)
82-
let intf_units, impl_units, mld_units =
83-
List.fold_left
84-
(fun (intf_units, impl_units, page_units) (unit : Odoc_unit.t) ->
85-
match unit with
86-
| { kind = `Intf _; _ } as intf ->
87-
(intf :: intf_units, impl_units, page_units)
88-
| { kind = `Impl _; _ } as impl ->
89-
(intf_units, impl :: impl_units, page_units)
90-
| { kind = `Mld; _ } as mld ->
91-
(intf_units, impl_units, mld :: page_units))
92-
([], [], []) all
93-
in
94-
let hashes = mk_byhash intf_units in
95-
let other_hashes, tbl =
96-
match partial with
97-
| Some _ -> find_partials partial_dir
98-
| None -> (Util.StringMap.empty, Hashtbl.create 10)
99-
in
100-
let all_hashes =
101-
Util.StringMap.union (fun _x o1 _o2 -> Some o1) hashes other_hashes
82+
let hashes = mk_byhash all in
83+
let compile_mod =
84+
(* Modules have a more complicated compilation because:
85+
- They have dependencies and must be compiled in the right order
86+
- In Voodoo mode, there might exists already compiled parts *)
87+
let other_hashes, tbl =
88+
match partial with
89+
| Some _ -> find_partials partial_dir
90+
| None -> (Util.StringMap.empty, Hashtbl.create 10)
91+
in
92+
let all_hashes =
93+
Util.StringMap.union (fun _x o1 _o2 -> Some o1) hashes other_hashes
94+
in
95+
let compile_one compile_other hash =
96+
match Util.StringMap.find_opt hash all_hashes with
97+
| None ->
98+
Logs.debug (fun m -> m "Error locating hash: %s" hash);
99+
Error Not_found
100+
| Some unit ->
101+
let deps = match unit.kind with `Intf { deps; _ } -> deps in
102+
let _fibers =
103+
Fiber.List.map
104+
(fun (other_unit : Odoc_unit.intf Odoc_unit.unit) ->
105+
match compile_other other_unit with
106+
| Ok r -> Some r
107+
| Error _exn ->
108+
Logs.debug (fun m ->
109+
m
110+
"Error during compilation of module %s (hash %s, \
111+
required by %s)"
112+
(Fpath.filename other_unit.input_file)
113+
(match other_unit.kind with
114+
| `Intf { hash; _ } -> hash)
115+
(Fpath.filename unit.input_file));
116+
None)
117+
deps
118+
in
119+
let includes = Fpath.Set.of_list unit.include_dirs in
120+
Odoc.compile ~output_dir:unit.output_dir ~input_file:unit.input_file
121+
~includes ~parent_id:unit.parent_id;
122+
Atomic.incr Stats.stats.compiled_units;
123+
124+
Ok unit
125+
in
126+
let rec compile_mod :
127+
Odoc_unit.intf Odoc_unit.unit ->
128+
(Odoc_unit.intf Odoc_unit.unit, exn) Result.t =
129+
fun unit ->
130+
let hash = match unit.kind with `Intf { hash; _ } -> hash in
131+
match Hashtbl.find_opt tbl hash with
132+
| Some p -> Promise.await p
133+
| None ->
134+
let p, r = Promise.create () in
135+
Hashtbl.add tbl hash p;
136+
let result = compile_one compile_mod hash in
137+
Promise.resolve r result;
138+
result
139+
in
140+
compile_mod
102141
in
103-
let compile_one compile_other hash =
104-
match Util.StringMap.find_opt hash all_hashes with
105-
| None ->
106-
Logs.debug (fun m -> m "Error locating hash: %s" hash);
107-
Error Not_found
108-
| Some unit ->
109-
let deps = match unit.kind with `Intf { deps; _ } -> deps in
110-
let _fibers =
111-
Fiber.List.map
112-
(fun other_unit ->
113-
match compile_other other_unit with
114-
| Ok r -> Some r
115-
| Error _exn ->
116-
Logs.debug (fun m ->
117-
m "Missing module %s (hash %s, required by %s)" "TODO"
118-
(* n h *) "TODO" "TODO" (* unit.m_name *));
119-
None)
120-
deps
121-
in
142+
143+
let compile (unit : Odoc_unit.t) =
144+
match unit.kind with
145+
| `Intf _ as kind ->
146+
(compile_mod { unit with kind } :> (Odoc_unit.t, _) Result.t)
147+
| `Impl src ->
148+
let includes = Fpath.Set.of_list unit.include_dirs in
149+
let source_id = src.src_id in
150+
Odoc.compile_impl ~output_dir:unit.output_dir
151+
~input_file:unit.input_file ~includes ~parent_id:unit.parent_id
152+
~source_id;
153+
Atomic.incr Stats.stats.compiled_impls;
154+
Ok unit
155+
| `Asset ->
156+
Odoc.compile_asset ~output_dir:unit.output_dir ~parent_id:unit.parent_id
157+
~name:(Fpath.filename unit.input_file);
158+
Ok unit
159+
| `Mld ->
122160
let includes = Fpath.Set.of_list unit.include_dirs in
123161
Odoc.compile ~output_dir:unit.output_dir ~input_file:unit.input_file
124162
~includes ~parent_id:unit.parent_id;
125-
Atomic.incr Stats.stats.compiled_units;
126-
163+
Atomic.incr Stats.stats.compiled_mlds;
127164
Ok unit
128165
in
129-
130-
let rec compile_mod :
131-
Odoc_unit.intf Odoc_unit.unit ->
132-
(Odoc_unit.intf Odoc_unit.unit, exn) Result.t =
133-
fun unit ->
134-
let hash = match unit.kind with `Intf { hash; _ } -> hash in
135-
match Hashtbl.find_opt tbl hash with
136-
| Some p -> Promise.await p
137-
| None ->
138-
let p, r = Promise.create () in
139-
Hashtbl.add tbl hash p;
140-
let result = compile_one compile_mod hash in
141-
Promise.resolve r result;
142-
result
143-
in
144-
let to_build = Util.StringMap.bindings hashes |> List.map snd in
145-
let mod_results = Fiber.List.map compile_mod to_build in
146-
let compile_mld (unit : Odoc_unit.mld Odoc_unit.unit) =
147-
let includes = Fpath.Set.of_list unit.include_dirs in
148-
Odoc.compile ~output_dir:unit.output_dir ~input_file:unit.input_file
149-
~includes ~parent_id:unit.parent_id;
150-
Atomic.incr Stats.stats.compiled_mlds
151-
in
152-
let () = Fiber.List.iter compile_mld mld_units in
153-
let compile_impl (unit : Odoc_unit.impl Odoc_unit.unit) =
154-
let includes = Fpath.Set.of_list unit.include_dirs in
155-
let source_id = match unit.kind with `Impl src -> src.src_id in
156-
Odoc.compile_impl ~output_dir:unit.output_dir ~input_file:unit.input_file
157-
~includes ~parent_id:unit.parent_id ~source_id;
158-
Atomic.incr Stats.stats.compiled_impls
159-
in
160-
let () = Fiber.List.iter compile_impl impl_units in
161-
let zipped_res =
162-
List.map2
163-
(fun Odoc_unit.{ kind = `Intf { hash; _ }; _ } b -> (hash, b))
164-
to_build mod_results
165-
in
166+
let res = Fiber.List.map compile all in
167+
(* For voodoo mode, we need to keep which modules successfully compiled *)
166168
let zipped =
167-
List.filter_map (function a, Ok b -> Some (a, b) | _ -> None) zipped_res
169+
List.filter_map
170+
(function
171+
| Ok (Odoc_unit.{ kind = `Intf { hash; _ }; _ } as b) -> Some (hash, b)
172+
| _ -> None)
173+
res
168174
in
169175
(match partial with
170176
| Some l -> marshal (zipped, hashes) Fpath.(l / "index.m")
@@ -193,6 +199,7 @@ let link : compiled list -> _ =
193199
(match c.kind with
194200
| `Intf _ -> Atomic.incr Stats.stats.linked_units
195201
| `Mld -> Atomic.incr Stats.stats.linked_mlds
202+
| `Asset -> () (* TODO *)
196203
| `Impl _ -> Atomic.incr Stats.stats.linked_impls);
197204
c
198205
in
@@ -239,6 +246,9 @@ let html_generate output_dir linked =
239246
Odoc.html_generate ~search_uris:[] ~output_dir ~input_file
240247
~source:src_path ();
241248
Atomic.incr Stats.stats.generated_units
249+
| `Asset ->
250+
Odoc.html_generate_asset ~output_dir ~input_file:l.odoc_file
251+
~asset_path:l.input_file ()
242252
| _ ->
243253
let db_path = compile_index l.index in
244254
let search_uris = [ db_path; Sherlodoc.js_file ] in

src/driver/dune_style.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ let of_dune_build dir =
5353
version = "1.0";
5454
libraries = [ lib ];
5555
mlds = [];
56+
assets = [] (* TODO *);
5657
pkg_dir;
5758
other_docs = Fpath.Set.empty;
5859
} )

src/driver/odoc.ml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ let compile ~output_dir ~input_file:file ~includes ~parent_id =
4545
Cmd_outputs.(
4646
add_prefixed_output cmd compile_output (Fpath.to_string file) lines)
4747

48+
let compile_asset ~output_dir ~name ~parent_id =
49+
let open Cmd in
50+
let output_file =
51+
Some Fpath.(output_dir // parent_id / ("asset-" ^ name ^ ".odoc"))
52+
in
53+
let cmd =
54+
!odoc % "compile-asset" % "--name" % name % "--output-dir" % p output_dir
55+
in
56+
57+
let cmd = cmd % "--parent-id" % Fpath.to_string parent_id in
58+
let desc = Printf.sprintf "Compiling %s" name in
59+
let lines = Cmd_outputs.submit desc cmd output_file in
60+
Cmd_outputs.(add_prefixed_output cmd compile_output name lines)
61+
4862
let compile_impl ~output_dir ~input_file:file ~includes ~parent_id ~source_id =
4963
let open Cmd in
5064
let includes =
@@ -156,6 +170,19 @@ let html_generate ~output_dir ?index ?(ignore_output = false) ?(assets = [])
156170
Cmd_outputs.(
157171
add_prefixed_output cmd generate_output (Fpath.to_string file) lines)
158172

173+
let html_generate_asset ~output_dir ?(ignore_output = false) ~input_file:file
174+
~asset_path () =
175+
let open Cmd in
176+
let cmd =
177+
!odoc % "html-generate" % p file % "-o" % output_dir % "--asset-path"
178+
% p asset_path
179+
in
180+
let desc = Printf.sprintf "Copying asset %s" (Fpath.to_string file) in
181+
let lines = Cmd_outputs.submit desc cmd None in
182+
if not ignore_output then
183+
Cmd_outputs.(
184+
add_prefixed_output cmd generate_output (Fpath.to_string file) lines)
185+
159186
let support_files path =
160187
let open Cmd in
161188
let cmd = !odoc % "support-files" % "-o" % Fpath.to_string path in

src/driver/odoc.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ val compile :
2424
parent_id:id ->
2525
unit
2626

27+
val compile_asset : output_dir:Fpath.t -> name:string -> parent_id:id -> unit
28+
2729
val link :
2830
?ignore_output:bool ->
2931
input_file:Fpath.t ->
@@ -54,6 +56,15 @@ val html_generate :
5456
input_file:Fpath.t ->
5557
unit ->
5658
unit
59+
60+
val html_generate_asset :
61+
output_dir:string ->
62+
?ignore_output:bool ->
63+
input_file:Fpath.t ->
64+
asset_path:Fpath.t ->
65+
unit ->
66+
unit
67+
5768
val support_files : Fpath.t -> string list
5869

5970
val count_occurrences : Fpath.t -> string list

src/driver/odoc_unit.ml

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ type impl = [ `Impl of impl_extra ]
3232

3333
type mld = [ `Mld ]
3434

35-
type t = [ impl | intf | mld ] unit
35+
type asset = [ `Asset ]
36+
37+
type t = [ impl | intf | mld | asset ] unit
3638

3739
let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
3840
t list =
@@ -90,14 +92,13 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
9092
let output_file = Fpath.(index_dir / pkg.name / Odoc.index_filename) in
9193
{ pkg_args; output_file; json = false; search_dir = pkg.pkg_dir }
9294
in
93-
let make_unit ~kind ~rel_dir ~input_file ~prefix ~pkg ~include_dirs : _ unit =
95+
let make_unit ~name ~kind ~rel_dir ~input_file ~pkg ~include_dirs : _ unit =
9496
let ( // ) = Fpath.( // ) in
9597
let ( / ) = Fpath.( / ) in
96-
let filename = input_file |> Fpath.rem_ext |> Fpath.basename in
9798
let odoc_dir = output_dir // rel_dir in
9899
let parent_id = rel_dir |> Odoc.id_of_fpath in
99-
let odoc_file = odoc_dir / (prefix ^ filename ^ ".odoc") in
100-
let odocl_file = linked_dir // rel_dir / (prefix ^ filename ^ ".odocl") in
100+
let odoc_file = odoc_dir / (name ^ ".odoc") in
101+
let odocl_file = linked_dir // rel_dir / (name ^ ".odocl") in
101102
{
102103
output_dir;
103104
pkgname = pkg.Packages.name;
@@ -134,7 +135,8 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
134135
let kind = `Intf { hidden; hash = intf.mif_hash; deps } in
135136
(include_dirs, kind)
136137
in
137-
make_unit ~kind ~rel_dir ~prefix:"" ~input_file:intf.mif_path ~pkg
138+
let name = intf.mif_path |> Fpath.rem_ext |> Fpath.basename in
139+
make_unit ~name ~kind ~rel_dir ~input_file:intf.mif_path ~pkg
138140
~include_dirs
139141
in
140142
let of_impl pkg libname (impl : Packages.impl) : impl unit option =
@@ -154,9 +156,12 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
154156
in
155157
`Impl { src_id; src_path }
156158
in
159+
let name =
160+
impl.mip_path |> Fpath.rem_ext |> Fpath.basename |> ( ^ ) "impl-"
161+
in
157162
let unit =
158-
make_unit ~kind ~rel_dir ~input_file:impl.mip_path ~pkg ~include_dirs
159-
~prefix:"impl-"
163+
make_unit ~name ~kind ~rel_dir ~input_file:impl.mip_path ~pkg
164+
~include_dirs
160165
in
161166
Some unit
162167
in
@@ -187,15 +192,31 @@ let of_packages ~output_dir ~linked_dir ~index_dir (pkgs : Packages.t list) :
187192
in
188193
let include_dirs = (output_dir // rel_dir) :: include_dirs in
189194
let kind = `Mld in
195+
let name = mld_path |> Fpath.rem_ext |> Fpath.basename |> ( ^ ) "page-" in
196+
let unit =
197+
make_unit ~name ~kind ~rel_dir ~input_file:mld_path ~pkg ~include_dirs
198+
in
199+
[ unit ]
200+
in
201+
let of_asset pkg (asset : Packages.asset) : asset unit list =
202+
let open Fpath in
203+
let { Packages.asset_path; asset_rel_path } = asset in
204+
let rel_dir =
205+
pkg.Packages.pkg_dir / "doc" // Fpath.parent asset_rel_path
206+
|> Fpath.normalize
207+
in
208+
let include_dirs = [] in
209+
let kind = `Asset in
190210
let unit =
191-
make_unit ~kind ~rel_dir ~input_file:mld_path ~pkg ~include_dirs
192-
~prefix:"page-"
211+
let name = asset_path |> Fpath.basename |> ( ^ ) "asset-" in
212+
make_unit ~name ~kind ~rel_dir ~input_file:asset_path ~pkg ~include_dirs
193213
in
194214
[ unit ]
195215
in
196216
let of_package (pkg : Packages.t) : t list =
197217
let lib_units :> t list list = List.map (of_lib pkg) pkg.libraries in
198218
let mld_units :> t list list = List.map (of_mld pkg) pkg.mlds in
199-
List.concat (List.rev_append lib_units mld_units)
219+
let asset_units :> t list list = List.map (of_asset pkg) pkg.assets in
220+
List.concat (lib_units @ mld_units @ asset_units)
200221
in
201222
List.concat_map of_package pkgs

src/driver/odoc_unit.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ type impl = [ `Impl of impl_extra ]
3232

3333
type mld = [ `Mld ]
3434

35-
type t = [ impl | intf | mld ] unit
35+
type asset = [ `Asset ]
36+
37+
type t = [ impl | intf | mld | asset ] unit
3638

3739
val of_packages :
3840
output_dir:Fpath.t ->

src/driver/opam.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ let pkg_to_dir_map () =
135135
| "doc" :: _pkg :: "odoc-pages" :: _ ->
136136
Logs.debug (fun m -> m "Found odoc page: %a" Fpath.pp fpath);
137137

138+
(Fpath.Set.add Fpath.(v prefix // fpath) odoc_pages, others)
139+
| "doc" :: _pkg :: "odoc-assets" :: _ ->
140+
Logs.debug (fun m -> m "Found odoc page: %a" Fpath.pp fpath);
141+
138142
(Fpath.Set.add Fpath.(v prefix // fpath) odoc_pages, others)
139143
| "doc" :: _ ->
140144
Logs.debug (fun m -> m "Found other doc: %a" Fpath.pp fpath);

0 commit comments

Comments
 (0)