let proceed () =
Hooks.call_hook Hooks.Before_options;
Options.init ();
if !Options.must_clean then clean ();
Hooks.call_hook Hooks.After_options;
Plugin.execute_plugin_if_needed ();
if !Options.targets = []
&& !Options.show_tags = []
&& not !Options.show_documentation
then raise Exit_silently;
let target_dirs = List.union [] (List.map Pathname.dirname !Options.targets) in
Configuration.parse_string
"<**/*.ml> or <**/*.mli> or <**/*.mlpack> or <**/*.ml.depends>: ocaml\n<**/*.byte>: ocaml, byte, program\n<**/*.odoc>: ocaml, doc\n<**/*.native>: ocaml, native, program\n<**/*.cma>: ocaml, byte, library\n<**/*.cmxa>: ocaml, native, library\n<**/*.cmo>: ocaml, byte\n<**/*.cmi>: ocaml, byte, native\n<**/*.cmx>: ocaml, native\n";
Configuration.tag_any !Options.tags;
if !Options.recursive
|| Sys.file_exists "_tags"
|| Sys.file_exists "myocamlbuild.ml"
then Configuration.tag_any ["traverse"];
List.iter
(fun pkg -> Configuration.tag_any [Param_tags.make "package" pkg])
!Options.ocaml_pkgs;
let newpwd = Sys.getcwd () in
Sys.chdir Pathname.pwd;
let entry_include_dirs = ref [] in
let entry =
Slurp.filter
begin fun path name _ ->
let dir =
if path = Filename.current_dir_name then
None
else
Some path
in
let path_name = path/name in
if name = "_tags" then
ignore (Configuration.parse_file ?dir path_name);
(String.length name > 0 && name.[0] <> '_' && name <> !Options.build_dir && not (List.mem name !Options.exclude_dirs))
&& begin
if path_name <> Filename.current_dir_name && Pathname.is_directory path_name then
let tags = tags_of_pathname path_name in
if Tags.mem "include" tags
|| List.mem path_name !Options.include_dirs then
(entry_include_dirs := path_name :: !entry_include_dirs; true)
else
Tags.mem "traverse" tags
|| List.exists (Pathname.is_prefix path_name) !Options.include_dirs
|| List.exists (Pathname.is_prefix path_name) target_dirs
else true
end
end
(Slurp.slurp Filename.current_dir_name)
in
Hooks.call_hook Hooks.Before_hygiene;
let hygiene_entry =
Slurp.map begin fun path name () ->
let tags = tags_of_pathname (path/name) in
not (Tags.mem "not_hygienic" tags) && not (Tags.mem "precious" tags)
end entry in
if !Options.hygiene then
Fda.inspect hygiene_entry
else
Slurp.force hygiene_entry;
let entry = hygiene_entry in
Hooks.call_hook Hooks.After_hygiene;
Options.include_dirs := Pathname.current_dir_name :: List.rev !entry_include_dirs;
dprintf 3 "include directories are:@ %a" print_string_list !Options.include_dirs;
Options.entry := Some entry;
List.iter Configuration.parse_string !Options.tag_lines;
Hooks.call_hook Hooks.Before_rules;
Ocaml_specific.init ();
Hooks.call_hook Hooks.After_rules;
Param_tags.init ();
Sys.chdir newpwd;
if !Options.show_documentation then begin
show_documentation ();
raise Exit_silently
end;
Digest_cache.init ();
Sys.catch_break true;
show_tags ();
let targets =
List.map begin fun starget ->
let starget = Resource.import starget in
let target = path_and_context_of_string starget in
let ext = Pathname.get_extension starget in
(target, starget, ext)
end !Options.targets in
try
let targets =
List.map begin fun (target, starget, ext) ->
Shell.mkdir_p (Pathname.dirname starget);
let target = Solver.solve_target starget target in
(target, ext)
end targets in
Command.dump_parallel_stats ();
Log.finish ();
Shell.chdir Pathname.pwd;
let call spec = sys_command (Command.string_of_command_spec spec) in
let cmds =
List.fold_right begin fun (target, ext) acc ->
let cmd = !Options.build_dir/target in
let link x =
if !Options.make_links then ignore (call (S [A"ln"; A"-sf"; P x; A Pathname.current_dir_name])) in
match ext with
| "byte" | "native" | "top" ->
link cmd; cmd :: acc
| "html" ->
link (Pathname.dirname cmd); acc
| _ ->
if !Options.program_to_execute then
eprintf "Warning: Won't execute %s whose extension is neither .byte nor .native" cmd;
acc
end targets [] in
if !Options.program_to_execute then
begin
match List.rev cmds with
| [] -> raise (Exit_usage "Using -- requires one target");
| cmd :: rest ->
if rest <> [] then dprintf 0 "Warning: Using -- only run the last target";
let cmd_spec = S [P cmd; atomize !Options.program_args] in
dprintf 3 "Running the user command:@ %a" Pathname.print cmd;
raise (Exit_with_code (call cmd_spec))
end
else
()
with
| Ocaml_dependencies.Circular_dependencies(seen, p) ->
raise
(Exit_build_error
(sbprintf "@[<2>Circular dependencies: %S already seen in@ %a@]@." p pp_l seen))