let rec prepare_link tag cmx extensions build =
  let key = (tag, cmx, extensions) in
  let dir = Pathname.dirname cmx in
  let include_dirs = Pathname.include_dirs_of dir in
  let ml = Pathname.update_extensions "ml" cmx in
  let mli = Pathname.update_extensions "mli" cmx in
  let modules =
    List.union
      (if Pathname.exists (ml-.-"depends"then path_dependencies_of ml else [])
      (if Pathname.exists (mli-.-"depends"then path_dependencies_of mli else [])
  in
  if modules <> [] && not (Hashtbl.mem cache_prepare_link key) then
    let () = Hashtbl.add cache_prepare_link key true in
    let modules' = List.map (fun (_, x) -> expand_module include_dirs x extensions) modules in
    List.iter2 begin fun (mandatory, _) result ->
      match mandatory, result with
      | _, Good p -> prepare_link tag p extensions build
      | `mandatory, Bad exn -> if not !Options.ignore_auto then raise exn
      | `just_try, Bad _ -> ()
    end modules (build modules')