1 (***********************************************************************)
4 (* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *)
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. *)
10 (***********************************************************************)
13 (* Original author: Nicolas Pouillard *)
15 let version = "ocamlbuild 0.1";;
17 type command_spec
= Command.spec
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
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
47 let search_in_path = memo
Command.search_in_path in
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
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
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")
71 let ocamllex = ref (V
"OCAMLLEX")
72 let ocamlmklib = ref (V
"OCAMLMKLIB")
73 let ocamlmktop = ref (V
"OCAMLMKTOP")
75 let program_to_execute = ref false
76 let must_clean = ref false
77 let show_documentation = ref false
78 let recursive = ref false
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 *)
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";
116 let xs = Lexers.comma_or_blank_sep_strings
(Lexing.from_string x
) in
123 let set_cmd rcmd
= String
(fun s
-> rcmd
:= Sh s
)
124 let set_build_dir s
= make_links := false; build_dir := s
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";
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 []
207 let tag_lines = ref []
208 let show_tags = ref []
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;
218 let log = !log_file_internal in
219 if log = "" then Log.init None
220 else if not
(Filename.is_implicit
log) then
222 (sprintf
"Bad log file name: the file name must be implicit (not %S)" log)
224 let log = filename_concat
!build_dir log in
225 Shell.mkdir_p
(Filename.dirname
log);
227 let log = if !Log.level
> 0 then Some
log else None
in
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;
246 if Filename.is_implicit
dir then
250 (sprintf
"Included or excluded directories must be implicit (not %S)" dir)
252 let dir_reorder my
dir =
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