Merge commit 'ocaml3102'
[ocaml.git] / ocamlbuild / options.ml
blob58e8d0bc61e0a8706af78243e91884ca810d4446
1 (***********************************************************************)
2 (* ocamlbuild *)
3 (* *)
4 (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *)
5 (* *)
6 (* Copyright 2007 Institut National de Recherche en Informatique et *)
7 (* en Automatique. All rights reserved. This file is distributed *)
8 (* under the terms of the Q Public License version 1.0. *)
9 (* *)
10 (***********************************************************************)
12 (* $Id$ *)
13 (* Original author: Nicolas Pouillard *)
15 let version = "ocamlbuild 0.1";;
17 type command_spec = Command.spec
19 open My_std
20 open Arg
21 open Format
22 open Command
24 let entry = ref None
25 let build_dir = ref "_build"
26 let include_dirs = ref []
27 let exclude_dirs = ref []
28 let nothing_should_be_rebuilt = ref false
29 let sanitize = ref true
30 let sanitization_script = ref "sanitize.sh"
31 let hygiene = ref true
32 let ignore_auto = ref true
33 let plugin = ref true
34 let just_plugin = ref false
35 let native_plugin = ref true
36 let make_links = ref true
37 let nostdlib = ref false
38 let use_menhir = ref false
39 let catch_errors = ref true
41 let mk_virtual_solvers =
42 let dir = Ocamlbuild_where.bindir in
43 List.iter begin fun cmd ->
44 let opt = cmd ^ ".opt" in
45 let a_opt = A opt in
46 let a_cmd = A cmd in
47 let search_in_path = memo Command.search_in_path in
48 let solver () =
49 if sys_file_exists !dir then
50 let long = filename_concat !dir cmd in
51 let long_opt = long ^ ".opt" in
52 if sys_file_exists long_opt then A long_opt
53 else if sys_file_exists long then A long
54 else try let _ = search_in_path opt in a_opt
55 with Not_found -> a_cmd
56 else
57 try let _ = search_in_path opt in a_opt
58 with Not_found -> a_cmd
59 in Command.setup_virtual_command_solver (String.uppercase cmd) solver
60 end
62 let () =
63 mk_virtual_solvers
64 ["ocamlc"; "ocamlopt"; "ocamldep"; "ocamldoc";
65 "ocamlyacc"; "menhir"; "ocamllex"; "ocamlmklib"; "ocamlmktop"]
66 let ocamlc = ref (V"OCAMLC")
67 let ocamlopt = ref (V"OCAMLOPT")
68 let ocamldep = ref (V"OCAMLDEP")
69 let ocamldoc = ref (V"OCAMLDOC")
70 let ocamlyacc = ref N
71 let ocamllex = ref (V"OCAMLLEX")
72 let ocamlmklib = ref (V"OCAMLMKLIB")
73 let ocamlmktop = ref (V"OCAMLMKTOP")
74 let ocamlrun = ref N
75 let program_to_execute = ref false
76 let must_clean = ref false
77 let show_documentation = ref false
78 let recursive = ref false
79 let ext_lib = ref "a"
80 let ext_obj = ref "o"
81 let ext_dll = ref "so"
83 let targets_internal = ref []
84 let ocaml_libs_internal = ref []
85 let ocaml_lflags_internal = ref []
86 let ocaml_cflags_internal = ref []
87 let ocaml_ppflags_internal = ref []
88 let ocaml_yaccflags_internal = ref []
89 let ocaml_lexflags_internal = ref []
90 let program_args_internal = ref []
91 let ignore_list_internal = ref []
92 let tags_internal = ref [["quiet"]]
93 let tag_lines_internal = ref []
94 let show_tags_internal = ref []
95 let log_file_internal = ref "_log"
97 let my_include_dirs = ref [[Filename.current_dir_name]]
98 let my_exclude_dirs = ref [[".svn"; "CVS"]]
100 let dummy = "*invalid-dummy-string*";; (* Dummy string for delimiting the latest argument *)
102 (* The JoCaml support will be in a plugin when the plugin system will support
103 * multiple/installed plugins *)
104 let use_jocaml () =
105 ocamlc := A "jocamlc";
106 ocamlopt := A "jocamlopt";
107 ocamldep := A "jocamldep";
108 ocamlyacc := A "jocamlyacc";
109 ocamllex := A "jocamllex";
110 ocamlmklib := A "jocamlmklib";
111 ocamlmktop := A "jocamlmktop";
112 ocamlrun := A "jocamlrun";
115 let add_to rxs x =
116 let xs = Lexers.comma_or_blank_sep_strings (Lexing.from_string x) in
117 rxs := xs :: !rxs
118 let add_to' rxs x =
119 if x <> dummy then
120 rxs := [x] :: !rxs
121 else
123 let set_cmd rcmd = String (fun s -> rcmd := Sh s)
124 let set_build_dir s = make_links := false; build_dir := s
125 let spec =
126 Arg.align
128 "-version", Unit (fun () -> print_endline version; raise Exit_OK), " Display the version";
129 "-quiet", Unit (fun () -> Log.level := 0), " Make as quiet as possible";
130 "-verbose", Int (fun i -> Log.level := i + 2), "<level> Set the verbosity level";
131 "-documentation", Set show_documentation, " Show rules and flags";
132 "-log", Set_string log_file_internal, "<file> Set log file";
133 "-no-log", Unit (fun () -> log_file_internal := ""), " No log file";
134 "-clean", Set must_clean, " Remove build directory and other files, then exit";
135 "-r", Set recursive, " Traverse directories by default (true: traverse)";
137 "-I", String (add_to' my_include_dirs), "<path> Add to include directories";
138 "-Is", String (add_to my_include_dirs), "<path,...> (same as above, but accepts a (comma or blank)-separated list)";
139 "-X", String (add_to' my_exclude_dirs), "<path> Directory to ignore";
140 "-Xs", String (add_to my_exclude_dirs), "<path,...> (idem)";
142 "-lib", String (add_to' ocaml_libs_internal), "<flag> Link to this ocaml library";
143 "-libs", String (add_to ocaml_libs_internal), "<flag,...> (idem)";
144 "-lflag", String (add_to' ocaml_lflags_internal), "<flag> Add to ocamlc link flags";
145 "-lflags", String (add_to ocaml_lflags_internal), "<flag,...> (idem)";
146 "-cflag", String (add_to' ocaml_cflags_internal), "<flag> Add to ocamlc compile flags";
147 "-cflags", String (add_to ocaml_cflags_internal), "<flag,...> (idem)";
148 "-yaccflag", String (add_to' ocaml_yaccflags_internal), "<flag> Add to ocamlyacc flags";
149 "-yaccflags", String (add_to ocaml_yaccflags_internal), "<flag,...> (idem)";
150 "-lexflag", String (add_to' ocaml_lexflags_internal), "<flag> Add to ocamllex flags";
151 "-lexflags", String (add_to ocaml_lexflags_internal), "<flag,...> (idem)";
152 "-ppflag", String (add_to' ocaml_ppflags_internal), "<flag> Add to ocaml preprocessing flags";
153 "-pp", String (add_to ocaml_ppflags_internal), "<flag,...> (idem)";
154 "-tag", String (add_to' tags_internal), "<tag> Add to default tags";
155 "-tags", String (add_to tags_internal), "<tag,...> (idem)";
156 "-tag-line", String (add_to' tag_lines_internal), "<tag> Use this line of tags (as in _tags)";
157 "-show-tags", String (add_to' show_tags_internal), "<path> Show tags that applies on that pathname";
159 "-ignore", String (add_to ignore_list_internal), "<module,...> Don't try to build these modules";
160 "-no-links", Clear make_links, " Don't make links of produced final targets";
161 "-no-skip", Clear ignore_auto, " Don't skip modules that are requested by ocamldep but cannot be built";
162 "-no-hygiene", Clear hygiene, " Don't apply sanity-check rules";
163 "-no-plugin", Clear plugin, " Don't build myocamlbuild.ml";
164 "-no-stdlib", Set nostdlib, " Don't ignore stdlib modules";
165 "-dont-catch-errors", Clear catch_errors, " Don't catch and display exceptions (useful to display the call stack)";
166 "-just-plugin", Set just_plugin, " Just build myocamlbuild.ml";
167 "-byte-plugin", Clear native_plugin, " Don't use a native plugin but bytecode";
168 "-sanitization-script", Set_string sanitization_script, " Change the file name for the generated sanitization script";
169 "-no-sanitize", Clear sanitize, " Do not generate sanitization script";
170 "-nothing-should-be-rebuilt", Set nothing_should_be_rebuilt, " Fail if something needs to be rebuilt";
171 "-classic-display", Set Log.classic_display, " Display executed commands the old-fashioned way";
172 "-use-menhir", Set use_menhir, " Use menhir instead of ocamlyacc";
173 "-use-jocaml", Unit use_jocaml, " Use jocaml compilers instead of ocaml ones";
175 "-j", Set_int Command.jobs, "<N> Allow N jobs at once (0 for unlimited)";
177 "-build-dir", String set_build_dir, "<path> Set build directory (implies no-links)";
178 "-install-lib-dir", Set_string Ocamlbuild_where.libdir, "<path> Set the install library directory";
179 "-install-bin-dir", Set_string Ocamlbuild_where.bindir, "<path> Set the install binary directory";
180 "-where", Unit (fun () -> print_endline !Ocamlbuild_where.libdir; raise Exit_OK), " Display the install library directory";
182 "-ocamlc", set_cmd ocamlc, "<command> Set the OCaml bytecode compiler";
183 "-ocamlopt", set_cmd ocamlopt, "<command> Set the OCaml native compiler";
184 "-ocamldep", set_cmd ocamldep, "<command> Set the OCaml dependency tool";
185 "-ocamlyacc", set_cmd ocamlyacc, "<command> Set the ocamlyacc tool";
186 "-menhir", set_cmd ocamlyacc, "<command> Set the menhir tool (use it after -use-menhir)";
187 "-ocamllex", set_cmd ocamllex, "<command> Set the ocamllex tool";
188 (* Not set since we perhaps want to replace ocamlmklib *)
189 (* "-ocamlmklib", set_cmd ocamlmklib, "<command> Set the ocamlmklib tool"; *)
190 "-ocamlmktop", set_cmd ocamlmklib, "<command> Set the ocamlmktop tool";
191 "-ocamlrun", set_cmd ocamlrun, "<command> Set the ocamlrun tool";
193 "--", Rest (fun x -> program_to_execute := true; add_to' program_args_internal x),
194 " Stop argument processing, remaining arguments are given to the user program";
197 let targets = ref []
198 let ocaml_libs = ref []
199 let ocaml_lflags = ref []
200 let ocaml_cflags = ref []
201 let ocaml_ppflags = ref []
202 let ocaml_yaccflags = ref []
203 let ocaml_lexflags = ref []
204 let program_args = ref []
205 let ignore_list = ref []
206 let tags = ref []
207 let tag_lines = ref []
208 let show_tags = ref []
210 let init () =
211 let anon_fun = add_to' targets_internal in
212 let usage_msg = sprintf "Usage %s [options] <target>" Sys.argv.(0) in
213 let argv' = Array.concat [Sys.argv; [|dummy|]] in
214 parse_argv argv' spec anon_fun usage_msg;
215 Shell.mkdir_p !build_dir;
217 let () =
218 let log = !log_file_internal in
219 if log = "" then Log.init None
220 else if not (Filename.is_implicit log) then
221 failwith
222 (sprintf "Bad log file name: the file name must be implicit (not %S)" log)
223 else
224 let log = filename_concat !build_dir log in
225 Shell.mkdir_p (Filename.dirname log);
226 Shell.rm_f log;
227 let log = if !Log.level > 0 then Some log else None in
228 Log.init log
231 let reorder x y = x := !x @ (List.concat (List.rev !y)) in
232 reorder targets targets_internal;
233 reorder ocaml_libs ocaml_libs_internal;
234 reorder ocaml_cflags ocaml_cflags_internal;
235 reorder ocaml_lflags ocaml_lflags_internal;
236 reorder ocaml_ppflags ocaml_ppflags_internal;
237 reorder ocaml_yaccflags ocaml_yaccflags_internal;
238 reorder ocaml_lexflags ocaml_lexflags_internal;
239 reorder program_args program_args_internal;
240 reorder tags tags_internal;
241 reorder tag_lines tag_lines_internal;
242 reorder ignore_list ignore_list_internal;
243 reorder show_tags show_tags_internal;
245 let check_dir dir =
246 if Filename.is_implicit dir then
247 sys_file_exists dir
248 else
249 failwith
250 (sprintf "Included or excluded directories must be implicit (not %S)" dir)
252 let dir_reorder my dir =
253 let d = !dir in
254 reorder dir my;
255 dir := List.filter check_dir (!dir @ d)
257 dir_reorder my_include_dirs include_dirs;
258 dir_reorder my_exclude_dirs exclude_dirs;
260 ignore_list := List.map String.capitalize !ignore_list