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
|
open StdLabels
open Printf
(* This program performs version checking of the compiler and switches to the
secondary compiler if necessary. The script should execute in OCaml 4.02! *)
let min_supported_natively = 4, 08, 0
let keep_generated_files =
let anon s = raise (Arg.Bad (sprintf "don't know what to do with %s\n" s)) in
let keep_generated_files = ref false in
Arg.parse
[ "-j", Arg.Int ignore, "JOBS Concurrency"
; "--verbose", Arg.Unit ignore, " Set the display mode"
; "--keep-generated-files", Arg.Set keep_generated_files, " Keep generated files"
; "--debug", Arg.Unit ignore, " Enable various debugging options"
; ( "--force-byte-compilation"
, Arg.Unit ignore
, " Force bytecode compilation even if ocamlopt is available" )
; "--static", Arg.Unit ignore, " Build a static binary"
; "--boot-dir", Arg.String (fun _ -> ()), " set the boot directory"
]
anon
"Usage: ocaml bootstrap.ml <options>\nOptions are:";
!keep_generated_files
;;
let modules = [ "boot/types"; "boot/libs"; "boot/duneboot" ]
let duneboot = ".duneboot"
let prog = duneboot ^ ".exe"
let () =
at_exit (fun () ->
Array.iter (Sys.readdir "boot") ~f:(fun fn ->
let fn = Filename.concat "boot" fn in
if Filename.check_suffix fn ".cmi" || Filename.check_suffix fn ".cmo"
then (
try Sys.remove fn with
| Sys_error _ -> ())));
if not keep_generated_files
then
at_exit (fun () ->
Array.iter (Sys.readdir ".") ~f:(fun fn ->
if
String.length fn >= String.length duneboot
&& String.sub fn ~pos:0 ~len:(String.length duneboot) = duneboot
then (
try Sys.remove fn with
| Sys_error _ -> ())))
;;
let runf fmt =
ksprintf
(fun cmd ->
prerr_endline cmd;
Sys.command cmd)
fmt
;;
let exit_if_non_zero = function
| 0 -> ()
| n -> exit n
;;
let read_file fn =
let ic = open_in_bin fn in
let s = really_input_string ic (in_channel_length ic) in
close_in ic;
s
;;
let () =
let v = Scanf.sscanf Sys.ocaml_version "%d.%d.%d" (fun a b c -> a, b, c) in
let compiler, which =
if v >= min_supported_natively
then "ocamlc", None
else (
let compiler = "ocamlfind -toolchain secondary ocamlc" in
let output_fn, out = Filename.open_temp_file "duneboot" "ocamlfind-output" in
let n = runf "%s 2>%s" compiler output_fn in
let s = read_file output_fn in
close_out out;
prerr_endline s;
if n <> 0 || s <> ""
then (
Format.eprintf
"@[%a@]@."
Format.pp_print_text
(let a, b, _ = min_supported_natively in
sprintf
"The ocamlfind's secondary toolchain does not seem to be correctly installed.\n\
Dune requires OCaml %d.%02d or later to compile.\n\
Please either upgrade your compile or configure a secondary OCaml compiler \
(in opam, this can be done by installing the ocamlfind-secondary package)."
a
b);
exit 2);
compiler, Some "--secondary")
in
exit_if_non_zero
(runf
"%s %s -intf-suffix .dummy -g -o %s -I boot %sunix.cma %s"
compiler
(* Make sure to produce a self-contained binary as dlls tend to cause
issues *)
(if v < (4, 10, 1) then "-custom" else "-output-complete-exe")
prog
(if v >= (5, 0, 0) then "-I +unix " else "")
(List.map modules ~f:(fun m -> m ^ ".ml") |> String.concat ~sep:" "));
let args = List.tl (Array.to_list Sys.argv) in
let args =
match which with
| None -> args
| Some x -> x :: args
in
let args = Filename.concat "." prog :: args in
exit (runf "%s" (String.concat ~sep:" " args))
;;
|