diff --git a/src/build_system.ml b/src/build_system.ml index 97336e8c..efa78d5a 100644 --- a/src/build_system.ml +++ b/src/build_system.ml @@ -238,6 +238,22 @@ let create_file_specs t targets rule ~allow_override = module Pre_rule = Build_interpret.Rule +let refresh_targets_timestamps_after_rule_execution t targets = + let missing = + List.fold_left targets ~init:Pset.empty ~f:(fun acc fn -> + match Unix.lstat (Path.to_string fn) with + | exception _ -> Pset.add fn acc + | stat -> + let ts = stat.st_mtime in + Hashtbl.add t.timestamps ~key:fn ~data:ts; + acc) + in + if not (Pset.is_empty missing) then + die "@{Error@}: Rule failed to generate the following targets:\n%s" + (Pset.elements missing + |> List.map ~f:(fun fn -> sprintf "- %s" (Path.to_string fn)) + |> String.concat ~sep:"\n") + let compile_rule t ~all_targets_by_dir ?(allow_override=false) pre_rule = let { Pre_rule. build; targets = target_specs } = pre_rule in let deps = Build_interpret.deps build ~all_targets_by_dir in @@ -296,8 +312,9 @@ let compile_rule t ~all_targets_by_dir ?(allow_override=false) pre_rule = acc || prev_hash <> hash) in if rule_changed || min_timestamp t targets < max_timestamp t all_deps then begin - List.iter targets ~f:(Hashtbl.remove t.timestamps); - Action.exec action + List.iter targets ~f:Path.unlink_no_err; + Action.exec action >>| fun () -> + refresh_targets_timestamps_after_rule_execution t targets end else return () ) in diff --git a/src/path.ml b/src/path.ml index 2fcf38ef..c5030677 100644 --- a/src/path.ml +++ b/src/path.ml @@ -335,6 +335,7 @@ let readdir t = Sys.readdir (to_string t) |> Array.to_list let is_directory t = Sys.is_directory (to_string t) let rmdir t = Unix.rmdir (to_string t) let unlink t = Unix.unlink (to_string t) +let unlink_no_err t = try Unix.unlink (to_string t) with _ -> () let extend_basename t ~suffix = t ^ suffix diff --git a/src/path.mli b/src/path.mli index e29d354f..73541614 100644 --- a/src/path.mli +++ b/src/path.mli @@ -71,3 +71,4 @@ val readdir : t -> string list val is_directory : t -> bool val rmdir : t -> unit val unlink : t -> unit +val unlink_no_err : t -> unit