this repo has no description
at main 335 lines 11 kB view raw
1open Odoc_unit 2 3type indices_style = 4 | Voodoo 5 | Normal of { toplevel_content : string option } 6 | Automatic 7 8let packages ~dirs ~extra_paths ~remap ~indices_style (pkgs : Packages.t list) : 9 any list = 10 let { odoc_dir; odocl_dir; index_dir; mld_dir = _ } = dirs in 11 12 let extra_libs_paths = extra_paths.Voodoo.libs in 13 let extra_libs_of_pkg = extra_paths.Voodoo.libs_of_pkg in 14 let extra_pkg_paths = extra_paths.Voodoo.pkgs in 15 16 let lib_dirs = 17 let open Packages in 18 let lds = extra_libs_paths in 19 List.fold_left 20 (fun lds pkg -> 21 List.fold_left 22 (fun lds lib -> 23 let lib_dir = lib_dir pkg lib in 24 let lds' = Util.StringMap.add lib.lib_name lib_dir lds in 25 lds') 26 lds pkg.libraries) 27 lds pkgs 28 in 29 let pkg_paths = 30 List.fold_left 31 (fun acc pkg -> Util.StringMap.add pkg.Packages.name (doc_dir pkg) acc) 32 extra_pkg_paths pkgs 33 in 34 35 let libs_of_pkg = 36 let libs_of_pkg pkg = 37 List.map (fun lib -> lib.Packages.lib_name) pkg.Packages.libraries 38 in 39 List.fold_left 40 (fun acc pkg -> 41 Util.StringMap.add pkg.Packages.name (libs_of_pkg pkg) acc) 42 extra_libs_of_pkg pkgs 43 in 44 45 let dash_p pkgname path = (pkgname, path) in 46 47 let dash_l lib_name = 48 match Util.StringMap.find_opt lib_name lib_dirs with 49 | Some dir -> [ (lib_name, dir) ] 50 | None -> 51 Logs.debug (fun m -> m "Library %s not found" lib_name); 52 [] 53 in 54 let base_args pkg lib_deps : Pkg_args.t = 55 let own_page = dash_p pkg.Packages.name (doc_dir pkg) in 56 let includes = 57 List.concat_map dash_l (Util.StringSet.to_list lib_deps) |> List.map snd 58 in 59 let libs = 60 List.fold_left 61 (fun acc lib -> Util.StringSet.add lib.Packages.lib_name acc) 62 lib_deps pkg.Packages.libraries 63 in 64 let libs = List.concat_map dash_l (Util.StringSet.to_list libs) in 65 Pkg_args.v ~pages:[ own_page ] ~libs ~includes ~odoc_dir ~odocl_dir 66 in 67 let args_of_config config : Pkg_args.t = 68 let { Global_config.deps = { packages; libraries } } = config in 69 let pages_rel = 70 List.filter_map 71 (fun pkgname -> 72 match Util.StringMap.find_opt pkgname pkg_paths with 73 | None -> 74 Logs.debug (fun m -> m "Package '%s' not found" pkgname); 75 None 76 | Some path -> Some (dash_p pkgname path)) 77 packages 78 in 79 (* Add all liraries from added packages *) 80 let libraries_from_pkgs = 81 List.filter_map 82 (fun pkgname -> Util.StringMap.find_opt pkgname libs_of_pkg) 83 packages 84 in 85 let libraries = List.concat @@ (libraries :: libraries_from_pkgs) in 86 let libs_rel = List.concat_map dash_l libraries in 87 Pkg_args.v ~pages:pages_rel ~libs:libs_rel ~includes:[] ~odoc_dir ~odocl_dir 88 in 89 let args_of = 90 let cache = Hashtbl.create 10 in 91 fun pkg lib_deps : Pkg_args.t -> 92 match Hashtbl.find_opt cache (pkg, lib_deps) with 93 | Some res -> res 94 | None -> 95 let result = 96 Pkg_args.combine (base_args pkg lib_deps) 97 (args_of_config pkg.Packages.config) 98 in 99 Hashtbl.add cache (pkg, lib_deps) result; 100 result 101 in 102 103 let index_of pkg = 104 let roots = [ Fpath.( // ) odocl_dir (doc_dir pkg) ] in 105 let output_file = Fpath.(index_dir / pkg.name / Odoc.index_filename) in 106 let pkg_dir = doc_dir pkg in 107 let sidebar = 108 let output_file = Fpath.(index_dir / pkg.name / Odoc.sidebar_filename) in 109 { output_file; json = false; pkg_dir } 110 in 111 { 112 roots; 113 output_file; 114 json = false; 115 search_dir = doc_dir pkg; 116 sidebar = Some sidebar; 117 } 118 in 119 120 let make_unit ~name ~kind ~rel_dir ~input_file ~pkg ~lib_deps ~enable_warnings 121 ~to_output ~stash_input : _ t = 122 let to_output = to_output || not remap in 123 (* If we haven't got active remapping, we output everything *) 124 let ( // ) = Fpath.( // ) in 125 let ( / ) = Fpath.( / ) in 126 let pkg_args = args_of pkg lib_deps in 127 let parent_id = rel_dir |> Odoc.Id.of_fpath in 128 let odoc_file = 129 odoc_dir // rel_dir / (String.uncapitalize_ascii name ^ ".odoc") 130 in 131 (* odoc will uncapitalise the output filename *) 132 let odocl_file = 133 odocl_dir // rel_dir / (String.uncapitalize_ascii name ^ ".odocl") 134 in 135 let input_copy = 136 if stash_input then 137 Some (odoc_dir // rel_dir / (String.uncapitalize_ascii name ^ ".cmti")) 138 else None 139 in 140 { 141 output_dir = odoc_dir; 142 pkgname = Some pkg.Packages.name; 143 pkg_args; 144 parent_id; 145 input_file; 146 input_copy; 147 odoc_file; 148 odocl_file; 149 kind; 150 to_output; 151 enable_warnings; 152 index = Some (index_of pkg); 153 } 154 in 155 156 let of_intf hidden pkg (lib : Packages.libty) lib_deps (intf : Packages.intf) 157 : intf t = 158 let rel_dir = lib_dir pkg lib in 159 let kind = 160 let deps = intf.mif_deps in 161 let kind = `Intf { hidden; hash = intf.mif_hash; deps } in 162 kind 163 in 164 let name = intf.mif_path |> Fpath.rem_ext |> Fpath.basename in 165 let stash_input = lib.archive_name = None in 166 make_unit ~name ~kind ~rel_dir ~input_file:intf.mif_path ~pkg ~lib_deps 167 ~enable_warnings:pkg.selected ~to_output:pkg.selected ~stash_input 168 in 169 let of_impl pkg lib lib_deps (impl : Packages.impl) : impl t option = 170 match impl.mip_src_info with 171 | None -> None 172 | Some { src_path } -> 173 let rel_dir = lib_dir pkg lib in 174 let kind = 175 let src_name = Fpath.filename src_path in 176 let src_id = 177 Fpath.(src_lib_dir pkg lib / src_name) |> Odoc.Id.of_fpath 178 in 179 `Impl { src_id; src_path } 180 in 181 let name = 182 impl.mip_path |> Fpath.rem_ext |> Fpath.basename 183 |> String.uncapitalize_ascii |> ( ^ ) "impl-" 184 in 185 let unit = 186 make_unit ~name ~kind ~rel_dir ~input_file:impl.mip_path ~pkg 187 ~lib_deps ~enable_warnings:false ~to_output:pkg.selected 188 ~stash_input:false 189 in 190 Some unit 191 in 192 193 let of_module pkg (lib : Packages.libty) lib_deps (m : Packages.modulety) : 194 any list = 195 let i :> any = of_intf m.m_hidden pkg lib lib_deps m.m_intf in 196 let m :> any list = 197 Option.bind m.m_impl (of_impl pkg lib lib_deps) |> Option.to_list 198 in 199 i :: m 200 in 201 let of_lib pkg (lib : Packages.libty) = 202 let lib_deps = Util.StringSet.add lib.lib_name lib.lib_deps in 203 let index = index_of pkg in 204 let units = List.concat_map (of_module pkg lib lib_deps) lib.modules in 205 if remap && not pkg.selected then units 206 else 207 let landing_page :> any = Landing_pages.library ~dirs ~pkg ~index lib in 208 landing_page :: units 209 in 210 let of_mld pkg (mld : Packages.mld) : mld t list = 211 let open Fpath in 212 let { Packages.mld_path; mld_rel_path } = mld in 213 let rel_dir = doc_dir pkg // Fpath.parent mld_rel_path |> Fpath.normalize in 214 let kind = `Mld in 215 let name = mld_path |> Fpath.rem_ext |> Fpath.basename |> ( ^ ) "page-" in 216 let lib_deps = 217 pkg.libraries 218 |> List.map (fun lib -> lib.Packages.lib_name) 219 |> Util.StringSet.of_list 220 in 221 let unit = 222 make_unit ~name ~kind ~rel_dir ~input_file:mld_path ~pkg ~lib_deps 223 ~enable_warnings:pkg.selected ~to_output:pkg.selected ~stash_input:false 224 in 225 [ unit ] 226 in 227 let of_md pkg (md : Packages.md) : md t list = 228 let ext = Fpath.get_ext md.md_path in 229 match ext with 230 | ".md" -> 231 let open Fpath in 232 let { Packages.md_path; md_rel_path } = md in 233 let rel_dir = 234 doc_dir pkg // Fpath.parent md_rel_path |> Fpath.normalize 235 in 236 let kind = `Md in 237 let name = 238 md_path |> Fpath.rem_ext |> Fpath.basename |> ( ^ ) "page-" 239 in 240 let lib_deps = Util.StringSet.empty in 241 let unit = 242 make_unit ~name ~kind ~rel_dir ~input_file:md_path ~pkg ~lib_deps 243 ~enable_warnings:pkg.selected ~to_output:pkg.selected 244 ~stash_input:false 245 in 246 [ unit ] 247 | _ -> 248 Logs.debug (fun m -> 249 m "Skipping non-markdown doc file %a" Fpath.pp md.md_path); 250 [] 251 in 252 let of_asset pkg (asset : Packages.asset) : asset t list = 253 let open Fpath in 254 let { Packages.asset_path; asset_rel_path } = asset in 255 let rel_dir = 256 doc_dir pkg // Fpath.parent asset_rel_path |> Fpath.normalize 257 in 258 let kind = `Asset in 259 let unit = 260 let name = asset_path |> Fpath.basename |> ( ^ ) "asset-" in 261 make_unit ~name ~kind ~rel_dir ~input_file:asset_path ~pkg 262 ~lib_deps:Util.StringSet.empty ~enable_warnings:false ~to_output:true 263 ~stash_input:false 264 in 265 [ unit ] 266 in 267 268 let of_package (pkg : Packages.t) : any list = 269 let lib_units :> any list list = List.map (of_lib pkg) pkg.libraries in 270 let mld_units :> any list list = List.map (of_mld pkg) pkg.mlds in 271 let asset_units :> any list list = List.map (of_asset pkg) pkg.assets in 272 let md_units :> any list list = List.map (of_md pkg) pkg.other_docs in 273 let pkg_index () :> any list = 274 let has_index_page = 275 List.exists 276 (fun mld -> 277 Fpath.equal 278 (Fpath.normalize mld.Packages.mld_rel_path) 279 (Fpath.normalize (Fpath.v "./index.mld"))) 280 pkg.mlds 281 in 282 if has_index_page || (remap && not pkg.selected) then [] 283 else 284 let index = index_of pkg in 285 [ Landing_pages.package ~dirs ~pkg ~index ] 286 in 287 let src_index () :> any list = 288 if remap && not pkg.selected then [] 289 else if 290 (* Some library has a module which has an implementation which has a source *) 291 List.exists 292 (fun lib -> 293 List.exists 294 (fun m -> 295 match m.Packages.m_impl with 296 | Some { mip_src_info = Some _; _ } -> true 297 | _ -> false) 298 lib.Packages.modules) 299 pkg.libraries 300 then 301 let index = index_of pkg in 302 [ Landing_pages.src ~dirs ~pkg ~index ] 303 else [] 304 in 305 let std_units = mld_units @ asset_units @ md_units @ lib_units in 306 match indices_style with 307 | Automatic when pkg.name = Monorepo_style.monorepo_pkg_name -> 308 let others :> any list = 309 Landing_pages.make_custom dirs index_of 310 (List.find 311 (fun p -> p.Packages.name = Monorepo_style.monorepo_pkg_name) 312 pkgs) 313 in 314 others @ List.concat std_units 315 | Normal _ | Voodoo | Automatic -> 316 List.concat (pkg_index () :: src_index () :: std_units) 317 in 318 match indices_style with 319 | Normal { toplevel_content = None } -> 320 let gen_indices :> any = Landing_pages.package_list ~dirs ~remap pkgs in 321 gen_indices :: List.concat_map of_package pkgs 322 | Normal { toplevel_content = Some content } -> 323 let content ppf = Format.fprintf ppf "%s" content in 324 let libs = 325 List.concat_map 326 (fun pkg -> List.map (fun lib -> (pkg, lib)) pkg.Packages.libraries) 327 pkgs 328 in 329 let index :> any = 330 Landing_pages.make_index ~dirs 331 ~rel_dir:Fpath.(v "./") 332 ~libs ~pkgs ~enable_warnings:true ~content ~index:None 333 in 334 index :: List.concat_map of_package pkgs 335 | Voodoo | Automatic -> List.concat_map of_package pkgs