Skip to content

Commit 0343a74

Browse files
committed
Voodoo mode!
In this mode we can process the results of 'voodoo prep' and produce output that will be compatible with what ocaml.org expects.
1 parent 711193f commit 0343a74

File tree

15 files changed

+708
-205
lines changed

15 files changed

+708
-205
lines changed

src/driver/compile.ml

Lines changed: 122 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
type ty = Module of Packages.modulety | Mld of Packages.mld
44

5-
type impl = { impl : Fpath.t; src : Fpath.t }
5+
type impl = { impl_odoc : Fpath.t; impl_odocl: Fpath.t; src : Fpath.t }
66

77
type pkg_args = {
88
docs : (string * Fpath.t) list;
@@ -11,12 +11,14 @@ type pkg_args = {
1111

1212
type compiled = {
1313
m : ty;
14-
output_dir : Fpath.t;
15-
output_file : Fpath.t;
14+
odoc_output_dir : Fpath.t; (* e.g. "_odoc/base/lib/base/" *)
15+
odoc_file : Fpath.t; (* Full path to odoc file *)
16+
odocl_file : Fpath.t;
1617
include_dirs : Fpath.Set.t;
1718
impl : impl option;
1819
pkg_args : pkg_args;
19-
package_name : string;
20+
pkg_name : string;
21+
pkg_dir : Fpath.t;
2022
}
2123

2224
let mk_byhash (pkgs : Packages.t Util.StringMap.t) =
@@ -67,20 +69,53 @@ let init_stats (pkgs : Packages.t Util.StringMap.t) =
6769

6870
open Eio.Std
6971

70-
let compile output_dir all =
72+
type partial =
73+
(string * compiled) list * (string * Packages.modulety) Util.StringMap.t
74+
75+
let unmarshal filename =
76+
let ic = open_in_bin (Fpath.to_string filename) in
77+
let (v : partial) = Marshal.from_channel ic in
78+
close_in ic;
79+
v
80+
81+
let marshal (v : partial) filename =
82+
let p = Fpath.parent filename in
83+
Util.mkdir_p p;
84+
let oc = open_out_bin (Fpath.to_string filename) in
85+
Marshal.to_channel oc v [];
86+
close_out oc
87+
88+
let find_partials odoc_dir =
89+
let tbl = Hashtbl.create 1000 in
90+
let hashes_result = Bos.OS.Dir.fold_contents ~dotfiles:false
91+
(fun p hashes ->
92+
if Fpath.filename p = "index.m"
93+
then
94+
let (tbl', hashes') = unmarshal p in
95+
List.iter (fun (k,v) -> Hashtbl.replace tbl k (Promise.create_resolved (Ok v))) tbl';
96+
Util.StringMap.union (fun _x o1 _o2 -> Some o1) hashes hashes'
97+
else hashes) Util.StringMap.empty odoc_dir in
98+
match hashes_result with
99+
| Ok h -> h, tbl
100+
| Error _ -> (* odoc_dir doesn't exist...? *) Util.StringMap.empty, tbl
101+
102+
let compile partial ~output_dir ?linked_dir all =
103+
let linked_dir = Option.value linked_dir ~default:output_dir in
71104
let hashes = mk_byhash all in
72-
let tbl = Hashtbl.create 10 in
105+
let other_hashes, tbl =
106+
match partial with
107+
| Some _ -> find_partials output_dir
108+
| None -> Util.StringMap.empty, Hashtbl.create 10 in
109+
let all_hashes = Util.StringMap.union (fun _x o1 _o2 -> Some o1) hashes other_hashes in
73110
let pkg_args =
74111
let docs, libs =
75112
Util.StringMap.fold
76-
(fun pkgname pkg (docs, libs) ->
77-
let ( / ) = Fpath.( / ) in
78-
let doc = (pkgname, output_dir / pkgname / "doc") in
113+
(fun pkgname (pkg : Packages.t) (docs, libs) ->
114+
let doc = (pkgname, Fpath.(output_dir // pkg.mld_odoc_dir)) in
79115
let lib =
80116
List.map
81117
(fun lib ->
82-
( lib.Packages.lib_name,
83-
output_dir / pkgname / "lib" / lib.lib_name ))
118+
( lib.Packages.lib_name, Fpath.(output_dir // lib.Packages.odoc_dir )))
84119
pkg.Packages.libraries
85120
in
86121
let docs = doc :: docs and libs = List.rev_append lib libs in
@@ -91,15 +126,16 @@ let compile output_dir all =
91126
in
92127

93128
let compile_one compile_other hash =
94-
match Util.StringMap.find_opt hash hashes with
129+
match Util.StringMap.find_opt hash all_hashes with
95130
| None ->
96131
Logs.debug (fun m -> m "Error locating hash: %s" hash);
97132
Error Not_found
98133
| Some (package_name, modty) ->
99134
let deps = modty.m_intf.mif_deps in
100-
let output_file = Fpath.(output_dir // modty.m_intf.mif_odoc_file) in
135+
let odoc_file = Fpath.(output_dir // modty.m_intf.mif_odoc_file) in
136+
let odocl_file = Fpath.(linked_dir // modty.m_intf.mif_odocl_file) in
101137
let fibers =
102-
Fiber.List.map
138+
List.map
103139
(fun (n, h) ->
104140
match compile_other h with
105141
| Ok r -> Some r
@@ -114,7 +150,7 @@ let compile output_dir all =
114150
List.fold_left
115151
(fun acc opt ->
116152
match opt with
117-
| Some s -> Fpath.(Set.add s.output_dir acc)
153+
| Some s -> Fpath.(Set.add s.odoc_output_dir acc)
118154
| _ -> acc)
119155
Fpath.Set.empty fibers
120156
in
@@ -124,11 +160,12 @@ let compile output_dir all =
124160
| Some impl -> (
125161
match impl.mip_src_info with
126162
| Some si ->
127-
let output_file = Fpath.(output_dir // impl.mip_odoc_file) in
163+
let odoc_file = Fpath.(output_dir // impl.mip_odoc_file) in
164+
let odocl_file = Fpath.(linked_dir // impl.mip_odocl_file) in
128165
Odoc.compile_impl ~output_dir ~input_file:impl.mip_path
129166
~includes ~parent_id:impl.mip_parent_id ~source_id:si.src_id;
130167
Atomic.incr Stats.stats.compiled_impls;
131-
Some { impl = output_file; src = si.src_path }
168+
Some { impl_odoc = odoc_file; impl_odocl=odocl_file; src = si.src_path }
132169
| None -> None)
133170
| None -> None
134171
in
@@ -137,45 +174,51 @@ let compile output_dir all =
137174
~parent_id:modty.m_intf.mif_parent_id;
138175
Atomic.incr Stats.stats.compiled_units;
139176

140-
let output_dir = Fpath.split_base output_file |> fst in
177+
let odoc_output_dir = Fpath.split_base odoc_file |> fst in
178+
141179
Ok
142180
{
143181
m = Module modty;
144-
output_dir;
145-
output_file;
182+
odoc_output_dir;
183+
odoc_file;
184+
odocl_file;
146185
include_dirs = includes;
147186
impl;
148187
pkg_args;
149-
package_name;
188+
pkg_dir = modty.m_pkg_dir;
189+
pkg_name = package_name;
150190
}
151191
in
152192

153193
let rec compile : string -> (compiled, exn) Result.t =
154194
fun hash ->
155195
match Hashtbl.find_opt tbl hash with
156-
| Some p -> Promise.await_exn p
196+
| Some p -> Promise.await p
157197
| None ->
158198
let p, r = Promise.create () in
159199
Hashtbl.add tbl hash p;
160200
let result = compile_one compile hash in
161-
Promise.resolve_ok r result;
201+
Promise.resolve r result;
162202
result
163203
in
164-
let all_hashes = Util.StringMap.bindings hashes |> List.map fst in
165-
let mod_results = Fiber.List.map compile all_hashes in
204+
let to_build = Util.StringMap.bindings hashes |> List.map fst in
205+
let mod_results = List.map compile to_build in
206+
let zipped_res = List.map2 (fun a b -> (a,b)) to_build mod_results in
207+
let zipped = List.filter_map (function (a, Ok b) -> Some (a,b) | _ -> None) zipped_res in
166208
let mods =
167209
List.filter_map (function Ok x -> Some x | Error _ -> None) mod_results
168210
in
169-
Util.StringMap.fold
211+
let result = Util.StringMap.fold
170212
(fun package_name (pkg : Packages.t) acc ->
171213
Logs.debug (fun m ->
172214
m "Package %s mlds: [%a]" pkg.name
173215
Fmt.(list ~sep:sp Packages.pp_mld)
174216
pkg.mlds);
175217
List.fold_left
176218
(fun acc (mld : Packages.mld) ->
177-
let output_file = Fpath.(output_dir // mld.Packages.mld_odoc_file) in
178-
let odoc_output_dir = Fpath.split_base output_file |> fst in
219+
let odoc_file = Fpath.(output_dir // mld.Packages.mld_odoc_file) in
220+
let odocl_file = Fpath.(linked_dir // mld.Packages.mld_odocl_file) in
221+
let odoc_output_dir = Fpath.split_base odoc_file |> fst in
179222
Odoc.compile ~output_dir ~input_file:mld.mld_path
180223
~includes:Fpath.Set.empty ~parent_id:mld.mld_parent_id;
181224
Atomic.incr Stats.stats.compiled_mlds;
@@ -184,128 +227,124 @@ let compile output_dir all =
184227
|> Fpath.Set.of_list
185228
in
186229
let include_dirs = Fpath.Set.add odoc_output_dir include_dirs in
230+
let odoc_output_dir = Fpath.split_base odoc_file |> fst in
187231
{
188232
m = Mld mld;
189-
output_dir;
190-
output_file;
233+
odoc_output_dir;
234+
odoc_file;
235+
odocl_file;
191236
include_dirs;
192237
impl = None;
193238
pkg_args;
194-
package_name;
239+
pkg_dir = mld.mld_pkg_dir;
240+
pkg_name = package_name;
195241
}
196242
:: acc)
197243
acc pkg.mlds)
198-
all mods
244+
all mods in
245+
246+
(match partial with
247+
| Some l -> marshal (zipped, hashes) Fpath.(l / "index.m")
248+
| None -> ());
249+
result
199250

200251
type linked = {
201252
output_file : Fpath.t;
202253
src : Fpath.t option;
203-
package_name : string;
254+
pkg_dir : Fpath.t;
204255
}
205256

206257
let link : compiled list -> _ =
207258
fun compiled ->
208259
let link : compiled -> linked list =
209260
fun c ->
210-
let includes = Fpath.Set.add c.output_dir c.include_dirs in
211-
let link input_file =
212-
let { pkg_args = { libs; docs }; package_name = current_package; _ } =
261+
let includes = Fpath.Set.add c.odoc_output_dir c.include_dirs in
262+
let link input_file output_file =
263+
let { pkg_args = { libs; docs }; pkg_name; _ } =
213264
c
214265
in
215-
Odoc.link ~input_file ~includes ~libs ~docs ~current_package ()
266+
Odoc.link ~input_file ~output_file ~includes ~libs ~docs ~current_package:pkg_name ()
216267
in
217268
let impl =
218269
match c.impl with
219-
| Some { impl; src } ->
220-
Logs.debug (fun m -> m "Linking impl: %a" Fpath.pp impl);
221-
link impl;
270+
| Some { impl_odoc; impl_odocl; src } ->
271+
Logs.debug (fun m -> m "Linking impl: %a -> %a" Fpath.pp impl_odoc Fpath.pp impl_odocl);
272+
link impl_odoc impl_odocl;
222273
Atomic.incr Stats.stats.linked_impls;
223274
[
224275
{
225-
package_name = c.package_name;
226-
output_file = Fpath.(set_ext "odocl" impl);
276+
pkg_dir = c.pkg_dir;
277+
output_file = impl_odocl;
227278
src = Some src;
228279
};
229280
]
230281
| None -> []
231282
in
232283
match c.m with
233284
| Module m when m.m_hidden ->
234-
Logs.debug (fun m -> m "not linking %a" Fpath.pp c.output_file);
285+
Logs.debug (fun m -> m "not linking %a" Fpath.pp c.odoc_file);
235286
impl
236287
| _ ->
237-
Logs.debug (fun m -> m "linking %a" Fpath.pp c.output_file);
238-
link c.output_file;
288+
Logs.debug (fun m -> m "linking %a" Fpath.pp c.odoc_file);
289+
link c.odoc_file c.odocl_file;
239290
(match c.m with
240291
| Module _ -> Atomic.incr Stats.stats.linked_units
241292
| Mld _ -> Atomic.incr Stats.stats.linked_mlds);
242293
{
243-
output_file = Fpath.(set_ext "odocl" c.output_file);
294+
output_file = c.odocl_file;
244295
src = None;
245-
package_name = c.package_name;
296+
pkg_dir = c.pkg_dir;
246297
}
247298
:: impl
248299
in
249300
Fiber.List.map link compiled |> List.concat
250301

251-
let odoc_index_path ~odoc_dir pkgname =
252-
Fpath.(odoc_dir / pkgname / "index.odoc-index")
253-
let sherlodoc_js_index_path_relative_to_html pkgname =
254-
Fpath.(v pkgname / "sherlodoc_db.js")
255-
256-
let sherlodoc_js_path_relative_to_html = Fpath.v "sherlodoc.js"
257-
let sherlodoc_js_index_path ~html_dir pkgname =
258-
Fpath.(html_dir // sherlodoc_js_index_path_relative_to_html pkgname)
259-
260-
let sherlodoc_js_path ~html_dir =
261-
Fpath.(html_dir // sherlodoc_js_path_relative_to_html)
262-
263-
let sherlodoc_marshall_path ~html_dir =
264-
Fpath.(html_dir / "sherlodoc_db.marshal")
265-
let index_one output_dir pkgname pkg =
266-
let dir = Fpath.(output_dir / pkgname) in
267-
let output_file = odoc_index_path ~odoc_dir:output_dir pkgname in
268-
let ( / ) = Fpath.( / ) in
302+
let index_one ~odocl_dir pkgname pkg =
303+
let dir = pkg.Packages.pkg_dir in
304+
let output_file = Fpath.(odocl_dir // dir / Odoc.index_filename) in
269305
let libs =
270306
List.map
271-
(fun lib -> (lib.Packages.lib_name, dir / "lib" / lib.lib_name))
307+
(fun lib ->
308+
(lib.Packages.lib_name, Fpath.(odocl_dir // lib.odoc_dir)))
272309
pkg.Packages.libraries
273310
in
274311
Odoc.compile_index ~json:false ~output_file ~libs
275-
~docs:[ (pkgname, dir / "doc") ]
312+
~docs:[ (pkgname, Fpath.(odocl_dir // pkg.mld_odoc_dir)) ]
276313
()
277314

278-
let index odoc_dir pkgs = Util.StringMap.iter (index_one odoc_dir) pkgs
315+
let index ~odocl_dir pkgs = Util.StringMap.iter (index_one ~odocl_dir) pkgs
279316

280-
let sherlodoc_index_one ~html_dir ~odoc_dir pkgname _pkg_content =
281-
ignore @@ Bos.OS.Dir.create Fpath.(html_dir / pkgname);
282-
let format = `js in
283-
let inputs = [ odoc_index_path ~odoc_dir pkgname ] in
284-
let dst = sherlodoc_js_index_path ~html_dir pkgname in
285-
Sherlodoc.index ~format ~inputs ~dst ()
317+
let sherlodoc_index_one ~html_dir ~odocl_dir _ pkg_content =
318+
let inputs = [ Fpath.(odocl_dir // pkg_content.Packages.pkg_dir / Odoc.index_filename) ] in
319+
let dst = Fpath.(html_dir // Sherlodoc.db_js_file pkg_content.pkg_dir) in
320+
let dst_dir, _ = Fpath.split_base dst in
321+
Util.mkdir_p dst_dir;
322+
Sherlodoc.index ~format:`js ~inputs ~dst ()
286323

287-
let sherlodoc ~html_dir ~odoc_dir pkgs =
324+
let sherlodoc ~html_dir ~odocl_dir pkgs =
288325
ignore @@ Bos.OS.Dir.create html_dir;
289-
Sherlodoc.js (sherlodoc_js_path ~html_dir);
290-
Util.StringMap.iter (sherlodoc_index_one ~html_dir ~odoc_dir) pkgs;
326+
Sherlodoc.js Fpath.(html_dir // Sherlodoc.js_file);
327+
Util.StringMap.iter (sherlodoc_index_one ~html_dir ~odocl_dir) pkgs;
291328
let format = `marshal in
292-
let dst = sherlodoc_marshall_path ~html_dir in
329+
let dst = Fpath.(html_dir // Sherlodoc.db_marshal_file) in
330+
let dst_dir, _ = Fpath.split_base dst in
331+
Util.mkdir_p dst_dir;
293332
let inputs =
294333
pkgs |> Util.StringMap.bindings
295-
|> List.map (fun (pkgname, _pkg) -> odoc_index_path ~odoc_dir pkgname)
334+
|> List.map (fun (_pkgname, pkg) -> Fpath.(odocl_dir // pkg.Packages.pkg_dir / Odoc.index_filename))
296335
in
297336
Sherlodoc.index ~format ~inputs ~dst ()
298337

299-
let html_generate output_dir ~odoc_dir linked =
338+
let html_generate output_dir ~odocl_dir linked =
300339
let html_generate : linked -> unit =
301340
fun l ->
302341
let search_uris =
303342
[
304-
sherlodoc_js_index_path_relative_to_html l.package_name;
305-
sherlodoc_js_path_relative_to_html;
343+
Sherlodoc.db_js_file l.pkg_dir;
344+
Sherlodoc.js_file;
306345
]
307346
in
308-
let index = Some (odoc_index_path ~odoc_dir l.package_name) in
347+
let index = Some (Fpath.(odocl_dir // l.pkg_dir / Odoc.index_filename)) in
309348
Odoc.html_generate ~search_uris ?index
310349
~output_dir:(Fpath.to_string output_dir)
311350
~input_file:l.output_file ?source:l.src ();

src/driver/compile.mli

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ type compiled
22

33
val init_stats : Packages.set -> unit
44

5-
val compile : Fpath.t -> Packages.set -> compiled list
5+
val compile : Fpath.t option -> output_dir:Fpath.t -> ?linked_dir:Fpath.t -> Packages.set -> compiled list
66

77
type linked
88

99
val link : compiled list -> linked list
1010

11-
val index : Fpath.t -> Packages.set -> unit
11+
val index : odocl_dir:Fpath.t -> Packages.set -> unit
1212

13-
val sherlodoc : html_dir:Fpath.t -> odoc_dir:Fpath.t -> Packages.set -> unit
13+
val sherlodoc : html_dir:Fpath.t -> odocl_dir:Fpath.t -> Packages.set -> unit
1414

1515
(* val compile_sidebars : *)
1616
(* odoc_dir:Fpath.t -> *)
1717
(* output_dir:Fpath.t -> *)
1818
(* Packages.set -> *)
1919
(* Fpath.t Util.StringMap.t *)
2020

21-
val html_generate : Fpath.t -> odoc_dir:Fpath.t -> linked list -> unit
21+
val html_generate : Fpath.t -> odocl_dir:Fpath.t -> linked list -> unit

0 commit comments

Comments
 (0)