162 lines
3.5 KiB
OCaml
162 lines
3.5 KiB
OCaml
#load "str.cma";;
|
|
|
|
open StdLabels
|
|
open Printf
|
|
|
|
let ( ^/ ) = Filename.concat
|
|
|
|
(* Topoligically sorted *)
|
|
let modules =
|
|
[ "Import"
|
|
; "Clflags"
|
|
; "Loc"
|
|
; "Sexp"
|
|
; "Sexp_lexer"
|
|
; "Future"
|
|
; "Kind"
|
|
; "Values"
|
|
; "Rule"
|
|
; "Jbuild_interpret"
|
|
; "Jbuild"
|
|
]
|
|
|
|
let lexers = [ "sexp_lexer" ]
|
|
|
|
let path =
|
|
match Sys.getenv "PATH" with
|
|
| exception Not_found -> []
|
|
| s ->
|
|
let sep =
|
|
if Sys.win32 then
|
|
";"
|
|
else
|
|
":"
|
|
in
|
|
Str.split_delim (Str.regexp sep) s
|
|
;;
|
|
|
|
let exe = if Sys.win32 then ".exe" else ""
|
|
|
|
let prog_not_found prog =
|
|
eprintf "Program %s not found in PATH" prog;
|
|
exit 2
|
|
|
|
type mode = Native | Byte
|
|
|
|
let best_prog dir prog =
|
|
let fn = dir ^/ prog ^ ".opt" ^ exe in
|
|
if Sys.file_exists fn then
|
|
Some fn
|
|
else
|
|
let fn = dir ^/ prog ^ exe in
|
|
if Sys.file_exists fn then
|
|
Some fn
|
|
else
|
|
None
|
|
|
|
let find_prog prog =
|
|
let rec search = function
|
|
| [] -> None
|
|
| dir :: rest ->
|
|
match best_prog dir prog with
|
|
| None -> search rest
|
|
| Some fn -> Some (dir, fn)
|
|
in
|
|
search path
|
|
|
|
let get_prog dir prog =
|
|
match best_prog dir prog with
|
|
| None -> prog_not_found prog
|
|
| Some fn -> fn
|
|
|
|
let count_newlines s =
|
|
let newlines = ref 0 in
|
|
String.iter s ~f:(function
|
|
| '\n' -> incr newlines
|
|
| _ -> ());
|
|
!newlines
|
|
|
|
let read_file fn =
|
|
let ic = open_in fn in
|
|
let data = really_input_string ic (in_channel_length ic) in
|
|
close_in ic;
|
|
data
|
|
|
|
let generated_file = "jbuild.ml"
|
|
|
|
let generate_file_with_all_the_sources () =
|
|
let oc = open_out "jbuild.ml" in
|
|
let pos_in_generated_file = ref 1 in
|
|
let pr fmt =
|
|
ksprintf (fun s ->
|
|
output_string oc s;
|
|
output_char oc '\n';
|
|
incr pos_in_generated_file)
|
|
fmt
|
|
in
|
|
let dump fn =
|
|
let s = read_file fn in
|
|
pr "# 1 %S" fn;
|
|
output_string oc s;
|
|
let newlines = count_newlines s in
|
|
let newlines =
|
|
if s <> "" && s.[String.length s - 1] <> '\n' then begin
|
|
output_char oc '\n';
|
|
newlines + 1
|
|
end else
|
|
newlines
|
|
in
|
|
pos_in_generated_file := !pos_in_generated_file + newlines;
|
|
pr "# %d %S" (!pos_in_generated_file + 1) generated_file
|
|
in
|
|
pr "module M : sig end = struct";
|
|
List.iter modules ~f:(fun m ->
|
|
let base = String.uncapitalize m in
|
|
let mli = sprintf "src/%s.mli" base in
|
|
let ml = sprintf "src/%s.ml" base in
|
|
if Sys.file_exists mli then begin
|
|
pr "module %s : sig" m;
|
|
dump mli;
|
|
pr "end = struct";
|
|
dump ml;
|
|
pr "end"
|
|
end else begin
|
|
pr "module %s = struct" m;
|
|
dump ml;
|
|
pr "end"
|
|
end);
|
|
pr "end";
|
|
close_out oc
|
|
|
|
let exec fmt =
|
|
ksprintf (fun cmd ->
|
|
print_endline cmd;
|
|
Sys.command cmd)
|
|
fmt
|
|
|
|
let () =
|
|
let bin_dir, mode, compiler =
|
|
match find_prog "ocamlopt" with
|
|
| Some (bin_dir, prog) -> (bin_dir, Native, prog)
|
|
| None ->
|
|
match find_prog "ocamlc" with
|
|
| Some (bin_dir, prog) -> (bin_dir, Byte, prog)
|
|
| None -> prog_not_found "ocamlc"
|
|
in
|
|
let ocamllex = get_prog bin_dir "ocamllex" in
|
|
List.iter lexers ~f:(fun name ->
|
|
let src = "src" ^/ name ^ ".mll" in
|
|
let dst = "src" ^/ name ^ ".ml" in
|
|
let x = Sys.file_exists dst in
|
|
let n = exec "%s %s" ocamllex src in
|
|
if n <> 0 then exit n;
|
|
if not x then
|
|
at_exit (fun () -> try Sys.remove dst with _ -> ()));
|
|
generate_file_with_all_the_sources ();
|
|
let lib_ext =
|
|
match mode with
|
|
| Native -> "cmxa"
|
|
| Byte -> "cma"
|
|
in
|
|
exit (exec "%s -w -40 -o jbuild unix.%s %s" compiler lib_ext generated_file)
|