A fork of mtelver's day10 project
at main 153 lines 7.7 kB view raw
1(** Doc tools layer management for odoc toolchain. 2 3 Split into two layers: 4 1. Driver layer (shared): odoc_driver_voodoo, sherlodoc, odoc-md 5 - Built once with OCaml 5.x 6 - These tools just need executables, don't need to match target compiler 7 8 2. Odoc layer (per OCaml version): odoc 9 - Must be built with same OCaml version as target packages 10 - .cmt/.cmti files have version-specific formats 11 12 All tools are pinned to odoc 3.1 from the configured repo/branch. *) 13 14let driver_packages = [ "odoc"; "odoc-parser"; "odoc-md"; "sherlodoc"; "odoc-driver" ] 15let odoc_packages = [ "odoc"; "odoc-parser" ] 16 17(** Return the local repo path to bind-mount for doc tools, if any. *) 18let local_repo_mount ~(config : Config.t) = 19 match Local_repo.find_for_packages ~local_repos:config.local_repos driver_packages with 20 | Some (path, _) -> Some (path, "/home/opam/local/odoc") 21 | None -> None 22 23(** Compute hash for the shared driver layer. 24 Depends on repo/branch and compiler layers (when stacking on pre-built compiler). *) 25let driver_layer_hash ~(config : Config.t) ~(compiler_layers : string list) = 26 let source_component = match Local_repo.find_for_packages ~local_repos:config.local_repos driver_packages with 27 | Some (path, _) -> Local_repo.repo_hash path 28 | None -> config.doc_tools_repo ^ "|" ^ config.doc_tools_branch 29 in 30 let components = [ "driver"; source_component ] @ compiler_layers in 31 String.concat "|" components |> Digest.string |> Digest.to_hex 32 33(** Directory name for the driver layer *) 34let driver_layer_name ~(config : Config.t) ~(compiler_layers : string list) = 35 "doc-driver-" ^ driver_layer_hash ~config ~compiler_layers 36 37(** Full path to the driver layer *) 38let driver_layer_path ~(config : Config.t) ~(compiler_layers : string list) = 39 let os_key = Config.os_key ~config in 40 Path.(config.dir / os_key / driver_layer_name ~config ~compiler_layers) 41 42(** Generate build script for the shared driver layer. 43 Builds odoc_driver_voodoo, sherlodoc, and odoc-md. 44 When [needs_compiler] is true, installs ocaml-base-compiler.5.2.1 first. 45 When false (compiler comes from lower layers), skips compiler installation. *) 46let driver_build_script ~(config : Config.t) ~needs_compiler = 47 let repo = config.doc_tools_repo in 48 let branch = config.doc_tools_branch in 49 let pin_cmds = match Local_repo.find_for_packages ~local_repos:config.local_repos driver_packages with 50 | Some (_, matched) -> 51 let local_mount = "/home/opam/local/odoc" in 52 let from_local = List.map (fun pkg -> 53 Printf.sprintf "opam pin add -yn %s %s" pkg local_mount 54 ) matched in 55 let from_git = List.filter_map (fun pkg -> 56 if List.mem pkg matched then None 57 else Some (Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch) 58 ) driver_packages in 59 from_local @ from_git 60 | None -> 61 List.map (fun pkg -> 62 Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch 63 ) driver_packages 64 in 65 let compiler_cmds = if needs_compiler then [ "opam install -y ocaml-base-compiler.5.2.1" ] else [] in 66 String.concat " && " 67 (compiler_cmds 68 @ pin_cmds 69 @ [ "opam install -y odoc-driver odoc-md sherlodoc"; 70 "eval $(opam env) && sherlodoc js > /home/opam/sherlodoc.js"; 71 "which odoc_driver_voodoo && which sherlodoc" ]) 72 73(** Check if driver layer exists *) 74let driver_exists ~(config : Config.t) ~(compiler_layers : string list) : bool = 75 Sys.file_exists (driver_layer_path ~config ~compiler_layers) 76 77(** Get the hash/name for the driver layer *) 78let get_driver_hash ~(config : Config.t) ~(compiler_layers : string list) : string = 79 driver_layer_name ~config ~compiler_layers 80 81(** Check if odoc_driver_voodoo is available in the driver layer *) 82let has_odoc_driver_voodoo ~(config : Config.t) ~(compiler_layers : string list) : bool = 83 let voodoo_path = Path.(driver_layer_path ~config ~compiler_layers / "fs" / "home" / "opam" / ".opam" / "default" / "bin" / "odoc_driver_voodoo") in 84 Sys.file_exists voodoo_path 85 86(** Path to sherlodoc.js within the driver layer *) 87let sherlodoc_js_path ~(config : Config.t) ~(compiler_layers : string list) = 88 Path.(driver_layer_path ~config ~compiler_layers / "fs" / "home" / "opam" / "sherlodoc.js") 89 90(* --- Per-version odoc layer --- *) 91 92(** Compute hash for the per-version odoc layer. 93 Depends on OCaml version, repo/branch, and compiler layers. *) 94let odoc_layer_hash ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~(compiler_layers : string list) = 95 let compiler_pkg = OpamPackage.to_string ocaml_version in 96 let source_component = match Local_repo.find_for_packages ~local_repos:config.local_repos odoc_packages with 97 | Some (path, _) -> Local_repo.repo_hash path 98 | None -> config.doc_tools_repo ^ "|" ^ config.doc_tools_branch 99 in 100 let components = [ "odoc"; compiler_pkg; source_component ] @ compiler_layers in 101 String.concat "|" components |> Digest.string |> Digest.to_hex 102 103(** Directory name for the odoc layer *) 104let odoc_layer_name ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~(compiler_layers : string list) = 105 "doc-odoc-" ^ odoc_layer_hash ~config ~ocaml_version ~compiler_layers 106 107(** Full path to the odoc layer *) 108let odoc_layer_path ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~(compiler_layers : string list) = 109 let os_key = Config.os_key ~config in 110 Path.(config.dir / os_key / odoc_layer_name ~config ~ocaml_version ~compiler_layers) 111 112(** Generate build script for the per-version odoc layer. 113 Builds odoc with the specified OCaml version, pinned to 3.1 from repo/branch. 114 When [needs_compiler] is false, skips compiler installation (comes from lower layers). *) 115let odoc_build_script ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~needs_compiler = 116 let repo = config.doc_tools_repo in 117 let branch = config.doc_tools_branch in 118 let compiler_pkg = OpamPackage.to_string ocaml_version in 119 let pin_cmds = match Local_repo.find_for_packages ~local_repos:config.local_repos odoc_packages with 120 | Some (_, matched) -> 121 let local_mount = "/home/opam/local/odoc" in 122 let from_local = List.map (fun pkg -> 123 Printf.sprintf "opam pin add -yn %s %s" pkg local_mount 124 ) matched in 125 let from_git = List.filter_map (fun pkg -> 126 if List.mem pkg matched then None 127 else Some (Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch) 128 ) odoc_packages in 129 from_local @ from_git 130 | None -> 131 List.map (fun pkg -> 132 Printf.sprintf "opam pin add -yn %s %s#%s" pkg repo branch 133 ) odoc_packages 134 in 135 let compiler_cmds = if needs_compiler then [ Printf.sprintf "opam install -y %s" compiler_pkg ] else [] in 136 String.concat " && " 137 (compiler_cmds 138 @ pin_cmds 139 @ [ "opam install -y odoc"; 140 "eval $(opam env) && which odoc && odoc --version" ]) 141 142(** Check if odoc layer exists for this OCaml version *) 143let odoc_exists ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~(compiler_layers : string list) : bool = 144 Sys.file_exists (odoc_layer_path ~config ~ocaml_version ~compiler_layers) 145 146(** Get the hash/name for the odoc layer *) 147let get_odoc_hash ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~(compiler_layers : string list) : string = 148 odoc_layer_name ~config ~ocaml_version ~compiler_layers 149 150(** Check if odoc is available in the odoc layer *) 151let has_odoc ~(config : Config.t) ~(ocaml_version : OpamPackage.t) ~(compiler_layers : string list) : bool = 152 let odoc_path = Path.(odoc_layer_path ~config ~ocaml_version ~compiler_layers / "fs" / "home" / "opam" / ".opam" / "default" / "bin" / "odoc") in 153 Sys.file_exists odoc_path