configure.ml 10 KB
Newer Older
1
(*
2 3
#use "topfind";;
#require "findlib";;
4
*)
5

6 7
open Printf

8 9
let not_distrib = Sys.file_exists "Makefile.distrib"

10 11 12 13 14 15 16 17 18 19
let usage () =
  print_string "\
Configuration of CDuce.

Usage: ./configure [OPTION]...

Defaults for the options are specified in brackets.

Options:
 --help                display this help and exit
20
 --bytecode            compile CDuce in bytecode instead of native
21 22 23 24 25 26 27 28

Optional features:
 --with-FEATURE        force support for FEATURE [default: autodetect]
 --without-FEATURE     disable support for FEATURE [default: autodetect]

 Available features:
 ocamlopt              use ocamlopt instead of ocamlc to build CDuce
 pxp_wlex              use wlexers for parsing utf8 with PXP [default: false]
29
 pxp                   support for the PXP XML parser
30 31 32
 expat                 support for the expat XML parser
 curl                  support for the libcurl library
 netclient             support for the netclient library
33
 cgi                   support for the cgi library
34

35
OCaml/CDuce interface:
36
 --mliface=DIR         build the interface with the OCaml sources in DIR
37

38 39 40 41
Installation directories:
 --prefix=PREFIX       install files in PREFIX [/usr/local]
 --bindir=DIR          install user executables in DIR [PREFIX/bin]
 --mandir=DIR          install man documentation in DIR [PREFIX/man]
42 43 44
 --docdir=DIR          install the rest of the doc in DIR [PREFIX/doc/cduce]
";
if not_distrib then print_string "
45 46 47
 --wprefix=WPREFIX     root directory of the web-server [/var/www]
 --cgidir=DIR          install the cgi-bin interpreter in DIR [WPREFIX/cgi-bin]
 --htmldir=DIR         install the website in DIR [WPREFIX/html]
48
 --sessiondir=DIR      store the open sessions of the cgi-bin in DIR
49 50 51
                       [/tmp/cduce_sessions]
"

52
let features =
53 54
  [ "ocamlopt", ref `auto;
    "mliface", ref `auto;
55
    "pxp", ref `auto;
56 57 58
    "expat", ref `auto;
    "curl", ref `auto;
    "netclient", ref `auto;
59
    "cgi", ref `auto;
60
    "pxp_wlex", ref `no ]
61 62

let vars =
63 64 65
  [ "prefix", ref "/usr/local";
    "bindir", ref "";
    "mandir", ref "";
66
    "docdir", ref "";
67 68 69 70 71

    "wprefix", ref "/var/www";
    "cgidir", ref "";
    "htmldir", ref "";

72
    "sessiondir", ref "/tmp/cduce_sessions";
73
    "mliface", ref "";
74
  ]
75

76
let native = ref true
77

78
let src_dirs = ["/usr/src"; "/usr/local/src"; "/tmp"]
79

80 81 82
let fatal s = printf "*** Fatal error: %s\n" s; exit 1
let warning s = printf "* Warning: %s\n" s

83 84 85 86 87 88 89 90 91 92 93
let log s =
  let oc = open_out_gen [ Open_append; Open_creat ] 0o600 "configure.log" in
  output_string oc s;
  output_char oc '\n';
  close_out oc;
  flush stdout

let command s =
  log ("==> " ^ s);
  Sys.command (sprintf "%s 2>> configure.log" s) = 0

94 95 96 97
let start_with s p =
  let ls = String.length s and lp = String.length p in
  if (ls >= lp) && (String.sub s 0 lp = p)
  then Some (String.sub s lp (ls - lp)) else None
98

99 100
let parse_arg s =
  if s = "--help" then (usage (); exit 0)
101
  else if s = "--bytecode" then native := false
102 103 104 105 106 107 108 109 110 111 112 113 114 115
  else
    match start_with s "--with-" with
      | Some f -> (List.assoc f features) := `yes
      | None ->
    match start_with s "--without-" with
      | Some f -> (List.assoc f features) := `no
      | None ->
    let i = String.index s '=' in
    if i < 2 then raise Not_found;
    let n = String.sub s 2 (i - 2) in
    let v = String.sub s (succ i) (String.length s - i - 1) in
    (List.assoc n vars) := v

let () =
116
  print_endline "Configuring CDuce for compilation...\n";
117 118 119 120 121 122
  (try for i = 1 to Array.length Sys.argv - 1 do parse_arg Sys.argv.(i) done
  with Not_found -> usage (); fatal "Incorrect command line");
  (try Sys.remove "configure.log" with Sys_error _ -> ());
  ignore (Sys.command "uname -a >> configure.log")

let print s = print_string s; flush stdout
123 124 125 126

let check_feature f p =
  printf "%s: " f;
  match !(List.assoc f features) with
127
    | `no ->
128
	print "disabled\n"; false
129
    | `yes ->
130
	print "checking... ";
131 132
	if p ()
	then (print "ok\n"; true)
133
	else (print "failed !\n"; fatal "Required feature is not available")
134
    | `auto ->
135
	print "autodetecting... ";
136
	if p ()
137 138 139
	then (print "enabled\n"; true)
	else (print "disabled\n"; false)

140
let native =
141
  check_feature "ocamlopt" (fun () -> command "ocamlfind ocamlopt")
142 143

let check_pkg p () =
144 145 146 147
  try
(*    ignore (Findlib.package_property
      [ (if native then "native" else "bytecode") ]
      p "archive"); *)
148 149
    command
      (sprintf
150
	 "ocamlfind ocaml%s -package %s -linkpkg -o configure.try && rm -f configure.try"
151 152 153
	 (if native then "opt" else "c")
	 p)
  with Not_found -> false
154 155

let need_pkg p =
156
  printf "Checking for package %s... " p; flush stdout;
157
  if not (check_pkg p ())
158 159
  then (print "failed !\n"; fatal "Required package is not available")
  else (print "ok\n")
160

161
let dir ?def d =
162 163
  let s = !(List.assoc d vars) in
  if s <> "" then s
164 165
  else match def with
    | Some x -> x
166 167 168
    | None -> fatal (sprintf "%s cannot be empty" d)


169
let exe = match Sys.os_type with
Karoline Malmkjaer's avatar
Karoline Malmkjaer committed
170
  | "Win32" ->
171
      print "Win32 detected... executable will have .exe extension\n"; ".exe"
172
  | "Cygwin" ->
173
      print "Cygwin detected... executable will have .exe extension\n"; ".exe"
174 175
  | _ -> ""

176
let add_icon = match Sys.os_type with
177 178 179
  | "Win32" | "Cygwin" -> true
  | _ -> false

180
let check_mliface dir =
Karoline Malmkjaer's avatar
Karoline Malmkjaer committed
181
(*  Sys.file_exists (Filename.concat dir "typing/types.ml") *)
182 183 184 185 186 187 188 189 190 191 192
  List.for_all (fun f ->
    Sys.file_exists (Filename.concat dir f))
    [ "typing/types.ml"; "VERSION" ]

let mliface_version dir =
  let ic = open_in (Filename.concat dir "VERSION") in
  let s = input_line ic in
  close_in ic;
  if s < "4" then "3.x"
  else if s < "4.02" then "4.01"
  else "4.02"
193

194
let ocaml_stdlib () =
195 196 197
  if (Sys.command "ocamlc -where > ocaml_stdlib" <> 0) then
    fatal "Can't run ocamlc to get OCaml standard library path";
  let ic = open_in "ocaml_stdlib" in
198 199
  let s = input_line ic in
  close_in ic;
200
  Sys.remove "ocaml_stdlib";
201
  s
202

203
let make_absolute dir =
204
  if Filename.is_relative dir
205 206 207
  then Filename.concat (Sys.getcwd ()) dir
  else dir

208
let ml_interface, mliface_version =
209
  let dir1 = !(List.assoc "mliface" vars) in
210
  let dirs = if dir1 = "" then [] else [ make_absolute dir1 ] in
211
  print "ocaml sources... ";
212
  let rec loop = function
213
    | [] ->
214
	print "not found (the interface will not be built)\n";
215
	None, ""
216
    | d::dirs ->
217
	if check_mliface d then
218 219 220
          let version = mliface_version d in
	  (print ("found: " ^ d ^ ", version " ^ version ^ "\n");
           Some d, version)
221
	else loop dirs
222 223
  in
  loop dirs
224

225
let pxp = check_feature "pxp" (check_pkg "pxp")
226 227
let expat = check_feature "expat" (check_pkg "expat")
let curl = check_feature "curl" (check_pkg "curl")
228
let netclient = check_feature "netclient" (check_pkg "netclient")
229
let cgi = check_feature "cgi" (check_pkg "netcgi2")
230 231 232 233
let pxp_wlex = check_feature "pxp_wlex" (check_pkg "pxp-wlex-utf8")
let prefix = dir "prefix"
let bindir = dir ~def:(prefix^"/bin") "bindir"
let mandir = dir ~def:(prefix^"/man") "mandir"
234
let docdir = dir ~def:(prefix^"/doc/cduce") "docdir"
235 236 237 238 239
let wprefix = dir "wprefix"
let cgidir = dir ~def:(wprefix^"/cgi-bin") "cgidir"
let htmldir = dir ~def:(wprefix^"/html") "htmldir"
let sessiondir = dir "sessiondir"

240 241 242 243 244 245 246 247
let netclient4 =
  let res = 
    netclient &&
      0 =
      (Sys.command "echo 'open Nethttp_client' > test_netclient4.ml &&
		   ocamlfind ocamlc -o test_netclient4 -linkpkg -package \
		    netclient test_netclient4.ml")
  in
248
  ignore (Sys.command "rm -r test_netclient4.ml test_netclient4 test_netclient4.cm*");
249 250
  res

251
let curl,netclient =
252
  match curl,netclient with
253
    | true,true ->
254 255 256 257 258 259 260
	warning "Both netclient and curl are available. Will use curl.";
	true,false
    | false,false ->
	warning "No package for loading external URLs.";
	false,false
    | c,n -> c,n

261
let pxp,expat =
262
  match pxp,expat with
263
    | true,true ->
264
	warning "Both PXP and expat are available. Will build both and use expat by default.";
265
	true,true
266 267 268 269 270
    | false,false ->
	warning "No package for parsing XML documents.";
	false,false
    | c,n -> c,n

271 272
let cgi =
    if not(cgi) then
273
        (warning "No cgi package found: dtd2cduce and the web interface won't be built";
274 275 276 277
        false)
    else true

let required_packages = ["camlp4"; "num"; "pcre"; "ulex"; "netstring"]
278

279 280
let has_forpack =
  print "testing for -for-pack option: ";
Karoline Malmkjaer's avatar
Karoline Malmkjaer committed
281 282 283 284 285 286 287 288
  let comm =
    match Sys.os_type with
      | "Win32" -> "ocamlc -for-pack foo"
      | _ -> "ocamlc -for-pack foo 2> /dev/null" in
    if Sys.command comm = 0 then
      (print "available\n"; true)
    else
      (print "not available\n"; false)
289

Kim Nguyễn's avatar
Kim Nguyễn committed
290 291 292 293 294 295 296 297 298 299 300 301
let has_bin_annot =
  print "testing for -bin-annot option: ";
  let comm =
    match Sys.os_type with
      | "Win32" -> "ocamlc -bin-annot"
      | _ -> "ocamlc -bin-annot 2> /dev/null" in
    if Sys.command comm = 0 then
      (print "available\n"; true)
    else
      (print "not available\n"; false)


302 303 304 305 306 307 308
let has_natdynlink =
  print "testing for native dynlink: ";
  if Sys.command "ocamlopt -o foo dynlink.cmxa && rm -f foo" = 0 then
    (printf "available\n"; true)
  else
    (print "not available\n"; false)

309 310
let () =
  List.iter need_pkg required_packages;
311 312
  if pxp then (
    need_pkg "pxp-engine";
313
    need_pkg "pxp-lex-iso88591";
314 315
    if not pxp_wlex then need_pkg "pxp-lex-utf8";
  );
316

317
  print "Creating Makefile.conf...\n";
318 319 320 321

  let out = open_out "Makefile.conf" in
  fprintf out "# This file has been generated by the configure script\n";
  fprintf out "NATIVE=%b\n" native;
322
  (match ml_interface with
323
    | Some d -> fprintf out "ML_INTERFACE=true\nOCAML_SRC=%s\nML_INTERFACE_VERSION=%s\n" d mliface_version
324
    | None -> fprintf out "ML_INTERFACE=false\n");
325
  fprintf out "PXP=%b\n" pxp;
326 327 328
  fprintf out "EXPAT=%b\n" expat;
  fprintf out "CURL=%b\n" curl;
  fprintf out "NETCLIENT=%b\n" netclient;
329
  fprintf out "NETCLIENT4=%b\n" netclient4;
330
  fprintf out "CGI=%b\n" cgi;
331 332 333
  fprintf out "PXP_WLEX=%b\n" pxp_wlex;
  fprintf out "BINDIR=%s\n" bindir;
  fprintf out "MANDIR=%s\n" mandir;
334
  fprintf out "DOCDIR=%s\n" docdir;
335 336 337 338
  fprintf out "CGI_DIR=%s\n" cgidir;
  fprintf out "HTML_DIR=%s\n" htmldir;
  fprintf out "SESSION_DIR=%s\n" sessiondir;
  fprintf out "EXE=%s\n" exe;
339
  fprintf out "ADDICON=%b\n" add_icon;
340
  fprintf out "PROFILE=false\n";
341
  fprintf out "FORPACK=%b\n" has_forpack;
342
  fprintf out "NATDYNLINK=%b\n" has_natdynlink;
Kim Nguyễn's avatar
Kim Nguyễn committed
343
  fprintf out "BIN_ANNOT=%b\n" has_bin_annot;
344
  close_out out