2
2
3
3
type ty = Module of Packages .modulety | Mld of Packages .mld
4
4
5
- type impl = { impl : Fpath .t ; src : Fpath .t }
5
+ type impl = { impl_odoc : Fpath .t ; impl_odocl : Fpath .t ; src : Fpath .t }
6
6
7
7
type pkg_args = {
8
8
docs : (string * Fpath .t ) list ;
@@ -11,12 +11,14 @@ type pkg_args = {
11
11
12
12
type compiled = {
13
13
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 ;
16
17
include_dirs : Fpath.Set .t ;
17
18
impl : impl option ;
18
19
pkg_args : pkg_args ;
19
- package_name : string ;
20
+ pkg_name : string ;
21
+ pkg_dir : Fpath .t ;
20
22
}
21
23
22
24
let mk_byhash (pkgs : Packages.t Util.StringMap.t ) =
@@ -67,20 +69,53 @@ let init_stats (pkgs : Packages.t Util.StringMap.t) =
67
69
68
70
open Eio.Std
69
71
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
71
104
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
73
110
let pkg_args =
74
111
let docs, libs =
75
112
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
79
115
let lib =
80
116
List. map
81
117
(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 )))
84
119
pkg.Packages. libraries
85
120
in
86
121
let docs = doc :: docs and libs = List. rev_append lib libs in
@@ -91,15 +126,16 @@ let compile output_dir all =
91
126
in
92
127
93
128
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
95
130
| None ->
96
131
Logs. debug (fun m -> m " Error locating hash: %s" hash);
97
132
Error Not_found
98
133
| Some (package_name , modty ) ->
99
134
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
101
137
let fibers =
102
- Fiber. List. map
138
+ List. map
103
139
(fun (n , h ) ->
104
140
match compile_other h with
105
141
| Ok r -> Some r
@@ -114,7 +150,7 @@ let compile output_dir all =
114
150
List. fold_left
115
151
(fun acc opt ->
116
152
match opt with
117
- | Some s -> Fpath. (Set. add s.output_dir acc)
153
+ | Some s -> Fpath. (Set. add s.odoc_output_dir acc)
118
154
| _ -> acc)
119
155
Fpath.Set. empty fibers
120
156
in
@@ -124,11 +160,12 @@ let compile output_dir all =
124
160
| Some impl -> (
125
161
match impl.mip_src_info with
126
162
| 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
128
165
Odoc. compile_impl ~output_dir ~input_file: impl.mip_path
129
166
~includes ~parent_id: impl.mip_parent_id ~source_id: si.src_id;
130
167
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 }
132
169
| None -> None )
133
170
| None -> None
134
171
in
@@ -137,45 +174,51 @@ let compile output_dir all =
137
174
~parent_id: modty.m_intf.mif_parent_id;
138
175
Atomic. incr Stats. stats.compiled_units;
139
176
140
- let output_dir = Fpath. split_base output_file |> fst in
177
+ let odoc_output_dir = Fpath. split_base odoc_file |> fst in
178
+
141
179
Ok
142
180
{
143
181
m = Module modty;
144
- output_dir;
145
- output_file;
182
+ odoc_output_dir;
183
+ odoc_file;
184
+ odocl_file;
146
185
include_dirs = includes;
147
186
impl;
148
187
pkg_args;
149
- package_name;
188
+ pkg_dir = modty.m_pkg_dir;
189
+ pkg_name = package_name;
150
190
}
151
191
in
152
192
153
193
let rec compile : string -> (compiled, exn) Result.t =
154
194
fun hash ->
155
195
match Hashtbl. find_opt tbl hash with
156
- | Some p -> Promise. await_exn p
196
+ | Some p -> Promise. await p
157
197
| None ->
158
198
let p, r = Promise. create () in
159
199
Hashtbl. add tbl hash p;
160
200
let result = compile_one compile hash in
161
- Promise. resolve_ok r result;
201
+ Promise. resolve r result;
162
202
result
163
203
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
166
208
let mods =
167
209
List. filter_map (function Ok x -> Some x | Error _ -> None ) mod_results
168
210
in
169
- Util.StringMap. fold
211
+ let result = Util.StringMap. fold
170
212
(fun package_name (pkg : Packages.t ) acc ->
171
213
Logs. debug (fun m ->
172
214
m " Package %s mlds: [%a]" pkg.name
173
215
Fmt. (list ~sep: sp Packages. pp_mld)
174
216
pkg.mlds);
175
217
List. fold_left
176
218
(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
179
222
Odoc. compile ~output_dir ~input_file: mld.mld_path
180
223
~includes: Fpath.Set. empty ~parent_id: mld.mld_parent_id;
181
224
Atomic. incr Stats. stats.compiled_mlds;
@@ -184,128 +227,124 @@ let compile output_dir all =
184
227
|> Fpath.Set. of_list
185
228
in
186
229
let include_dirs = Fpath.Set. add odoc_output_dir include_dirs in
230
+ let odoc_output_dir = Fpath. split_base odoc_file |> fst in
187
231
{
188
232
m = Mld mld;
189
- output_dir;
190
- output_file;
233
+ odoc_output_dir;
234
+ odoc_file;
235
+ odocl_file;
191
236
include_dirs;
192
237
impl = None ;
193
238
pkg_args;
194
- package_name;
239
+ pkg_dir = mld.mld_pkg_dir;
240
+ pkg_name = package_name;
195
241
}
196
242
:: acc)
197
243
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
199
250
200
251
type linked = {
201
252
output_file : Fpath .t ;
202
253
src : Fpath .t option ;
203
- package_name : string ;
254
+ pkg_dir : Fpath .t ;
204
255
}
205
256
206
257
let link : compiled list -> _ =
207
258
fun compiled ->
208
259
let link : compiled -> linked list =
209
260
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 ; _ } =
213
264
c
214
265
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 ()
216
267
in
217
268
let impl =
218
269
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 ;
222
273
Atomic. incr Stats. stats.linked_impls;
223
274
[
224
275
{
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 ;
227
278
src = Some src;
228
279
};
229
280
]
230
281
| None -> []
231
282
in
232
283
match c.m with
233
284
| 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 );
235
286
impl
236
287
| _ ->
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 ;
239
290
(match c.m with
240
291
| Module _ -> Atomic. incr Stats. stats.linked_units
241
292
| Mld _ -> Atomic. incr Stats. stats.linked_mlds);
242
293
{
243
- output_file = Fpath. (set_ext " odocl " c.output_file) ;
294
+ output_file = c.odocl_file ;
244
295
src = None ;
245
- package_name = c.package_name ;
296
+ pkg_dir = c.pkg_dir ;
246
297
}
247
298
:: impl
248
299
in
249
300
Fiber.List. map link compiled |> List. concat
250
301
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
269
305
let libs =
270
306
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)))
272
309
pkg.Packages. libraries
273
310
in
274
311
Odoc. compile_index ~json: false ~output_file ~libs
275
- ~docs: [ (pkgname, dir / " doc " ) ]
312
+ ~docs: [ (pkgname, Fpath. (odocl_dir // pkg.mld_odoc_dir) ) ]
276
313
()
277
314
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
279
316
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 ()
286
323
287
- let sherlodoc ~html_dir ~odoc_dir pkgs =
324
+ let sherlodoc ~html_dir ~odocl_dir pkgs =
288
325
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;
291
328
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;
293
332
let inputs =
294
333
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) )
296
335
in
297
336
Sherlodoc. index ~format ~inputs ~dst ()
298
337
299
- let html_generate output_dir ~odoc_dir linked =
338
+ let html_generate output_dir ~odocl_dir linked =
300
339
let html_generate : linked -> unit =
301
340
fun l ->
302
341
let search_uris =
303
342
[
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 ;
306
345
]
307
346
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
309
348
Odoc. html_generate ~search_uris ?index
310
349
~output_dir: (Fpath. to_string output_dir)
311
350
~input_file: l.output_file ?source:l.src () ;
0 commit comments