this repo has no description
at main 232 lines 7.4 kB view raw
1module Pkg_args = struct 2 type t = { 3 odoc_dir : Fpath.t; 4 odocl_dir : Fpath.t; 5 includes : Fpath.Set.t; 6 pages : Fpath.t Util.StringMap.t; 7 libs : Fpath.t Util.StringMap.t; 8 } 9 10 let v ~odoc_dir ~odocl_dir ~includes ~pages ~libs = 11 let includes = Fpath.Set.of_list includes in 12 let pages, libs = Util.StringMap.(of_list pages, of_list libs) in 13 { odoc_dir; odocl_dir; includes; pages; libs } 14 15 let map_rel dir m = 16 Util.StringMap.fold (fun a b acc -> (a, Fpath.(dir // b)) :: acc) m [] 17 18 let compiled_pages v = map_rel v.odoc_dir v.pages 19 let compiled_libs v = map_rel v.odoc_dir v.libs 20 let includes (x : t) = 21 List.map (fun y -> Fpath.(x.odoc_dir // y)) (Fpath.Set.to_list x.includes) 22 let linked_pages v = map_rel v.odocl_dir v.pages 23 let linked_libs v = map_rel v.odocl_dir v.libs 24 25 let combine v1 v2 = 26 if v1.odoc_dir <> v2.odoc_dir then 27 Fmt.invalid_arg "combine: odoc_dir differs"; 28 if v1.odocl_dir <> v2.odocl_dir then 29 Fmt.invalid_arg "combine: odocl_dir differs"; 30 { 31 odoc_dir = v1.odoc_dir; 32 odocl_dir = v1.odocl_dir; 33 includes = Fpath.Set.union v1.includes v2.includes; 34 pages = Util.StringMap.union (fun _ x _ -> Some x) v1.pages v2.pages; 35 libs = Util.StringMap.union (fun _ x _ -> Some x) v1.libs v2.libs; 36 } 37 38 let pp fmt x = 39 let sfp_pp = 40 Fmt.( 41 list ~sep:comma (fun fmt (a, b) -> 42 Format.fprintf fmt "(%s, %a)" a Fpath.pp b)) 43 in 44 Format.fprintf fmt 45 "@[<hov>odoc_dir: %a@;\ 46 odocl_dir: %a@;\ 47 includes: %a@;\ 48 pages: [%a]@;\ 49 libs: [%a]@]" 50 Fpath.pp x.odoc_dir Fpath.pp x.odocl_dir 51 Fmt.Dump.(list Fpath.pp) 52 (Fpath.Set.to_list x.includes) 53 sfp_pp 54 (Util.StringMap.bindings x.pages) 55 sfp_pp 56 (Util.StringMap.bindings x.libs) 57end 58 59type sidebar = { output_file : Fpath.t; json : bool; pkg_dir : Fpath.t } 60 61type index = { 62 roots : Fpath.t list; 63 output_file : Fpath.t; 64 json : bool; 65 search_dir : Fpath.t; 66 sidebar : sidebar option; 67} 68 69let pp_index fmt x = 70 Format.fprintf fmt 71 "@[<hov>roots: %a@;output_file: %a@;json: %b@;search_dir: %a@]" 72 (Fmt.list Fpath.pp) x.roots Fpath.pp x.output_file x.json Fpath.pp 73 x.search_dir 74 75type 'a t = { 76 parent_id : Odoc.Id.t; 77 input_file : Fpath.t; 78 input_copy : Fpath.t option; 79 (* Used to stash cmtis from virtual libraries into the odoc dir for voodoo mode. 80 See https://github.com/ocaml/odoc/pull/1309 *) 81 output_dir : Fpath.t; 82 odoc_file : Fpath.t; 83 odocl_file : Fpath.t; 84 pkg_args : Pkg_args.t; 85 pkgname : string option; 86 index : index option; 87 enable_warnings : bool; 88 to_output : bool; 89 kind : 'a; 90} 91 92type intf_extra = { 93 hidden : bool; 94 hash : string; 95 deps : (string * Digest.t) list; 96} 97 98and intf = [ `Intf of intf_extra ] 99 100type impl_extra = { src_id : Odoc.Id.t; src_path : Fpath.t } 101type impl = [ `Impl of impl_extra ] 102 103type mld = [ `Mld ] 104type md = [ `Md ] 105type asset = [ `Asset ] 106 107type all_kinds = [ impl | intf | mld | asset | md ] 108type any = all_kinds t 109 110let rec pp_kind : all_kinds Fmt.t = 111 fun fmt x -> 112 match x with 113 | `Intf x -> Format.fprintf fmt "`Intf %a" pp_intf_extra x 114 | `Impl x -> Format.fprintf fmt "`Impl %a" pp_impl_extra x 115 | `Mld -> Format.fprintf fmt "`Mld" 116 | `Md -> Format.fprintf fmt "`Md" 117 | `Asset -> Format.fprintf fmt "`Asset" 118 119and pp_intf_extra fmt x = 120 Format.fprintf fmt "@[<hov>hidden: %b@;hash: %s@;deps: [%a]@]" x.hidden x.hash 121 Fmt.Dump.(list (pair string string)) 122 x.deps 123 124and pp_impl_extra fmt x = 125 Format.fprintf fmt "@[<hov>src_id: %s@;src_path: %a@]" 126 (Odoc.Id.to_string x.src_id) 127 Fpath.pp x.src_path 128 129and pp : all_kinds t Fmt.t = 130 fun fmt x -> 131 Format.fprintf fmt 132 "@[<hov>parent_id: %s@;\ 133 input_file: %a@;\ 134 output_dir: %a@;\ 135 odoc_file: %a@;\ 136 odocl_file: %a@;\ 137 pkg_args: %a@;\ 138 pkgname: %a@;\ 139 index: %a@;\ 140 kind:%a@;\ 141 @]" 142 (Odoc.Id.to_string x.parent_id) 143 Fpath.pp x.input_file Fpath.pp x.output_dir Fpath.pp x.odoc_file Fpath.pp 144 x.odocl_file Pkg_args.pp x.pkg_args (Fmt.option Fmt.string) x.pkgname 145 (Fmt.option pp_index) x.index pp_kind 146 (x.kind :> all_kinds) 147 148let pkg_dir : Packages.t -> Fpath.t = fun pkg -> pkg.pkg_dir 149let doc_dir : Packages.t -> Fpath.t = fun pkg -> pkg.doc_dir 150let lib_dir (pkg : Packages.t) (lib : Packages.libty) = 151 match lib.id_override with 152 | Some id -> Fpath.v id 153 | None -> Fpath.(doc_dir pkg / lib.Packages.lib_name) 154let src_dir pkg = Fpath.(doc_dir pkg / "src") 155let src_lib_dir (pkg : Packages.t) (lib : Packages.libty) = 156 match lib.id_override with 157 | Some id -> Fpath.v id 158 | None -> Fpath.(src_dir pkg / lib.Packages.lib_name) 159 160type dirs = { 161 odoc_dir : Fpath.t; 162 odocl_dir : Fpath.t; 163 index_dir : Fpath.t; 164 mld_dir : Fpath.t; 165} 166 167let fix_virtual ~(precompiled_units : intf t list Util.StringMap.t) 168 ~(units : intf t list Util.StringMap.t) = 169 Logs.debug (fun m -> 170 m "Fixing virtual libraries: %d precompiled units, %d other units" 171 (Util.StringMap.cardinal precompiled_units) 172 (Util.StringMap.cardinal units)); 173 let all = 174 Util.StringMap.union 175 (fun h x y -> 176 Logs.debug (fun m -> 177 m "Unifying hash %s (%d, %d)" h (List.length x) (List.length y)); 178 Some (x @ y)) 179 precompiled_units units 180 in 181 Util.StringMap.map 182 (fun units -> 183 List.map 184 (fun unit -> 185 let uhash = match unit.kind with `Intf { hash; _ } -> hash in 186 if not (Fpath.has_ext "cmt" unit.input_file) then unit 187 else 188 match Util.StringMap.find uhash all with 189 | [ _ ] -> unit 190 | xs -> ( 191 let unit_name = 192 Fpath.rem_ext unit.input_file |> Fpath.basename 193 in 194 match 195 List.filter 196 (fun (x : intf t) -> 197 (match x.kind with `Intf { hash; _ } -> uhash = hash) 198 && Fpath.has_ext "cmti" x.input_file 199 && Fpath.rem_ext x.input_file |> Fpath.basename 200 = unit_name) 201 xs 202 with 203 | [ x ] -> { unit with input_file = x.input_file } 204 | xs -> ( 205 Logs.debug (fun m -> 206 m 207 "Duplicate hash found, but multiple (%d) matching \ 208 cmti found for %a" 209 (List.length xs) Fpath.pp unit.input_file); 210 let possibles = 211 List.find_map 212 (fun x -> 213 match x.input_copy with 214 | Some x -> 215 if 216 x |> Bos.OS.File.exists 217 |> Result.value ~default:false 218 then Some x 219 else None 220 | None -> None) 221 xs 222 in 223 match possibles with 224 | None -> 225 Logs.debug (fun m -> m "Not replacing input file"); 226 unit 227 | Some x -> 228 Logs.debug (fun m -> 229 m "Replacing input_file of unit with %a" Fpath.pp x); 230 { unit with input_file = x }))) 231 units) 232 units