7 let len = String.length string in
14 try String.index_from string curr char
15 with Not_found -> len in
16 String.sub string curr (next - curr) :: loop (succ next)
22 let len = String.length string in
27 match String.unsafe_get string (pred curr) with
28 | ' '|'\n'|'\r'|'\t' -> loop (pred curr)
29 | _ when curr = len -> string
30 | _ -> String.sub string 0 curr
37 let (//) = Filename.concat
45 Pervasives.prerr_endline
46 ("File.rm: " ^ Printexc.to_string exn);
49 = fun ?(prefix="tmp") ?(suffix="tmp") fct ->
50 let (file, chan) = Filename.open_temp_file prefix suffix in
55 try let t = fct ~file ~chan in clean (); t
56 with exn -> clean (); raise exn
61 { close : unit -> unit
62 ; format : 'a. ('a, Pervasives.out_channel, unit) format -> 'a
67 { close = Pervasives.ignore
68 ; format = (fun format -> Printf.ifprintf Pervasives.stderr format)
71 let chan = Pervasives.open_out file in
72 { close = (fun _ -> Pervasives.close_out chan)
73 ; format = (fun format -> Printf.fprintf chan format)
81 match Sys.os_type with
88 try split (Sys.getenv name)
93 try Some (Sys.getenv name)
94 with Not_found -> None
102 let self = Sys.argv.(0)
103 let c = ref (self^".h")
104 and caml = ref (self^".ml")
105 and camlpp = ref (self^".mlp")
106 and make = ref (self^".make")
107 and log = ref (self^".log")
119 and caml = !Param.caml
120 and camlpp = !Param.camlpp
121 and make = !Param.make
122 and log = !Param.log in
125 and caml = Out.t caml
126 and camlpp = Out.t camlpp
127 and make = Out.t make
128 and c_def = String.copy c in
129 for i = 0 to pred (String.length c_def)
130 do match String.unsafe_get c_def i with
131 | 'a'..'z' | 'A'..'Z' -> ()
132 | _ -> String.unsafe_set c_def i '_'
140 if Sys.file_exists log
142 fct {c=c; caml=caml; camlpp=camlpp; make=make; log=log};
161 = fun ~glob:{Glob.c=c; caml=caml; camlpp=camlpp; make=make} name bool ->
167 c .Out.format "#define %s\n" name;
168 caml .Out.format "let _%s = true\n" name;
169 camlpp .Out.format "#let %s = true\n" name;
170 make .Out.format "%s := true\n" name
172 c .Out.format "#undef %s\n" name;
173 caml .Out.format "let _%s = false\n" name;
174 camlpp .Out.format "#let _%s = false\n" name;
175 make .Out.format "%s := \n" name
185 = fun ~glob:{Glob.log=log} string ->
189 let log = Pervasives.open_out_gen
190 [Open_wronly; Open_append; Open_creat; Open_text] 0o660 log in
191 Pervasives.output_string log string;
192 Pervasives.close_out log;
200 Log.t ~glob (Printf.sprintf "$ %s\n" string);
201 match glob.Glob.log with
202 | "" -> 0 = Sys.command string
205 (fun string -> 0 = Sys.command string)
207 string (Filename.quote log))
208 let buffer_size = ref 2048
213 Log.t ~glob (Printf.sprintf "$ %s\n" string);
216 let size = !buffer_size in
217 let chan = Unix.open_process_in string
218 and buf = Buffer.create size
219 and string = String.create size
222 read := Pervasives.input chan string 0 size;
223 Buffer.add_substring buf string 0 !read
225 match Unix.close_process_in chan with
226 | Unix.WEXITED 0 -> Buffer.contents buf
227 | Unix.WEXITED int -> ""
229 | Unix.WSTOPPED int ->
232 "command received signal %i: %s"
234 match glob.Glob.log with
238 (fun string -> sh string)
239 "{ %s ; } 2>&1 | tee -a %s"
240 string (Filename.quote log))
246 let ocamlc = ref "ocamlfind ocamlc"
247 and ext_obj = ref ".o"
248 and os_type = ref Sys.os_type
249 and ccomp_type = ref "cc"
260 (fun dir -> {inc=dir//"include"; lib=dir//"lib"})
276 [ List.map (fun dir -> {inc=dir; lib=dir//".."//"lib"})
277 (Env.list "C_INCLUDE_PATH")
278 ; List.map (fun dir -> {inc=dir//".." //"include"; lib=dir})
279 (Env.list "LIBRARY_PATH")
284 Log.t ~glob (Printf.sprintf "# searching for %s .. " h);
288 Log.t ~glob (Printf.sprintf "found NOTHING; \
289 you may use environment variables: \
290 C_INCLUDE_PATH and LIBRARY_PATH\n");
292 | {inc=inc; lib=lib}::list ->
293 match Sys.file_exists (inc//h) with
296 Log.t ~glob (Printf.sprintf "found include:%s lib:%s\n" inc lib);
297 Some {inc=inc; lib=lib}
305 = fun ~glob ~prefix ~default ->
308 ( Env.list (prefix ^ "_CFLAGS")
309 , Env.list (prefix ^ "_LIBS")
311 | (_::_ as opt), (_::_ as lib) -> (opt, lib)
313 let opt, lib = default () in
315 | (_::_ as opt), [] -> (opt, lib)
316 | [] , (_::_ as lib) -> (opt, lib)
317 | [] , [] -> (opt, lib)
318 | _ -> assert false in
319 let {Glob.make} = glob in
320 make.Out.format "%s_CFLAGS := %s\n" prefix (String.concat " " inc);
321 make.Out.format "%s_LIBS := %s\n" prefix (String.concat " " lib);
328 File.tmp ~prefix: "configure_ml_" ~suffix: ".ml"
330 Pervasives.output_string chan string;
331 Pervasives.close_out chan;
334 File.rm (Filename.chop_extension file ^ ".cmi");
335 File.rm (Filename.chop_extension file ^ ".cmo");
336 File.rm (Filename.chop_extension file ^ ".byte");
338 try let t = fct ~ml:file in clean (); t
339 with exn -> clean (); raise exn
346 File.tmp ~prefix: "configure_c_" ~suffix: ".c"
348 Pervasives.output_string chan string;
349 Pervasives.close_out chan;
352 File.rm (Filename.chop_extension file ^ !Param.ext_obj);
354 try let t = fct ~c:file in clean (); t
355 with exn -> clean (); raise exn
359 = fun ~glob (opt, lib) c ->
361 external t : unit -> unit = \"t\"\n\
365 (fun ~c -> Shell.t ~glob
366 "cd %s && %s -o %s -verbose -custom %s %s %s %s"
367 (Filename.quote (Filename.dirname c))
369 (Filename.quote ((Filename.chop_extension ml) ^ ".byte"))
370 (String.concat " " (List.map (fun t -> Printf.sprintf "-ccopt %s" (Filename.quote t)) opt))
371 (String.concat " " (List.map (fun t -> Printf.sprintf "-cclib %s" (Filename.quote t)) lib))
373 (Filename.quote ml)))
378 = fun ~glob ?(enable=true) ?(required=true) ~name ~macro test ->
379 Log.t ~glob (Printf.sprintf "# checking %s\n" name);
380 Trace.format "checking %s %!" name;
381 let line = (String.make (35 - String.length name) '.') in
384 (match try Some (test ~glob)
385 with exn -> None with
387 Trace.format "%s available\n%!" line;
388 Emit.bool ~glob macro true;
391 Trace.format "%s unavailable" line;
392 Emit.bool ~glob macro false;
394 then Trace.format " (required)\n%!"
395 else Trace.format "\n%!";
399 Trace.format "%s disabled\n%!" line;
400 Emit.bool ~glob macro enable;
411 | "false" -> t := false
412 | "true" -> t := true
413 | _ -> assert false )
421 ( ["auto"; "true"; "false"]
423 | "auto" -> t := None
424 | "false" -> t := Some false
425 | "true" -> t := Some true
426 | _ -> assert false )
442 ( ["auto"; "dynamic"; "static"]
444 | "auto" -> t := `Auto
445 | "static" -> t := `Static
446 | "dynamic" -> t := `Dynamic
452 | `Static -> "static"
453 | `Dynamic -> "dynamic"
457 let mode : Mode.t ref = ref `Auto
462 = fun ~glob:{Glob.make} ->
463 match !Param.mode with
464 | `Auto -> make.Out.format "export LINKING_MODE := \n"
465 | `Static -> make.Out.format "export LINKING_MODE := static\n"
466 | `Dynamic -> make.Out.format "export LINKING_MODE := dynamic\n"
479 let bool : t ref = ref false
484 = fun ~glob:{Glob.make} ->
485 match !Param.bool with
486 | true -> make.Out.format "export DEBUG := true\n";
487 | false -> make.Out.format "export DEBUG := \n";
493 [ "--debug" , Arg.unit Debug.Param.bool , Printf.sprintf " activate debug (DEFAULT: %s)" (Debug.string !Debug.Param.bool)
494 ; "--link-type" , Link.Mode.Arg.t Link.Param.mode , Printf.sprintf " link mode (DEFAULT: %s)" (Link.Mode.string !Link.Param.mode)
495 ; "--ocamlc" , Arg.Set_string Compile.Param.ocamlc , Printf.sprintf "<command> ocamlc command (DEFAULT: %s)" !Compile.Param.ocamlc
496 ; "--ext-obj" , Arg.Set_string Compile.Param.ext_obj , Printf.sprintf "<ext> C object files extension (DEFAULT: %s)" !Compile.Param.ext_obj
497 ; "--os-type" , Arg.Set_string Compile.Param.os_type , Printf.sprintf "<name> type of the target os (DEFAULT: %s)" !Compile.Param.os_type
498 ; "--ccomp-type", Arg.Set_string Compile.Param.ccomp_type, Printf.sprintf "<name> C compiler type (DEFAULT: %s)" !Compile.Param.ccomp_type
499 ; "--c" , Arg.Set_string Glob.Param.c , Printf.sprintf "<file> C output (DEFAULT: %s)" !Glob.Param.c
500 ; "--caml" , Arg.Set_string Glob.Param.caml , Printf.sprintf "<file> OCaml output (DEFAULT: %s)" !Glob.Param.caml
501 ; "--camlpp" , Arg.Set_string Glob.Param.camlpp , Printf.sprintf "<file> OCaml preprocessor output (DEFAULT: %s)" !Glob.Param.camlpp
502 ; "--make" , Arg.Set_string Glob.Param.make , Printf.sprintf "<file> Makefile output (DEFAULT: %s)" !Glob.Param.make
503 ; "--log" , Arg.Set_string Glob.Param.log , Printf.sprintf "<file> shell log output (DEFAULT: %s)" !Glob.Param.log
507 = fun ?(env="") ~argv fct ->
513 "check prerequisites and generate %s.* files\n\
515 \ C_INCLUDE_PATH colon-separated paths to search C headers\n\
516 \ LIBRARY_PATH colon-separated paths to search libraries\n\
517 \ <NAME>_CFLAGS compile-time flags for <NAME>\n\
518 \ <NAME>_LIBS link-time flags for <NAME>\n\
520 OPTIONS" Glob.Param.self env);
522 (fun ({Glob.make} as glob) ->