package opam_bin_lib
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
The opam-bin tool is a simple framework to use `opam` with binary packages
Install
dune-project
Dependency
ocamlpro.github.io
Readme
Changelog
LGPL-2.1-only WITH OCaml-LGPL-linking-exception License
Edit opam file
Versions (5)
Authors
Maintainers
Sources
v1.2.0.tar.gz
sha256=1d061f53870a3212133c6713207e040fca9c76a1b81696049599f1a84b44e76c
doc/src/opam_bin_lib/commandPreBuild.ml.html
Source file commandPreBuild.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361(**************************************************************************) (* *) (* Copyright 2020 OCamlPro & Origin Labs *) (* *) (* All rights reserved. This file is distributed under the terms of the *) (* GNU Lesser General Public License version 2.1, with the special *) (* exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) open Ez_opam_file.V1 open Ezcmd.TYPES open Ez_file.V1 open EzFile.OP open EzConfig.OP open OpamParserTypes.FullPos module OpamParser = OpamParser.FullPos let cmd_name = "pre-build" let cache_file ~cache ~md5 = cache // "md5" // String.sub md5 0 2 // md5 let check_cache_file ~cache ~md5 = let file = cache_file ~cache ~md5 in if Sys.file_exists file then Some file else None let find_archive_in_cache ~repo ~md5 = match check_cache_file ~cache:Globals.opam_cache_dir ~md5 with | Some file -> Some file | None -> match check_cache_file ~cache:Globals.opambin_cache_dir ~md5 with | Some file -> Some file | None -> ignore repo; (* TODO: lookup repo specific caches ? (* We should read .opam/repos-config to get the URL of the repository: ``` repositories: [ "default" {"file:///home/---/GIT/opam-repository-relocatable"} "local-bin" {"file:///home/---/.opam/opam-bin/store/repo"} ] ``` together with .opam/repo/XXX/repo: ``` opam-version: "2.0" archive-mirrors: "../../cache" ``` *) match check_cache_file ~cache:(repo // "cache") ~md5 with | Some file -> Some file | None -> match OpamParser.file (repo // "repo") with | exception _ -> None | Some opam -> let cache = ref None in List.iter (function | Variable ( _, "archive-mirrors" , String ( _, v ) ) -> cache := v ) opam.file_contents ; match !cache with | None -> None | Some cache -> *) None let check_cached_binary_archive ~nvo ~version ~repo ~package = Misc.global_log ~nvo "found binary package in repo %s" repo; let package_dir = repo // "packages" // package // version in let src = ref None in let md5 = ref None in let opam = OpamParser.file ( package_dir // "opam" ) in List.iter (function | { pelem = Section { section_kind = { pelem = "url"; _} ; section_items ; _ }; _} -> List.iter (function { pelem = Variable ({ pelem = "src"; _}, { pelem = String v; _}); _} -> src := Some v | { pelem = Variable ({ pelem = "checksum"; _}, { pelem = List { pelem = [{ pelem = String v; _} ]; _}; _}); _} -> assert ( EzString.starts_with v ~prefix:"md5=" ); let len = String.length v in md5 := Some ( String.sub v 4 (len-4) ) | _ -> () ) section_items.pelem | _ -> () ) opam.file_contents ; let binary_archive = match !md5 with | None -> Misc.global_log ~nvo "url.checksum.md5 not found"; None | Some md5 -> match find_archive_in_cache ~repo ~md5 with | Some binary_archive -> Some binary_archive | None -> match !src with | None -> Printf.eprintf "error: url.src not found\n%!"; exit 2 | Some url -> let temp_dir = Globals.opambin_switch_temp_dir () in let output = temp_dir // md5 in match Misc.wget ~nvo ~url ~output with | None -> Printf.eprintf "Error: could not download archive at %S\n%!" url; exit 2 | Some binary_archive -> let digest = Digest.file binary_archive in assert ( Digest.to_hex digest = md5 ); let cache_dir = Globals.opam_cache_dir // "md5" // String.sub md5 0 2 in let cached_file = cache_dir // md5 in EzFile.make_dir ~p:true cache_dir; Sys.rename binary_archive cached_file ; Some cached_file in EzFile.make_dir Globals.marker_cached ; let install_file = package ^ ".install" in if Sys.file_exists install_file then Sys.remove install_file ; Unix.chdir Globals.marker_cached ; let package_files = package_dir // "files" in let s = EzFile.read_file ( package_files // Globals.package_version ) in EzFile.write_file Globals.package_version s ; begin match EzFile.read_file ( package_files // Globals.package_config ) with | exception _ -> () | s -> EzFile.write_file Globals.package_config s end; begin match binary_archive with | None -> () | Some binary_archive -> Misc.call ~nvo [| "tar" ; "zxf" ; binary_archive |] ; end; true let chop_prefix s ~prefix = if EzString.starts_with s ~prefix then let prefix_len = String.length prefix in let len = String.length s in Some ( String.sub s prefix_len (len - prefix_len) ) else None let chop_suffix s ~suffix = if EzString.ends_with s ~suffix then let suffix_len = String.length suffix in let len = String.length s in Some ( String.sub s 0 (len - suffix_len) ) else None let has_equal_suffix v = let len = String.length v in assert ( len > 0 ); v.[len-1] = '=' let maybe_apply_patch ~nvo ~name ~version = let keep_version = version in let patches_dir = let patches_url = !!Config.patches_url in match chop_prefix patches_url ~prefix:"file://" with | Some s -> s | None -> Globals.opambin_patches_dir in if not ( Sys.file_exists patches_dir ) then Printf.kprintf failwith {| Error: patches dir '%s' does not exist.\n Maybe you didn't use 'opam-bin install patches' ?\n%!|} patches_dir ; let rec iter_package package = let package_dir = patches_dir // "patches" // package in if Sys.file_exists package_dir then let files = Sys.readdir package_dir in Misc.global_log ~nvo "package %s needs relocation" name; let versions = ref [] in let alias = ref None in Array.iter (fun file -> match chop_suffix file ~suffix:".alias" with | Some package -> alias := Some package | None -> match chop_suffix file ~suffix:".patch" with | Some version -> versions := version :: !versions | None -> () ) files; match !alias with | Some package -> Misc.global_log ~nvo "lookup patches for %s instead" package; iter_package package | None -> let versions = Array.of_list !versions in Array.sort VersionCompare.compare versions ; let rec iter version versions current = match versions with | [] -> current | v :: versions -> if has_equal_suffix v then if v = version ^ "=" then Some v else iter version versions current else if VersionCompare.compare version v >= 0 then iter version versions (Some v) else current in match iter version (Array.to_list versions) None with | None -> Misc.global_log_err ~nvo "Package %S is not relocatable, but no patch found for version %S.\n%!" name version; Misc.global_log_err ~nvo "You may have to disable opam-bin to install that version.\n%!"; false | Some version -> let patch = package_dir // version ^ ".patch" in Misc.global_log ~nvo "Using patch %s for %s.%s" patch name keep_version ; Misc.call ~nvo [| "cp" ; "-f"; patch ; Globals.marker_patch |]; Misc.call ~nvo [| "patch" ; "-p1"; "-i"; patch |] ; if Sys.file_exists "reloc-patch.sh" then begin Misc.call ~nvo [| "sh"; "./reloc-patch.sh" |]; end; true else true in iter_package name let cached_binary_archive ~nvo ~name ~version ~depends = if not ( maybe_apply_patch ~nvo ~name ~version ) then `NotRelocatable else let ( source_md5, _depends, _dependset, missing_versions, _opam_file ) = CommandPostInstall.compute_hash ~nvo ~name ~version ~depends () in if missing_versions <> [] then `MissingVersions missing_versions else let version_prefix = Printf.sprintf "%s.%s+bin+%s+" name version source_md5 in if Misc.iter_repos ~cont:(fun x -> x) ( Misc.all_repos () ) (fun ~repo ~package ~version -> if EzString.starts_with version ~prefix:version_prefix then begin check_cached_binary_archive ~nvo ~package ~repo ~version end else false ) then `BinaryArchiveFound else begin Misc.global_log ~nvo "Could not find cached binary package %s" version_prefix ; `NoBinaryArchiveFound source_md5 end let error_on_compile = match Sys.getenv "OPAM_BIN_FORCE" with | exception _ -> false | _ -> true let error_on_non_reloc = match Sys.getenv "OPAM_BIN_RELOC" with | exception _ -> false | _ -> true let action args = match args with | name :: version :: depends :: [] -> let nvo = Some ( Printf.sprintf "%s.%s" name version ) in Misc.log_cmd ~nvo cmd_name args ; let marker_skip = Globals.marker_skip in if not !!Config.enabled || Misc.not_this_switch () then begin Misc.global_log ~nvo "opam-bin is disabled"; EzFile.write_file marker_skip "opam-bin is disabled"; end else let marker_source = Globals.marker_source in let marker_opam = Globals.marker_opam in let marker_patch = Globals.marker_patch in if Sys.file_exists marker_source then begin Misc.global_log ~nvo "removing marker_source"; Sys.remove marker_source ; end; if Sys.file_exists marker_opam then begin Misc.global_log ~nvo "removing marker_opam"; Sys.remove marker_opam ; end; if Sys.file_exists marker_patch then begin Misc.global_log ~nvo "removing marker_patch"; Sys.remove marker_patch ; end; if Sys.file_exists Globals.marker_cached then begin Misc.global_log ~nvo "%s should not already exist!" Globals.marker_cached; exit 2 end else if Sys.file_exists Globals.package_version then begin Misc.global_log ~nvo "already a binary package"; EzFile.write_file marker_source "already-a-binary-package"; end else begin Misc.global_log ~nvo "checking for cached archive"; match cached_binary_archive ~nvo ~name ~version ~depends with | `BinaryArchiveFound -> Misc.global_log ~nvo "found a binary archive in cache"; (* this should have created a marker_cached/ directory *) | `NoBinaryArchiveFound source_md5 -> Misc.global_log ~nvo "no binary archive found."; if error_on_compile then begin Printf.eprintf "Error: opam-bin is configured to prevent compilation.\n%!"; exit 2 end; EzFile.write_file marker_source source_md5 | `MissingVersions missing_versions -> EzFile.write_file marker_skip ( Printf.sprintf "Missing binary deps: %s" ( String.concat " " missing_versions ) ) | `NotRelocatable -> if error_on_non_reloc then begin Printf.eprintf "Error: opam-bin is configured to force relocation.\n%!"; exit 2 end; EzFile.write_file marker_skip "Missing relocation patch for unrelocatable package" end | _ -> Misc.global_log ~nvo:None "unexpected arg."; Printf.eprintf "Unexpected args: usage is '%s %s name version depends cmd...'\n%!" Globals.command cmd_name ; exit 2 let cmd = let args = ref [] in Arg.{ cmd_name ; cmd_action = (fun () -> action !args) ; cmd_args = [ [ "opamfile" ] , Arg.String (fun s -> CommandPostInstall.opamfile_arg := Some s), Ezcmd.info "filename of the opam package description"; [], Anons (fun list -> args := list), Ezcmd.info "args" ]; cmd_man = []; cmd_doc = "(opam hook) Backup the sources before building the package"; }
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>