diff --git a/bin/import.ml b/bin/import.ml index 5c46485afc9..bd5266325ab 100644 --- a/bin/import.ml +++ b/bin/import.ml @@ -25,6 +25,7 @@ module Colors = Dune_rules.Colors module Dune_project = Dune_engine.Dune_project module Workspace = Dune_rules.Workspace module Cached_digest = Dune_engine.Cached_digest +module Targets = Dune_engine.Targets module Profile = Dune_rules.Profile module Log = Dune_util.Log module Dune_rpc = Dune_rpc_private diff --git a/bin/print_rules.ml b/bin/print_rules.ml index 76249ffcc26..9d3a60144d2 100644 --- a/bin/print_rules.ml +++ b/bin/print_rules.ml @@ -38,7 +38,7 @@ let print_rule_makefile ppf (rule : Dune_engine.Reflection.Rule.t) = "@[@{%a:%t@}@]@,@<0>\t@{%a@}@,@," (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf p -> Format.pp_print_string ppf (Path.to_string p))) - (List.map ~f:Path.build (Path.Build.Set.to_list rule.targets)) + (Targets.to_list_map rule.targets ~file:Path.build) (fun ppf -> Path.Set.iter rule.expanded_deps ~f:(fun dep -> Format.fprintf ppf "@ %s" (Path.to_string dep))) @@ -55,7 +55,7 @@ let print_rule_sexp ppf (rule : Dune_engine.Reflection.Rule.t) = [ [ ("deps", Dep.Set.encode rule.deps) ; ( "targets" , paths - (Path.Build.Set.to_list rule.targets + (Targets.to_list_map rule.targets ~file:Fun.id |> Path.set_of_build_paths_list) ) ] ; (match rule.context with diff --git a/src/dune_engine/action_builder.ml b/src/dune_engine/action_builder.ml index e5ba292bbd4..a67eb90878d 100644 --- a/src/dune_engine/action_builder.ml +++ b/src/dune_engine/action_builder.ml @@ -131,44 +131,42 @@ let source_tree ~dir = } (* CR-someday amokhov: The set of targets is accumulated using information from - multiple sources by calling [Path.Build.Set.union] and hence occasionally - duplicate declarations of the very same target go unnoticed. I think such - redeclarations are not erroneous but are merely redundant; it seems that it - would be better to rule them out completely. - - Another improvement is to cache [Path.Build.Set.to_list targets] which is - currently performed multiple times on the very same - [Action_builder.With_targets.t]. *) + multiple sources by calling [Targets.combine], which performs set union and + hence duplicate declarations of the very same target can go unnoticed. I + think such redeclarations are not erroneous but are merely redundant; perhaps + we should detect and disallow them. *) module With_targets = struct type nonrec 'a t = { build : 'a t - ; targets : Path.Build.Set.t + ; targets : Targets.t } let map_build t ~f = { t with build = f t.build } - let return x = { build = return x; targets = Path.Build.Set.empty } + let return x = { build = return x; targets = Targets.empty } - let add t ~targets = + let add t ~file_targets = { build = t.build - ; targets = Path.Build.Set.union t.targets (Path.Build.Set.of_list targets) + ; targets = + Targets.combine t.targets + (Targets.Files.create (Path.Build.Set.of_list file_targets)) } let map { build; targets } ~f = { build = map build ~f; targets } let map2 x y ~f = { build = map2 x.build y.build ~f - ; targets = Path.Build.Set.union x.targets y.targets + ; targets = Targets.combine x.targets y.targets } let both x y = { build = both x.build y.build - ; targets = Path.Build.Set.union x.targets y.targets + ; targets = Targets.combine x.targets y.targets } let seq x y = { build = x.build >>> y.build - ; targets = Path.Build.Set.union x.targets y.targets + ; targets = Targets.combine x.targets y.targets } module O = struct @@ -186,48 +184,53 @@ module With_targets = struct | [] -> return [] | xs -> let build, targets = - List.fold_left xs ~init:([], Path.Build.Set.empty) - ~f:(fun (xs, set) x -> - (x.build :: xs, Path.Build.Set.union set x.targets)) + List.fold_left xs ~init:([], Targets.empty) + ~f:(fun (builds, targets) x -> + (x.build :: builds, Targets.combine x.targets targets)) in { build = all (List.rev build); targets } let write_file_dyn ?(perm = Action.File_perm.Normal) fn s = - add ~targets:[ fn ] + add ~file_targets:[ fn ] (let+ s = s in Action.Write_file (fn, perm, s)) let memoize name t = { build = memoize name t.build; targets = t.targets } end -let with_targets build ~targets : _ With_targets.t = - { build; targets = Path.Build.Set.of_list targets } +let with_targets build ~targets : _ With_targets.t = { build; targets } -let with_targets_set build ~targets : _ With_targets.t = { build; targets } +let with_file_targets build ~file_targets : _ With_targets.t = + { build + ; targets = Targets.Files.create (Path.Build.Set.of_list file_targets) + } let with_no_targets build : _ With_targets.t = - { build; targets = Path.Build.Set.empty } + { build; targets = Targets.empty } let write_file ?(perm = Action.File_perm.Normal) fn s = - with_targets ~targets:[ fn ] (return (Action.Write_file (fn, perm, s))) + with_file_targets ~file_targets:[ fn ] + (return (Action.Write_file (fn, perm, s))) let write_file_dyn ?(perm = Action.File_perm.Normal) fn s = - with_targets ~targets:[ fn ] + with_file_targets ~file_targets:[ fn ] (let+ s = s in Action.Write_file (fn, perm, s)) let copy ~src ~dst = - with_targets ~targets:[ dst ] (path src >>> return (Action.Copy (src, dst))) + with_file_targets ~file_targets:[ dst ] + (path src >>> return (Action.Copy (src, dst))) let copy_and_add_line_directive ~src ~dst = - with_targets ~targets:[ dst ] + with_file_targets ~file_targets:[ dst ] (path src >>> return (Action.Copy_and_add_line_directive (src, dst))) let symlink ~src ~dst = - with_targets ~targets:[ dst ] (path src >>> return (Action.Symlink (src, dst))) + with_file_targets ~file_targets:[ dst ] + (path src >>> return (Action.Symlink (src, dst))) let create_file ?(perm = Action.File_perm.Normal) fn = - with_targets ~targets:[ fn ] + with_file_targets ~file_targets:[ fn ] (return (Action.Redirect_out (Stdout, fn, perm, Action.empty))) let progn ts = diff --git a/src/dune_engine/action_builder.mli b/src/dune_engine/action_builder.mli index 9705b000dfc..05dfceaf641 100644 --- a/src/dune_engine/action_builder.mli +++ b/src/dune_engine/action_builder.mli @@ -10,14 +10,14 @@ module With_targets : sig type nonrec 'a t = { build : 'a t - ; targets : Path.Build.Set.t + ; targets : Targets.t } val map_build : 'a t -> f:('a build -> 'b build) -> 'b t val return : 'a -> 'a t - val add : 'a t -> targets:Path.Build.t list -> 'a t + val add : 'a t -> file_targets:Path.Build.t list -> 'a t val map : 'a t -> f:('a -> 'b) -> 'b t @@ -42,12 +42,13 @@ module With_targets : sig end with type 'a build := 'a t -(** Add a set of targets to an action builder, turning a target-less - [Action_builder.t] into [Action_builder.With_targets.t]. *) -val with_targets : 'a t -> targets:Path.Build.t list -> 'a With_targets.t +(** Add targets to an action builder, turning a target-less [Action_builder.t] + into [Action_builder.With_targets.t]. *) +val with_targets : 'a t -> targets:Targets.t -> 'a With_targets.t -(** [with_targets_set] is like [with_targets] but [targets] is a set *) -val with_targets_set : 'a t -> targets:Path.Build.Set.t -> 'a With_targets.t +(** Like [with_targets] but specifies a list of file targets. *) +val with_file_targets : + 'a t -> file_targets:Path.Build.t list -> 'a With_targets.t (** Create a value of [With_targets.t] with the empty set of targets. *) val with_no_targets : 'a t -> 'a With_targets.t diff --git a/src/dune_engine/action_exec.ml b/src/dune_engine/action_exec.ml index 278c6b230c2..47a0ff02653 100644 --- a/src/dune_engine/action_exec.ml +++ b/src/dune_engine/action_exec.ml @@ -71,7 +71,7 @@ type done_or_more_deps = | Need_more_deps of (DAP.Dependency.Set.t * Dynamic_dep.Set.t) type exec_context = - { targets : Path.Build.Set.t + { targets : Targets.t ; context : Build_context.t option ; purpose : Process.purpose ; rule_loc : Loc.t @@ -127,8 +127,7 @@ let exec_run_dynamic_client ~ectx ~eenv prog args = let to_relative path = path |> Stdune.Path.build |> Stdune.Path.reach ~from:eenv.working_dir in - Stdune.Path.Build.Set.to_list ectx.targets - |> String.Set.of_list_map ~f:to_relative + Targets.to_list_map ectx.targets ~file:to_relative |> String.Set.of_list in DAP.Run_arguments. { prepared_dependencies = eenv.prepared_dependencies; targets } diff --git a/src/dune_engine/action_exec.mli b/src/dune_engine/action_exec.mli index 02dc80049f9..24239d3e32b 100644 --- a/src/dune_engine/action_exec.mli +++ b/src/dune_engine/action_exec.mli @@ -30,7 +30,7 @@ end (** [root] should be the root of the current build context, or the root of the sandbox if the action is sandboxed. *) val exec : - targets:Path.Build.Set.t + targets:Targets.t -> root:Path.t -> context:Build_context.t option -> env:Env.t diff --git a/src/dune_engine/build_system.ml b/src/dune_engine/build_system.ml index b3faab0683b..65a66c78223 100644 --- a/src/dune_engine/build_system.ml +++ b/src/dune_engine/build_system.ml @@ -520,7 +520,8 @@ let () = Path.Build.Set.iter fns ~f:(fun p -> Path.unlink_no_err (Path.build p))) let compute_target_digests targets = - Option.List.traverse (Path.Build.Set.to_list targets) ~f:(fun target -> + Option.List.traverse (Targets.to_list_map targets ~file:Fun.id) + ~f:(fun target -> Cached_digest.build_file target |> Cached_digest.Digest_result.to_option |> Option.map ~f:(fun digest -> (target, digest))) @@ -535,15 +536,15 @@ let compute_target_digests_or_raise_error exec_params ~loc targets = (* FIXME: searching the dune version for each single target seems way suboptimal. This information could probably be stored in rules directly. *) - if Path.Build.Set.is_empty targets then + if Targets.is_empty targets then false else Execution_parameters.should_remove_write_permissions_on_generated_files exec_params in let good, missing, errors = - Path.Build.Set.fold targets ~init:([], [], []) - ~f:(fun target (good, missing, errors) -> + Targets.fold targets ~init:([], [], []) + ~file:(fun target (good, missing, errors) -> let expected_syscall_path = Path.to_string (Path.build target) in match Cached_digest.refresh ~remove_write_permissions target with | Ok digest -> ((target, digest) :: good, missing, errors) @@ -773,13 +774,13 @@ end = struct we try to sandbox this. *) ~sandbox:Sandbox_config.no_sandboxing ~context:None ~info:(Source_file_copy path) - ~targets:(Path.Build.Set.singleton ctx_path) + ~targets:(Targets.File.create ctx_path) build) let compile_rules ~dir ~source_dirs rules = List.concat_map rules ~f:(fun rule -> assert (Path.Build.( = ) dir rule.Rule.dir); - Path.Build.Set.to_list_map rule.targets ~f:(fun target -> + Targets.to_list_map rule.targets ~file:(fun target -> if String.Set.mem source_dirs (Path.Build.basename target) then report_rule_src_dir_conflict dir target rule else @@ -851,8 +852,9 @@ end = struct (* All targets are in [dir] and we know it correspond to a directory of a build context since there are source files to copy, so this call can't fail. *) - Path.Build.Set.to_list rule.targets - |> Path.Source.Set.of_list_map ~f:Path.Build.drop_build_context_exn + Targets.to_list_map rule.targets + ~file:Path.Build.drop_build_context_exn + |> Path.Source.Set.of_list in if Path.Source.Set.is_subset source_files_for_targets ~of_:to_copy then @@ -1020,10 +1022,10 @@ end = struct match mode with | Promote { only = None; _ } | Ignore_source_files -> - Path.Build.Set.union targets acc_ignored + Path.Build.Set.union (Targets.files targets) acc_ignored | Promote { only = Some pred; _ } -> let to_ignore = - Path.Build.Set.filter targets ~f:(fun target -> + Path.Build.Set.filter (Targets.files targets) ~f:(fun target -> Predicate_lang.Glob.exec pred (Path.reach (Path.build target) ~from:(Path.build dir)) ~standard:Predicate_lang.any) @@ -1361,7 +1363,7 @@ end = struct let trace = ( rule_digest_version (* Update when changing the rule digest scheme. *) , Dep.Facts.digest deps ~sandbox_mode ~env - , Path.Build.Set.to_list_map rule.targets ~f:Path.Build.to_string + , Targets.to_list_map rule.targets ~file:Path.Build.to_string , Option.map rule.context ~f:(fun c -> Context_name.to_string c.name) , Action.for_shell action , can_go_in_shared_cache @@ -1430,7 +1432,8 @@ end = struct let { Action.Full.action; env; locks; can_go_in_shared_cache = _ } = action in - pending_targets := Path.Build.Set.union targets !pending_targets; + let file_targets = Targets.files targets in + pending_targets := Path.Build.Set.union file_targets !pending_targets; let chdirs = Action.chdirs action in let sandbox = Option.map sandbox_mode ~f:(fun mode -> @@ -1473,7 +1476,7 @@ end = struct in Option.iter sandbox ~f:Sandbox.destroy; (* All went well, these targets are no longer pending *) - pending_targets := Path.Build.Set.diff !pending_targets targets; + pending_targets := Path.Build.Set.diff !pending_targets file_targets; exec_result let try_to_store_to_shared_cache ~mode ~rule_digest ~action ~targets = @@ -1494,7 +1497,7 @@ end = struct Cached_digest.set target digest) in match - Path.Build.Set.to_list_map targets ~f:Dune_cache.Local.Target.create + Targets.to_list_map targets ~file:Dune_cache.Local.Target.create |> Option.List.all with | None -> Fiber.return None @@ -1590,7 +1593,7 @@ end = struct rule in start_rule t rule; - let head_target = Path.Build.Set.choose_exn targets in + let head_target = Targets.head_exn targets in let* execution_parameters = match Dpath.Target_dir.of_target dir with | Regular (With_context (_, dir)) @@ -1745,7 +1748,7 @@ end = struct ~cache_debug_flags:t.cache_debug_flags ~head_target miss_reason; (* Step I. Remove stale targets both from the digest table and from the build directory. *) - Path.Build.Set.iter targets ~f:(fun target -> + Targets.iter targets ~file:(fun target -> Cached_digest.remove target; Path.Build.unlink_no_err target); (* Step II. Try to restore artifacts from the shared cache if the @@ -1855,20 +1858,22 @@ end = struct | Promote { lifetime; into; only }, (Some Automatically | None) -> Fiber.parallel_iter_set (module Path.Build.Set) - targets - ~f:(fun path -> + (Targets.files targets) + ~f:(fun target -> let consider_for_promotion = match only with | None -> true | Some pred -> Predicate_lang.Glob.exec pred - (Path.reach (Path.build path) ~from:(Path.build dir)) + (Path.reach (Path.build target) ~from:(Path.build dir)) ~standard:Predicate_lang.any in match consider_for_promotion with | false -> Fiber.return () | true -> - let in_source_tree = Path.Build.drop_build_context_exn path in + let in_source_tree = + Path.Build.drop_build_context_exn target + in let in_source_tree = match into with | None -> in_source_tree @@ -1910,7 +1915,7 @@ end = struct | None -> false | Some in_source_tree_digest -> ( match - Cached_digest.build_file path + Cached_digest.build_file target |> Cached_digest.Digest_result.to_option with | None -> @@ -1935,7 +1940,7 @@ end = struct explicitly set the user writable bit. *) let chmod n = n lor 0o200 in Path.unlink_no_err (Path.source dst); - t.promote_source ~src:path ~dst ~chmod context + t.promote_source ~src:target ~dst ~chmod context )) in t.rule_done <- t.rule_done + 1; @@ -2005,7 +2010,7 @@ end = struct (match loc with | Some loc -> From_dune_file loc | None -> Internal) - ~targets:(Path.Build.Set.singleton target) + ~targets:(Targets.File.create target) (Action_builder.of_thunk { f = (fun mode -> diff --git a/src/dune_engine/dune_engine.ml b/src/dune_engine/dune_engine.ml index 6e31e42c16a..45db9fe7fd6 100644 --- a/src/dune_engine/dune_engine.ml +++ b/src/dune_engine/dune_engine.ml @@ -35,6 +35,7 @@ module Section = Section module Dpath = Dpath module Rules = Rules module Rule = Rule +module Targets = Targets module Build_context = Build_context module Build_system = Build_system module Cram_test = Cram_test diff --git a/src/dune_engine/process.ml b/src/dune_engine/process.ml index 28762a8f786..d9c2919967a 100644 --- a/src/dune_engine/process.ml +++ b/src/dune_engine/process.ml @@ -155,7 +155,7 @@ end type purpose = | Internal_job of Loc.t option * User_error.Annot.t list - | Build_job of Loc.t option * User_error.Annot.t list * Path.Build.Set.t + | Build_job of Loc.t option * User_error.Annot.t list * Targets.t let loc_and_annots_of_purpose = function | Internal_job (loc, annots) -> (loc, annots) @@ -318,9 +318,9 @@ module Fancy = struct ("(internal)" :: targets_acc) (add_ctx ctx ctxs_acc) rest) in - let targets = Path.Build.Set.to_list targets in + let file_targets = Targets.to_list_map targets ~file:Fun.id in let target_names, contexts = - split_paths [] Context_name.Set.empty targets + split_paths [] Context_name.Set.empty file_targets in let targets = List.map target_names ~f:Filename.split_extension_after_dot diff --git a/src/dune_engine/process.mli b/src/dune_engine/process.mli index 673e1b1f6f1..b7029cfbe53 100644 --- a/src/dune_engine/process.mli +++ b/src/dune_engine/process.mli @@ -56,7 +56,7 @@ end error messages. *) type purpose = | Internal_job of Loc.t option * User_error.Annot.t list - | Build_job of Loc.t option * User_error.Annot.t list * Path.Build.Set.t + | Build_job of Loc.t option * User_error.Annot.t list * Targets.t (** [run ?dir ?stdout_to prog args] spawns a sub-process and wait for its termination. [stdout_to] [stderr_to] are released *) diff --git a/src/dune_engine/reflection.ml b/src/dune_engine/reflection.ml index 5c2f2bc558d..20944bc56f3 100644 --- a/src/dune_engine/reflection.ml +++ b/src/dune_engine/reflection.ml @@ -8,7 +8,7 @@ module Rule = struct ; dir : Path.Build.t ; deps : Dep.Set.t ; expanded_deps : Path.Set.t - ; targets : Path.Build.Set.t + ; targets : Targets.t ; context : Build_context.t option ; action : Action.t } @@ -102,5 +102,5 @@ let eval ~recursive ~request = ; Pp.chain cycle ~f:(fun rule -> Pp.verbatim (Path.to_string_maybe_quoted - (Path.build (Path.Build.Set.choose_exn rule.targets)))) + (Path.build (Targets.head_exn rule.targets)))) ] diff --git a/src/dune_engine/reflection.mli b/src/dune_engine/reflection.mli index f1eaa1071a4..9780b6b577c 100644 --- a/src/dune_engine/reflection.mli +++ b/src/dune_engine/reflection.mli @@ -9,7 +9,7 @@ module Rule : sig ; (* [expanded_deps] skips over non-file dependencies, such as: environment variables, universe, glob listings, sandbox requirements *) expanded_deps : Path.Set.t - ; targets : Path.Build.Set.t + ; targets : Targets.t ; context : Build_context.t option ; action : Action.t } diff --git a/src/dune_engine/rule.ml b/src/dune_engine/rule.ml index 8cb38c9f3f1..0217992cb93 100644 --- a/src/dune_engine/rule.ml +++ b/src/dune_engine/rule.ml @@ -54,7 +54,7 @@ module T = struct type t = { id : Id.t ; context : Build_context.t option - ; targets : Path.Build.Set.t + ; targets : Targets.t ; action : Action.Full.t Action_builder.t ; mode : Mode.t ; info : Info.t @@ -102,30 +102,24 @@ let make ?(sandbox = Sandbox_config.default) ?(mode = Mode.Standard) ~context }) in let dir = - match Path.Build.Set.choose targets with - | None -> ( + match Targets.validate targets with + | Valid { parent_dir } -> parent_dir + | No_targets -> ( match info with | From_dune_file loc -> User_error.raise ~loc [ Pp.text "Rule has no targets specified" ] | _ -> Code_error.raise "Build_interpret.Rule.make: no targets" []) - | Some x -> - let dir = Path.Build.parent_exn x in - (if - Path.Build.Set.exists targets ~f:(fun path -> - Path.Build.( <> ) (Path.Build.parent_exn path) dir) - then - match info with - | Internal - | Source_file_copy _ -> - Code_error.raise "rule has targets in different directories" - [ ("targets", Path.Build.Set.to_dyn targets) ] - | From_dune_file loc -> - User_error.raise ~loc - [ Pp.text "Rule has targets in different directories.\nTargets:" - ; Pp.enumerate (Path.Build.Set.to_list targets) ~f:(fun p -> - Pp.verbatim (Path.to_string_maybe_quoted (Path.build p))) - ]); - dir + | Inconsistent_parent_dir -> ( + match info with + | Internal + | Source_file_copy _ -> + Code_error.raise "rule has targets in different directories" + [ ("targets", Targets.to_dyn targets) ] + | From_dune_file loc -> + User_error.raise ~loc + [ Pp.text "Rule has targets in different directories.\nTargets:" + ; Targets.pp targets + ]) in let loc = match info with diff --git a/src/dune_engine/rule.mli b/src/dune_engine/rule.mli index 2b62f3f6324..3e220f54a97 100644 --- a/src/dune_engine/rule.mli +++ b/src/dune_engine/rule.mli @@ -59,7 +59,7 @@ end type t = private { id : Id.t ; context : Build_context.t option - ; targets : Path.Build.Set.t + ; targets : Targets.t ; action : Action.Full.t Action_builder.t ; mode : Mode.t ; info : Info.t @@ -80,7 +80,7 @@ val make : -> ?mode:Mode.t -> context:Build_context.t option -> ?info:Info.t - -> targets:Path.Build.Set.t + -> targets:Targets.t -> Action.Full.t Action_builder.t -> t diff --git a/src/dune_engine/rules.ml b/src/dune_engine/rules.ml index 71225c2cc91..f9ff7a5e497 100644 --- a/src/dune_engine/rules.ml +++ b/src/dune_engine/rules.ml @@ -31,7 +31,7 @@ module Dir_rules = struct let data_to_dyn = function | Rule rule -> Dyn.Variant - ("Rule", [ Record [ ("targets", Path.Build.Set.to_dyn rule.targets) ] ]) + ("Rule", [ Record [ ("targets", Targets.to_dyn rule.targets) ] ]) | Alias alias -> Dyn.Variant ("Alias", [ Record [ ("name", Alias.Name.to_dyn alias.name) ] ]) diff --git a/src/dune_engine/sandbox.ml b/src/dune_engine/sandbox.ml index c05a4a6ee85..4c0f329c721 100644 --- a/src/dune_engine/sandbox.ml +++ b/src/dune_engine/sandbox.ml @@ -113,7 +113,7 @@ let rename_optional_file ~src ~dst = | () -> ()) let move_targets_to_build_dir t ~targets = - Path.Build.Set.iter targets ~f:(fun target -> + Targets.iter targets ~file:(fun target -> rename_optional_file ~src:(map_path t target) ~dst:target) let destroy t = Path.rm_rf (Path.build t.dir) diff --git a/src/dune_engine/sandbox.mli b/src/dune_engine/sandbox.mli index 79c38147dd4..ef41499601a 100644 --- a/src/dune_engine/sandbox.mli +++ b/src/dune_engine/sandbox.mli @@ -21,6 +21,6 @@ val create : (** Move the targets created by the action from the sandbox to the build directory. *) -val move_targets_to_build_dir : t -> targets:Path.Build.Set.t -> unit +val move_targets_to_build_dir : t -> targets:Targets.t -> unit val destroy : t -> unit diff --git a/src/dune_engine/targets.ml b/src/dune_engine/targets.ml new file mode 100644 index 00000000000..b6f336a13b1 --- /dev/null +++ b/src/dune_engine/targets.ml @@ -0,0 +1,61 @@ +open! Stdune +open Import + +type t = { files : Path.Build.Set.t } [@@unboxed] + +module File = struct + let create file = { files = Path.Build.Set.singleton file } +end + +module Files = struct + let create files = { files } +end + +let empty = { files = Path.Build.Set.empty } + +let combine x y = { files = Path.Build.Set.union x.files y.files } + +let is_empty t = Path.Build.Set.is_empty t.files + +let head { files } = Path.Build.Set.choose files + +let head_exn t = + match head t with + | Some target -> target + | None -> + Code_error.raise "Targets.head_exn applied to empty set of targets" [] + +let to_dyn { files } = Dyn.Record [ ("files", Path.Build.Set.to_dyn files) ] + +let pp { files } = + Pp.enumerate (Path.Build.Set.to_list files) ~f:(fun target -> + Pp.text (Dpath.describe_target target)) + +let exists { files } ~file = Path.Build.Set.exists files ~f:file + +let to_list_map { files } ~file = Path.Build.Set.to_list_map files ~f:file + +let fold { files } ~init ~file = Path.Build.Set.fold files ~init ~f:file + +let iter { files } ~file = Path.Build.Set.iter files ~f:file + +let files t = t.files + +module Validation_result = struct + type t = + | Valid of { parent_dir : Path.Build.t } + | No_targets + | Inconsistent_parent_dir +end + +let validate t = + match is_empty t with + | true -> Validation_result.No_targets + | false -> ( + let parent_dir = Path.Build.parent_exn (head_exn t) in + match + exists t ~file:(fun target -> + Path.Build.(parent_exn target <> parent_dir)) + with + | true -> Inconsistent_parent_dir + | false -> Valid { parent_dir }) diff --git a/src/dune_engine/targets.mli b/src/dune_engine/targets.mli new file mode 100644 index 00000000000..460b73d50e0 --- /dev/null +++ b/src/dune_engine/targets.mli @@ -0,0 +1,57 @@ +open! Stdune +open! Import + +(* CR-someday amokhov: Add directory targets. *) + +(** A set of file targets of a build rule. *) +type t + +(** The empty set of targets. Note that rules are not allowed to have the empty + set of targets, but it is convenient to construct [t] by aggregating several + sources of information, for some of which it's OK to be empty. *) +val empty : t + +val is_empty : t -> bool + +(** Combine the sets of file and directory targets. *) +val combine : t -> t -> t + +module File : sig + (** A single file target. *) + val create : Path.Build.t -> t +end + +module Files : sig + (** A set of file targets. *) + val create : Path.Build.Set.t -> t +end + +module Validation_result : sig + type t = + | Valid of { parent_dir : Path.Build.t } + | No_targets + | Inconsistent_parent_dir +end + +(** Ensure that the set of targets is non-empty and that all targets have the + same parent dir. *) +val validate : t -> Validation_result.t + +(** The "head" target, i.e. the lexicographically first target file if [t] is + non-empty. *) +val head : t -> Path.Build.t option + +(** Like [head] but raises a code error if the set of targets is empty. *) +val head_exn : t -> Path.Build.t + +val files : t -> Path.Build.Set.t + +val to_list_map : t -> file:(Path.Build.t -> 'a) -> 'a list + +val fold : t -> init:'a -> file:(Path.Build.t -> 'a -> 'a) -> 'a + +val iter : t -> file:(Path.Build.t -> unit) -> unit + +val to_dyn : t -> Dyn.t + +val pp : t -> _ Pp.t diff --git a/src/dune_rules/action_unexpanded.ml b/src/dune_rules/action_unexpanded.ml index a64acb6231a..d73ad9b39df 100644 --- a/src/dune_rules/action_unexpanded.ml +++ b/src/dune_rules/action_unexpanded.ml @@ -88,7 +88,7 @@ end = struct type deps = Path.Set.t Action_builder.t type collector = - { targets : Path.Build.Set.t + { file_targets : Path.Build.Set.t (** We only infer file targets *) ; deps : deps ; deps_if_exist : deps } @@ -126,19 +126,22 @@ end = struct let run t ~expander = let deps = Action_builder.return Path.Set.empty in - let acc = { targets = Path.Build.Set.empty; deps; deps_if_exist = deps } in + let acc = + { file_targets = Path.Build.Set.empty; deps; deps_if_exist = deps } + in let env = { expander; infer = true; dir = Expander.dir expander } in Memo.Build.map (t env acc) ~f:(fun (b, acc) -> - let { targets; deps; deps_if_exist } = acc in + let { file_targets; deps; deps_if_exist } = acc in (* A file can be inferred as both a dependency and a target, for instance: {[ (progn (copy a b) (copy b c)) ]} *) let remove_targets = - let targets = - Path.Build.Set.to_list targets |> Path.Set.of_list_map ~f:Path.build + let file_targets = + Path.Build.Set.to_list file_targets + |> Path.Set.of_list_map ~f:Path.build in - fun deps -> Path.Set.diff deps targets + fun deps -> Path.Set.diff deps file_targets in let deps = deps >>| remove_targets in let deps_if_exist = deps_if_exist >>| remove_targets in @@ -149,7 +152,8 @@ end = struct >>> Action_builder.if_file_exists f ~then_:(Action_builder.path f) ~else_:(Action_builder.return ())) in - Action_builder.with_targets_set ~targets + Action_builder.with_targets + ~targets:(Targets.Files.create file_targets) (let+ () = deps >>= Action_builder.path_set and+ () = deps_if_exist >>= action_builder_path_set_if_exist and+ res = b in @@ -310,7 +314,8 @@ end = struct else let+! p = Expander.No_deps.expand_path env sw in let p = as_in_build_dir p ~what ~loc:(loc sw) in - (Action_builder.return p, { acc with targets = f acc.targets p }) + ( Action_builder.return p + , { acc with file_targets = f acc.file_targets p } ) let consume_file = add_or_remove_target ~what:"File" ~f:Path.Build.Set.remove @@ -481,8 +486,6 @@ let rec expand (t : Action_dune_lang.t) : Action.t Action_expander.t = let+ script = E.dep script in O.Cram script -let pp_path_build target = Pp.text (Dpath.describe_path (Path.build target)) - let expand_no_targets t ~loc ~deps:deps_written_by_user ~expander ~what = let open Action_builder.O in let deps_builder, expander = @@ -494,13 +497,13 @@ let expand_no_targets t ~loc ~deps:deps_written_by_user ~expander ~what = let* { Action_builder.With_targets.build; targets } = Action_builder.memo_build (Action_expander.run (expand t) ~expander) in - if not (Path.Build.Set.is_empty targets) then + if not (Targets.is_empty targets) then User_error.raise ~loc [ Pp.textf "%s must not have targets, however I inferred that these files will \ be created by this action:" (String.capitalize what) - ; Pp.enumerate (Path.Build.Set.to_list targets) ~f:pp_path_build + ; Targets.pp targets ]; let+ () = deps_builder and+ action = build in @@ -514,7 +517,7 @@ let expand t ~loc ~deps:deps_written_by_user ~targets_dir Dep_conf_eval.named ~expander deps_written_by_user in let expander = - match (targets_written_by_user : _ Targets.t) with + match (targets_written_by_user : _ Targets_spec.t) with | Infer -> expander | Static { targets; multiplicity } -> Expander.add_bindings_full expander @@ -535,18 +538,19 @@ let expand t ~loc ~deps:deps_written_by_user ~targets_dir Action_expander.run (expand t) ~expander in let targets = - match (targets_written_by_user : _ Targets.t) with + match (targets_written_by_user : _ Targets_spec.t) with | Infer -> targets - | Static { targets = targets'; multiplicity = _ } -> - Path.Build.Set.union targets (Path.Build.Set.of_list targets') + | Static { targets = targets_written_by_user; multiplicity = _ } -> + Targets.combine targets + (Targets.Files.create (Path.Build.Set.of_list targets_written_by_user)) in - Path.Build.Set.iter targets ~f:(fun target -> + Targets.iter targets ~file:(fun target -> if Path.Build.( <> ) (Path.Build.parent_exn target) targets_dir then User_error.raise ~loc [ Pp.text "This action has targets in a different directory than the \ current one, this is not allowed by dune at the moment:" - ; Pp.enumerate (Path.Build.Set.to_list targets) ~f:pp_path_build + ; Targets.pp targets ]); let build = let+ () = deps_builder @@ -554,7 +558,7 @@ let expand t ~loc ~deps:deps_written_by_user ~targets_dir let dir = Path.build (Expander.dir expander) in Action.Chdir (dir, action) in - Action_builder.with_targets_set ~targets build + Action_builder.with_targets ~targets build (* We re-export [Action_dune_lang] in the end to avoid polluting the inferred types in this module with all the various t's *) diff --git a/src/dune_rules/action_unexpanded.mli b/src/dune_rules/action_unexpanded.mli index 501b409a084..27a9e030c85 100644 --- a/src/dune_rules/action_unexpanded.mli +++ b/src/dune_rules/action_unexpanded.mli @@ -31,7 +31,7 @@ val expand : -> loc:Loc.t -> deps:Dep_conf.t Bindings.t -> targets_dir:Path.Build.t - -> targets:Path.Build.t Targets.t + -> targets:Path.Build.t Targets_spec.t -> expander:Expander.t -> Action.t Action_builder.With_targets.t Memo.Build.t diff --git a/src/dune_rules/buildable_rules.ml b/src/dune_rules/buildable_rules.ml index e4768632cb5..f976dba58c8 100644 --- a/src/dune_rules/buildable_rules.ml +++ b/src/dune_rules/buildable_rules.ml @@ -8,7 +8,7 @@ let gen_select_rules t ~dir compile_info = let { Lib.Compile.Resolved_select.dst_fn; src_fn } = rs in let dst = Path.Build.relative dir dst_fn in Super_context.add_rule t ~dir - (Action_builder.with_targets ~targets:[ dst ] + (Action_builder.with_file_targets ~file_targets:[ dst ] (let open Action_builder.O in let* src_fn = Resolve.read src_fn in let src = Path.build (Path.Build.relative dir src_fn) in diff --git a/src/dune_rules/command.ml b/src/dune_rules/command.ml index ee230b065f4..60b2caff4f7 100644 --- a/src/dune_rules/command.ml +++ b/src/dune_rules/command.ml @@ -76,7 +76,7 @@ let rec expand : Action_builder.With_targets.map (expand ~dir (S ts)) ~f:(fun x -> [ String.concat ~sep x ]) | Target fn -> - Action_builder.with_targets ~targets:[ fn ] + Action_builder.with_file_targets ~file_targets:[ fn ] (Action_builder.return [ Path.reach (Path.build fn) ~from:dir ]) | Dyn dyn -> Action_builder.with_no_targets @@ -86,12 +86,13 @@ let rec expand : Action_builder.with_no_targets (Action_builder.map (Action_builder.deps deps) ~f:(fun () -> [])) | Hidden_targets fns -> - Action_builder.with_targets ~targets:fns (Action_builder.return []) + Action_builder.with_file_targets ~file_targets:fns + (Action_builder.return []) | Expand f -> Action_builder.with_no_targets (f ~dir) and expand_no_targets ~dir (t : without_targets t) = let { Action_builder.With_targets.build; targets } = expand ~dir t in - assert (Path.Build.Set.is_empty targets); + assert (Targets.is_empty targets); build let dep_prog = function @@ -99,7 +100,7 @@ let dep_prog = function | Error _ -> Action_builder.return () let run ~dir ?stdout_to prog args = - Action_builder.With_targets.add ~targets:(Option.to_list stdout_to) + Action_builder.With_targets.add ~file_targets:(Option.to_list stdout_to) (let open Action_builder.With_targets.O in let+ () = Action_builder.with_no_targets (dep_prog prog) and+ args = expand ~dir (S args) in diff --git a/src/dune_rules/context.ml b/src/dune_rules/context.ml index b264d7355cf..7117d2596c9 100644 --- a/src/dune_rules/context.ml +++ b/src/dune_rules/context.ml @@ -887,8 +887,7 @@ let gen_configurator_rules t = let* () = let fn = configurator_v1 t in Rules.Produce.rule - (Rule.make ~context:None - ~targets:(Path.Build.Set.singleton fn) + (Rule.make ~context:None ~targets:(Targets.File.create fn) (let open Action_builder.O in let+ () = Action_builder.return () in { Action.Full.action = @@ -909,8 +908,7 @@ let gen_configurator_rules t = in let fn = configurator_v2 t in Rules.Produce.rule - (Rule.make ~context:None - ~targets:(Path.Build.Set.singleton fn) + (Rule.make ~context:None ~targets:(Targets.File.create fn) (let open Action_builder.O in let+ () = Action_builder.return () in { Action.Full.action = diff --git a/src/dune_rules/coq_rules.ml b/src/dune_rules/coq_rules.ml index 828230e4f37..288cedf44a0 100644 --- a/src/dune_rules/coq_rules.ml +++ b/src/dune_rules/coq_rules.ml @@ -585,5 +585,5 @@ let extraction_rules ~sctx ~dir ~dir_contents (s : Extraction.t) = theories >>> Action_builder.path (Path.build (Coq_module.source coq_module)) in let { Module_rule.coqc; coqdep } = setup_rule cctx ~source_rule coq_module in - let coqc = Action_builder.With_targets.add coqc ~targets:ml_targets in + let coqc = Action_builder.With_targets.add coqc ~file_targets:ml_targets in [ coqdep; coqc ] diff --git a/src/dune_rules/ctypes_rules.ml b/src/dune_rules/ctypes_rules.ml index 1b6fa5e79f6..3e76528cba7 100644 --- a/src/dune_rules/ctypes_rules.ml +++ b/src/dune_rules/ctypes_rules.ml @@ -386,8 +386,8 @@ let build_c_program ~sctx ~dir ~source_files ~scope ~cflags_sexp ~output () = in Action.run exe args) in - Action_builder.with_targets action - ~targets:[ Path.Build.relative dir output ] + Action_builder.with_file_targets action + ~file_targets:[ Path.Build.relative dir output ] in Super_context.add_rule sctx ~dir build diff --git a/src/dune_rules/dir_contents.ml b/src/dune_rules/dir_contents.ml index 2fe2538f5ab..795a8a3abe4 100644 --- a/src/dune_rules/dir_contents.ml +++ b/src/dune_rules/dir_contents.ml @@ -144,7 +144,7 @@ end = struct | Menhir.T menhir -> Memo.Build.return (Menhir_rules.targets menhir) | Rule rule -> Simple_rules.user_rule sctx rule ~dir ~expander - >>| Path.Build.Set.to_list_map ~f:Path.Build.basename + >>| Targets.to_list_map ~file:Path.Build.basename | Copy_files def -> let+ ps = Simple_rules.copy_files sctx def ~src_dir ~dir ~expander diff --git a/src/dune_rules/dune_file.ml b/src/dune_rules/dune_file.ml index aab63bc8d4a..c1b29edae3b 100644 --- a/src/dune_rules/dune_file.ml +++ b/src/dune_rules/dune_file.ml @@ -1564,7 +1564,7 @@ module Rule = struct end type t = - { targets : String_with_vars.t Targets.t + { targets : String_with_vars.t Targets_spec.t ; deps : Dep_conf.t Bindings.t ; action : Loc.t * Action_dune_lang.t ; mode : Rule.Mode.t @@ -1633,7 +1633,7 @@ module Rule = struct String_with_vars.add_user_vars_to_decoding_env (Bindings.var_names deps) (let+ loc = loc and+ action = field "action" (located Action_dune_lang.decode) - and+ targets = Targets.field + and+ targets = Targets_spec.field and+ locks = field "locks" (repeat String_with_vars.decode) ~default:[] and+ () = let+ fallback = diff --git a/src/dune_rules/dune_file.mli b/src/dune_rules/dune_file.mli index 0840b3dd687..a6cbb3fb70b 100644 --- a/src/dune_rules/dune_file.mli +++ b/src/dune_rules/dune_file.mli @@ -301,7 +301,7 @@ end module Rule : sig type t = - { targets : String_with_vars.t Targets.t + { targets : String_with_vars.t Targets_spec.t ; deps : Dep_conf.t Bindings.t ; action : Loc.t * Action_dune_lang.t ; mode : Rule.Mode.t diff --git a/src/dune_rules/expander.ml b/src/dune_rules/expander.ml index fb9d702eb2c..d8a0c6d020f 100644 --- a/src/dune_rules/expander.ml +++ b/src/dune_rules/expander.ml @@ -10,7 +10,7 @@ module Expanding_what = struct type t = | Nothing_special | Deps_like_field - | User_action of Path.Build.t Targets.t + | User_action of Path.Build.t Targets_spec.t | User_action_without_targets of { what : string } end @@ -262,7 +262,7 @@ let[@inline never] invalid_use_of_target_variable t ] | Static { targets = _; multiplicity } -> assert (multiplicity <> var_multiplicity); - Targets.Multiplicity.check_variable_matches_field ~loc:source.loc + Targets_spec.Multiplicity.check_variable_matches_field ~loc:source.loc ~field:multiplicity ~variable:var_multiplicity; assert false) diff --git a/src/dune_rules/expander.mli b/src/dune_rules/expander.mli index f0b6347eb2b..4223ba7b15d 100644 --- a/src/dune_rules/expander.mli +++ b/src/dune_rules/expander.mli @@ -48,7 +48,7 @@ module Expanding_what : sig type t = | Nothing_special | Deps_like_field - | User_action of Path.Build.t Targets.t + | User_action of Path.Build.t Targets_spec.t | User_action_without_targets of { what : string } (** [what] describe what the action is. It should be a plural and is inserted in a sentence as follow: " are not allowed to have diff --git a/src/dune_rules/format_rules.ml b/src/dune_rules/format_rules.ml index 395a218cbe4..846a78f4679 100644 --- a/src/dune_rules/format_rules.ml +++ b/src/dune_rules/format_rules.ml @@ -37,7 +37,7 @@ let gen_rules_output sctx (config : Format_config.t) ~version ~dialects match Path.Source.basename file with | "dune" when Format_config.includes config Dune -> Option.some - @@ Action_builder.with_targets ~targets:[ output ] + @@ Action_builder.with_file_targets ~file_targets:[ output ] @@ let open Action_builder.O in let+ () = Action_builder.path input in diff --git a/src/dune_rules/gen_rules.ml b/src/dune_rules/gen_rules.ml index 8a831c24b4a..f1cf8a9cd7e 100644 --- a/src/dune_rules/gen_rules.ml +++ b/src/dune_rules/gen_rules.ml @@ -272,7 +272,7 @@ let gen_rules sctx dir_contents cctxs expander | None -> (* This happens often when passing a [-p ...] option that hides a library *) - let targets = + let file_targets = List.map (Menhir_rules.targets m) ~f:(Path.Build.relative ctx_dir) in @@ -286,7 +286,7 @@ let gen_rules sctx dir_contents cctxs expander files produced by this stanza are part of." ]) } - |> Action_builder.with_targets ~targets) + |> Action_builder.with_file_targets ~file_targets) | Some cctx -> Menhir_rules.gen_rules cctx m ~dir:ctx_dir)) | Coq_stanza.Theory.T m -> ( Expander.eval_blang expander m.enabled_if >>= function diff --git a/src/dune_rules/inline_tests.ml b/src/dune_rules/inline_tests.ml index 3e1d49f27ff..b093ca0f47a 100644 --- a/src/dune_rules/inline_tests.ml +++ b/src/dune_rules/inline_tests.ml @@ -149,7 +149,7 @@ include Sub_system.Register_end_point (struct in Action.with_stdout_to target (Action.progn actions) in - Action_builder.With_targets.add ~targets:[ target ] action) + Action_builder.With_targets.add ~file_targets:[ target ] action) and* cctx = let package = Dune_file.Library.package lib in let+ ocaml_flags = Super_context.ocaml_flags sctx ~dir info.executable in diff --git a/src/dune_rules/module_compilation.ml b/src/dune_rules/module_compilation.ml index 772ea5b8bae..ce685c4a2aa 100644 --- a/src/dune_rules/module_compilation.ml +++ b/src/dune_rules/module_compilation.ml @@ -268,7 +268,7 @@ let ocamlc_i ?(flags = []) ~deps cctx (m : Module.t) ~output = let ocaml_flags = Ocaml_flags.get (CC.flags cctx) Mode.Byte in let modules = Compilation_context.modules cctx in SC.add_rule sctx ~sandbox ~dir - (Action_builder.With_targets.add ~targets:[ output ] + (Action_builder.With_targets.add ~file_targets:[ output ] (let open Action_builder.With_targets.O in Action_builder.with_no_targets cm_deps >>> Action_builder.With_targets.map diff --git a/src/dune_rules/ocamldep.ml b/src/dune_rules/ocamldep.ml index 463f2f07970..fdd1255ea79 100644 --- a/src/dune_rules/ocamldep.ml +++ b/src/dune_rules/ocamldep.ml @@ -115,7 +115,7 @@ let deps_of ~cctx ~ml_kind unit = ( build_paths modules , List.map modules ~f:(fun m -> Module_name.to_string (Module.name m)) ) in - Action_builder.with_targets ~targets:[ all_deps_file ] + Action_builder.with_file_targets ~file_targets:[ all_deps_file ] (let+ sources, extras = Action_builder.dyn_paths (let+ sources, extras = paths in diff --git a/src/dune_rules/preprocessing.ml b/src/dune_rules/preprocessing.ml index 3d267f7121b..d5f5e1d9472 100644 --- a/src/dune_rules/preprocessing.ml +++ b/src/dune_rules/preprocessing.ml @@ -504,7 +504,7 @@ let action_for_pp_with_target ~loc ~expander ~action ~src ~target = let action = action_for_pp ~loc ~expander ~action ~src in Action_builder.With_targets.map ~f:(Action.with_stdout_to target) - (Action_builder.with_targets ~targets:[ target ] action) + (Action_builder.with_file_targets ~file_targets:[ target ] action) (* Generate rules for the dialect modules in [modules] and return a a new module with only OCaml sources *) @@ -666,7 +666,7 @@ let make sctx ~dir ~expander ~lint ~preprocess ~preprocessor_deps (promote_correction_with_target ~suffix:corrected_suffix (Path.as_in_build_dir_exn (Option.value_exn (Module.file m ~ml_kind))) - (Action_builder.with_targets ~targets:[ dst ] + (Action_builder.with_file_targets ~file_targets:[ dst ] (let open Action_builder.O in preprocessor_deps >>> let* exe, flags, args = driver_and_flags in diff --git a/src/dune_rules/simple_rules.ml b/src/dune_rules/simple_rules.ml index c550e3f8c29..0e63482fd6f 100644 --- a/src/dune_rules/simple_rules.ml +++ b/src/dune_rules/simple_rules.ml @@ -51,7 +51,7 @@ let rule_kind ~(rule : Rule.t) match rule.alias with | None -> No_alias | Some alias -> ( - match action.targets |> Path.Build.Set.choose with + match action.targets |> Targets.head with | None -> Alias_only alias | Some target -> Alias_with_targets (alias, target)) @@ -69,15 +69,15 @@ let user_rule sctx ?extra_bindings ~dir ~expander (rule : Rule.t) = Expander.eval_blang expander rule.enabled_if >>= function | false -> ( match rule.alias with - | None -> Memo.Build.return Path.Build.Set.empty + | None -> Memo.Build.return Targets.empty | Some name -> let alias = Alias.make ~dir name in let+ () = Alias_rules.add_empty sctx ~alias ~loc:(Some rule.loc) in - Path.Build.Set.empty) + Targets.empty) | true -> ( let* targets = match rule.targets with - | Infer -> Memo.Build.return Targets.Infer + | Infer -> Memo.Build.return Targets_spec.Infer | Static { targets; multiplicity } -> let+ targets = Memo.Build.List.concat_map targets ~f:(fun target -> @@ -89,7 +89,7 @@ let user_rule sctx ?extra_bindings ~dir ~expander (rule : Rule.t) = | Multiple -> Expander.No_deps.expand expander ~mode:Many target) >>| List.map ~f:(check_filename ~dir ~error_loc)) in - Targets.Static { multiplicity; targets } + Targets_spec.Static { multiplicity; targets } in let expander = match extra_bindings with @@ -115,7 +115,7 @@ let user_rule sctx ?extra_bindings ~dir ~expander (rule : Rule.t) = let+ () = Alias_rules.add sctx ~alias ~loc:(Some rule.loc) action.build ~locks in - Path.Build.Set.empty) + Targets.empty) let copy_files sctx ~dir ~expander ~src_dir (def : Copy_files.t) = let loc = String_with_vars.loc def.files in diff --git a/src/dune_rules/simple_rules.mli b/src/dune_rules/simple_rules.mli index 9ef7e904e3e..40febdba0dd 100644 --- a/src/dune_rules/simple_rules.mli +++ b/src/dune_rules/simple_rules.mli @@ -28,7 +28,7 @@ val user_rule : -> dir:Path.Build.t -> expander:Expander.t -> Rule.t - -> Path.Build.Set.t Memo.Build.t + -> Targets.t Memo.Build.t (** Interpret a [(copy_files ...)] stanza and return the targets it produces. *) val copy_files : diff --git a/src/dune_rules/super_context.mli b/src/dune_rules/super_context.mli index 70df50cb8db..1359c0c6e4b 100644 --- a/src/dune_rules/super_context.mli +++ b/src/dune_rules/super_context.mli @@ -122,7 +122,7 @@ val add_rule_get_targets : -> ?loc:Loc.t -> dir:Path.Build.t -> Action.t Action_builder.With_targets.t - -> Path.Build.Set.t Memo.Build.t + -> Targets.t Memo.Build.t val add_rules : t diff --git a/src/dune_rules/targets.ml b/src/dune_rules/targets_spec.ml similarity index 100% rename from src/dune_rules/targets.ml rename to src/dune_rules/targets_spec.ml diff --git a/src/dune_rules/targets.mli b/src/dune_rules/targets_spec.mli similarity index 86% rename from src/dune_rules/targets.mli rename to src/dune_rules/targets_spec.mli index 2a09dbd098f..5ed5cc258e4 100644 --- a/src/dune_rules/targets.mli +++ b/src/dune_rules/targets_spec.mli @@ -1,4 +1,4 @@ -(** Defines target behavior for rules. *) +(** Specification of targets. *) open! Dune_engine open Import @@ -25,5 +25,5 @@ type 'a t = | Static of 'a Static.t | Infer -(** target or targets with field with the correct multiplicity *) +(** [target] or [targets] field with the correct multiplicity. *) val field : String_with_vars.t t Dune_lang.Decoder.fields_parser diff --git a/src/dune_rules/test_rules.ml b/src/dune_rules/test_rules.ml index f4ea37acfb8..7ccd5971f5d 100644 --- a/src/dune_rules/test_rules.ml +++ b/src/dune_rules/test_rules.ml @@ -66,7 +66,7 @@ let rules (t : Dune_file.Tests.t) ~sctx ~dir ~scope ~expander ~dir_contents = } in add_alias ~loc ~action:(Diff diff) ~locks:t.locks - >>> let+ (_ignored_paths : Path.Build.Set.t) = + >>> let+ (_ignored_targets : Targets.t) = Simple_rules.user_rule sctx rule ~extra_bindings ~dir ~expander in ())