let init () =
  let anon_fun = add_to' targets_internal in
  let usage_msg = sprintf "Usage %s [options] <target>" Sys.argv.(0) in
  let argv' = Array.concat [Sys.argv; [|dummy|]] in
  parse_argv argv' spec anon_fun usage_msg;
  Shell.mkdir_p !build_dir;

  let () =
    let log = !log_file_internal in
    if log = "" then Log.init None
    else if not (Filename.is_implicit log) then
      failwith
        (sprintf "Bad log file name: the file name must be implicit (not %S)" log)
    else
      let log = filename_concat !build_dir log in
      Shell.mkdir_p (Filename.dirname log);
      Shell.rm_f log;
      let log = if !Log.level > 0 then Some log else None in
      Log.init log
  in

  if !use_ocamlfind then begin
    (* TODO: warning message when using an option such as -ocamlc *)
    (* Note that plugins can still modify these variables After_options.
       This design decision can easily be changed. *)

    ocamlc := ocamlfind & A"ocamlc";
    ocamlopt := ocamlfind & A"ocamlopt";
    ocamldep := ocamlfind & A"ocamldep";
    ocamldoc := ocamlfind & A"ocamldoc";
    ocamlmktop := ocamlfind & A"ocamlmktop";
  end;

  let reorder x y = x := !x @ (List.concat (List.rev !y)) in
  reorder targets targets_internal;
  reorder ocaml_libs ocaml_libs_internal;
  reorder ocaml_mods ocaml_mods_internal;
  reorder ocaml_pkgs ocaml_pkgs_internal;
  reorder ocaml_cflags ocaml_cflags_internal;
  reorder ocaml_lflags ocaml_lflags_internal;
  reorder ocaml_ppflags ocaml_ppflags_internal;
  reorder ocaml_yaccflags ocaml_yaccflags_internal;
  reorder ocaml_lexflags ocaml_lexflags_internal;
  reorder program_args program_args_internal;
  reorder tags tags_internal;
  reorder tag_lines tag_lines_internal;
  reorder ignore_list ignore_list_internal;
  reorder show_tags show_tags_internal;

  let check_dir dir =
    if Filename.is_implicit dir then
      sys_file_exists dir
    else
      failwith
        (sprintf "Included or excluded directories must be implicit (not %S)" dir)
  in
  let dir_reorder my dir =
    let d = !dir in
    reorder dir my;
    dir := List.filter check_dir (!dir @ d)
  in
  dir_reorder my_include_dirs include_dirs;
  dir_reorder my_exclude_dirs exclude_dirs;

  ignore_list := List.map String.capitalize !ignore_list