diff --git a/src/action.mli b/src/action.mli index 6c103f51..4a7d32ad 100644 --- a/src/action.mli +++ b/src/action.mli @@ -83,7 +83,7 @@ module Unexpanded : sig : t -> dir:Path.t -> map_exe:(Path.t -> Path.t) - -> f:(String_with_vars.Var.t -> Syntax.Version.t -> Value.t list option) + -> f:(Value.t list option String_with_vars.expander) -> Unresolved.t end @@ -91,7 +91,7 @@ module Unexpanded : sig : t -> dir:Path.t -> map_exe:(Path.t -> Path.t) - -> f:(String_with_vars.Var.t -> Syntax.Version.t -> Value.t list option) + -> f:(Value.t list option String_with_vars.expander) -> Partial.t end diff --git a/src/ordered_set_lang.ml b/src/ordered_set_lang.ml index 6301e562..393f7a76 100644 --- a/src/ordered_set_lang.ml +++ b/src/ordered_set_lang.ml @@ -10,6 +10,10 @@ module Ast = struct | Union : ('a, 'b) t list -> ('a, 'b) t | Diff : ('a, 'b) t * ('a, 'b) t -> ('a, 'b) t | Include : String_with_vars.t -> ('a, unexpanded) t + + let union = function + | [x] -> x + | xs -> Union xs end type 'ast generic = @@ -32,7 +36,7 @@ module Parse = struct peek_exn >>= function | Atom (loc, A "\\") -> Loc.fail loc "unexpected \\" | (Atom (_, A "") | Quoted_string (_, _)) | Template _ -> - elt >>| fun x -> Element x + elt | Atom (loc, A s) -> begin match s with | ":standard" -> @@ -43,7 +47,7 @@ module Parse = struct | _ when s.[0] = ':' -> Loc.fail loc "undefined symbol %s" s | _ -> - elt >>| fun x -> Element x + elt end | List (_, Atom (loc, A s) :: _) -> begin match s, kind with @@ -88,7 +92,8 @@ end let t = let open Stanza.Of_sexp in get_all >>= fun context -> - located (Parse.without_include ~elt:(plain_string (fun ~loc s -> (loc, s)))) + located (Parse.without_include + ~elt:(plain_string (fun ~loc s -> Ast.Element (loc, s)))) >>| fun (loc, ast) -> { ast; loc = Some loc; context } @@ -210,10 +215,12 @@ let field ?(default=standard) name = Sexp.Of_sexp.field name t ~default module Unexpanded = struct type ast = (String_with_vars.t, Ast.unexpanded) Ast.t type t = ast generic - let t = + let t : t Sexp.Of_sexp.t = let open Stanza.Of_sexp in get_all >>= fun context -> - located (Parse.with_include ~elt:String_with_vars.t) + located ( + Parse.with_include + ~elt:(String_with_vars.t >>| fun s -> Ast.Element s)) >>| fun (loc, ast) -> { ast ; loc = Some loc @@ -239,12 +246,11 @@ module Unexpanded = struct let field ?(default=standard) name = Stanza.Of_sexp.field name t ~default let files t ~f = - let rec loop acc (t : ast) = + let rec loop acc (ast : ast) = let open Ast in - match t with + match ast with | Element _ | Standard -> acc - | Include fn -> - String.Set.add acc (f fn) + | Include fn -> Path.Set.add acc (f fn) | Union l -> List.fold_left l ~init:acc ~f:loop | Diff (l, r) -> @@ -255,7 +261,7 @@ module Unexpanded = struct | Some (0, _)-> File_tree.Dune_file.Kind.Jbuild | None | Some (_, _) -> Dune in - (syntax, loop String.Set.empty t.ast) + (syntax, loop Path.Set.empty t.ast) let has_special_forms t = let rec loop (t : ast) = @@ -291,31 +297,41 @@ module Unexpanded = struct in loop t.ast Pos init - let expand t ~files_contents ~f = + let expand t ~dir ~files_contents ~(f : String_with_vars.t -> Value.t list) = let context = t.context in + let f_elems s = + let loc = String_with_vars.loc s in + Ast.union + (List.map (f s) ~f:(fun s -> Ast.Element (loc, Value.to_string ~dir s))) + in let rec expand (t : ast) : ast_expanded = let open Ast in match t with - | Element s -> Element (String_with_vars.loc s, f s) + | Element s -> f_elems s | Standard -> Standard | Include fn -> let sexp = - let fn = f fn in - match String.Map.find files_contents fn with + let path = + match f fn with + | [x] -> Value.to_path ~dir x + | _ -> + Loc.fail (String_with_vars.loc fn) + "An unquoted templated expanded to more than one value. \ + A file path is expected in this position." + in + match Path.Map.find files_contents path with | Some x -> x | None -> Exn.code_error "Ordered_set_lang.Unexpanded.expand" - [ "included-file", Quoted_string fn - ; "files", Sexp.To_sexp.(list string) - (String.Map.keys files_contents) + [ "included-file", Path.sexp_of_t path + ; "files", Sexp.To_sexp.(list Path.sexp_of_t) + (Path.Map.keys files_contents) ] in let open Stanza.Of_sexp in parse - (Parse.without_include - ~elt:(String_with_vars.t >>| fun s -> - (String_with_vars.loc s, f s))) + (Parse.without_include ~elt:(String_with_vars.t >>| f_elems)) context sexp | Union l -> Union (List.map l ~f:expand) diff --git a/src/ordered_set_lang.mli b/src/ordered_set_lang.mli index be36d9cb..6ebaf74f 100644 --- a/src/ordered_set_lang.mli +++ b/src/ordered_set_lang.mli @@ -65,16 +65,17 @@ module Unexpanded : sig (** List of files needed to expand this set *) val files : t - -> f:(String_with_vars.t -> string) - -> Sexp.syntax * String.Set.t + -> f:(String_with_vars.t -> Path.t) + -> Sexp.syntax * Path.Set.t (** Expand [t] using with the given file contents. [file_contents] is a map from filenames to their parsed contents. Every [(:include fn)] in [t] is replaced by [Map.find files_contents fn]. Every element is converted to a string using [f]. *) val expand : t - -> files_contents:Sexp.Ast.t String.Map.t - -> f:(String_with_vars.t -> string) + -> dir:Path.t + -> files_contents:Sexp.Ast.t Path.Map.t + -> f:(String_with_vars.t -> Value.t list) -> expanded type position = Pos | Neg diff --git a/src/pform.ml b/src/pform.ml index 238192d7..17165b58 100644 --- a/src/pform.ml +++ b/src/pform.ml @@ -187,7 +187,7 @@ module Map = struct Syntax.Error.deleted_in (String_with_vars.Var.loc pform) Stanza.syntax syntax_version ~what:(describe pform) ?repl - let expand t ~syntax_version ~pform = + let expand t pform syntax_version = match String_with_vars.Var.payload pform with | None -> Option.map (expand t.vars ~syntax_version ~pform) ~f:(fun x -> diff --git a/src/pform.mli b/src/pform.mli index fcce5f06..4d5bf6a7 100644 --- a/src/pform.mli +++ b/src/pform.mli @@ -48,11 +48,7 @@ module Map : sig val input_file : Path.t -> t - val expand - : t - -> syntax_version:Syntax.Version.t - -> pform:String_with_vars.Var.t - -> Expansion.t option + val expand : t -> Expansion.t option String_with_vars.expander val empty : t end diff --git a/src/string_with_vars.ml b/src/string_with_vars.ml index 67c8e9ae..6237ac5e 100644 --- a/src/string_with_vars.ml +++ b/src/string_with_vars.ml @@ -158,7 +158,7 @@ let concat_rev = function | l -> String.concat (List.rev l) ~sep:"" module Mode = struct - type 'a t = + type _ t = | Single : Value.t t | Many : Value.t list t @@ -264,6 +264,8 @@ let partial_expand end | _ -> loop [] [] template.parts +type 'a expander = Var.t -> Syntax.Version.t -> 'a + let expand t ~mode ~dir ~f = match partial_expand t ~mode ~dir ~f:(fun var syntax_version -> diff --git a/src/string_with_vars.mli b/src/string_with_vars.mli index 48936764..4a3736bd 100644 --- a/src/string_with_vars.mli +++ b/src/string_with_vars.mli @@ -35,7 +35,7 @@ val is_var : t -> name:string -> bool val text_only : t -> string option module Mode : sig - type 'a t = + type _ t = | Single : Value.t t | Many : Value.t list t end @@ -64,16 +64,18 @@ module Var : sig val describe : t -> string end +type 'a expander = Var.t -> Syntax.Version.t -> 'a + val expand : t -> mode:'a Mode.t -> dir:Path.t - -> f:(Var.t -> Syntax.Version.t -> Value.t list option) + -> f:(Value.t list option expander) -> 'a val partial_expand : t -> mode:'a Mode.t -> dir:Path.t - -> f:(Var.t -> Syntax.Version.t -> Value.t list option) + -> f:(Value.t list option expander) -> 'a Partial.t diff --git a/src/super_context.ml b/src/super_context.ml index 973c4bfc..f956c69f 100644 --- a/src/super_context.ml +++ b/src/super_context.ml @@ -95,50 +95,49 @@ let expand_ocaml_config t pform name = "Unknown ocaml configuration variable %S" name -let (expand_vars_string, expand_vars_path) = - let expand t ~scope ~dir ?(bindings=Pform.Map.empty) s = - String_with_vars.expand ~mode:Single ~dir s ~f:(fun pform syntax_version -> - (match Pform.Map.expand bindings ~syntax_version ~pform with - | None -> Pform.Map.expand t.pforms ~syntax_version ~pform - | Some _ as x -> x) - |> Option.map ~f:(function - | Pform.Expansion.Var (Values l) -> l - | Macro (Ocaml_config, s) -> expand_ocaml_config t pform s - | Var Project_root -> [Value.Dir (Scope.root scope)] - | _ -> - Loc.fail (String_with_vars.Var.loc pform) - "%s isn't allowed in this position" - (String_with_vars.Var.describe pform))) - in - let expand_vars t ~scope ~dir ?bindings s = - expand t ~scope ~dir ?bindings s - |> Value.to_string ~dir - in - let expand_vars_path t ~scope ~dir ?bindings s = - expand t ~scope ~dir ?bindings s - |> Value.to_path ~error_loc:(String_with_vars.loc s) ~dir - in - (expand_vars, expand_vars_path) +let expand_vars t ~mode ~scope ~dir ?(bindings=Pform.Map.empty) s = + String_with_vars.expand ~mode ~dir s ~f:(fun pform syntax_version -> + (match Pform.Map.expand bindings pform syntax_version with + | None -> Pform.Map.expand t.pforms pform syntax_version + | Some _ as x -> x) + |> Option.map ~f:(function + | Pform.Expansion.Var (Values l) -> l + | Macro (Ocaml_config, s) -> expand_ocaml_config t pform s + | Var Project_root -> [Value.Dir (Scope.root scope)] + | _ -> + Loc.fail (String_with_vars.Var.loc pform) + "%s isn't allowed in this position" + (String_with_vars.Var.describe pform))) + +let expand_vars_string t ~scope ~dir ?bindings s = + expand_vars t ~mode:Single ~scope ~dir ?bindings s + |> Value.to_string ~dir + +let expand_vars_path t ~scope ~dir ?bindings s = + expand_vars t ~mode:Single ~scope ~dir ?bindings s + |> Value.to_path ~error_loc:(String_with_vars.loc s) ~dir let expand_and_eval_set t ~scope ~dir ?bindings set ~standard = let open Build.O in - let f = expand_vars_string t ~scope ~dir ?bindings in let parse ~loc:_ s = s in - let (syntax, files) = Ordered_set_lang.Unexpanded.files set ~f in - match String.Set.to_list files with + let (syntax, files) = + let f = expand_vars_path t ~scope ~dir ?bindings in + Ordered_set_lang.Unexpanded.files set ~f in + let f = expand_vars t ~mode:Many ~scope ~dir ?bindings in + match Path.Set.to_list files with | [] -> let set = - Ordered_set_lang.Unexpanded.expand set ~files_contents:String.Map.empty ~f + Ordered_set_lang.Unexpanded.expand set ~dir + ~files_contents:Path.Map.empty ~f in standard >>^ fun standard -> Ordered_set_lang.String.eval set ~standard ~parse - | files -> - let paths = List.map files ~f:(Path.relative dir) in + | paths -> Build.fanout standard (Build.all (List.map paths ~f:(fun f -> Build.read_sexp f syntax))) >>^ fun (standard, sexps) -> - let files_contents = List.combine files sexps |> String.Map.of_list_exn in - let set = Ordered_set_lang.Unexpanded.expand set ~files_contents ~f in + let files_contents = List.combine paths sexps |> Path.Map.of_list_exn in + let set = Ordered_set_lang.Unexpanded.expand set ~dir ~files_contents ~f in Ordered_set_lang.String.eval set ~standard ~parse module Env = struct @@ -560,39 +559,225 @@ module Scope_key = struct sprintf "%s@%s" key (Dune_project.Name.encode scope) end +type targets = + | Static of Path.t list + | Infer + | Alias + +module Expander : sig + module Resolved_forms : sig + type t + + (* Failed resolutions *) + val failures : t -> fail list + + (* All "name" for %{lib:name:...}/%{lib-available:name} forms *) + val lib_deps : t -> Build.lib_deps + + (* Static deps from %{...} variables. For instance %{exe:...} *) + val sdeps : t -> Path.Set.t + + (* Dynamic deps from %{...} variables. For instance %{read:...} *) + val ddeps : t -> (unit, Value.t list) Build.t String.Map.t + end + + type sctx = t + + val with_expander + : sctx + -> dir:Path.t + -> dep_kind:Build.lib_dep_kind + -> scope:Scope.t + -> targets_written_by_user:targets + -> map_exe:(Path.t -> Path.t) + -> bindings:Pform.Map.t + -> f:(Value.t list option String_with_vars.expander -> 'a) + -> 'a * Resolved_forms.t +end = struct + module Resolved_forms = struct + type t = + { (* Failed resolutions *) + mutable failures : fail list + ; (* All "name" for %{lib:name:...}/%{lib-available:name} forms *) + mutable lib_deps : Build.lib_deps + ; (* Static deps from %{...} variables. For instance %{exe:...} *) + mutable sdeps : Path.Set.t + ; (* Dynamic deps from %{...} variables. For instance %{read:...} *) + mutable ddeps : (unit, Value.t list) Build.t String.Map.t + } + + let failures t = t.failures + let lib_deps t = t.lib_deps + let sdeps t = t.sdeps + let ddeps t = t.ddeps + + let empty () = + { failures = [] + ; lib_deps = String.Map.empty + ; sdeps = Path.Set.empty + ; ddeps = String.Map.empty + } + + let add_lib_dep acc lib kind = + acc.lib_deps <- String.Map.add acc.lib_deps lib kind + + let add_fail acc fail = + acc.failures <- fail :: acc.failures; + None + + let add_ddep acc ~key dep = + acc.ddeps <- String.Map.add acc.ddeps key dep; + None + end + + type sctx = t + + let path_exp path = [Value.Path path] + let str_exp str = [Value.String str] + + let parse_lib_file ~loc s = + match String.lsplit2 s ~on:':' with + | None -> + Loc.fail loc "invalid %%{lib:...} form: %s" s + | Some x -> x + + open Build.O + + let expander ~acc sctx ~dir ~dep_kind ~scope ~targets_written_by_user + ~map_exe ~bindings pform syntax_version = + let loc = String_with_vars.Var.loc pform in + let key = String_with_vars.Var.full_name pform in + let res = + Pform.Map.expand bindings pform syntax_version + |> Option.bind ~f:(function + | Pform.Expansion.Var (Values l) -> Some l + | Macro (Ocaml_config, s) -> Some (expand_ocaml_config sctx pform s) + | Var Project_root -> Some [Value.Dir (Scope.root scope)] + | Var (First_dep | Deps | Named_local) -> None + | Var Targets -> + begin match targets_written_by_user with + | Infer -> + Loc.fail loc "You cannot use %s with inferred rules." + (String_with_vars.Var.describe pform) + | Alias -> + Loc.fail loc "You cannot use %s in aliases." + (String_with_vars.Var.describe pform) + | Static l -> + Some (Value.L.dirs l) (* XXX hack to signal no dep *) + end + | Macro (Exe, s) -> Some (path_exp (map_exe (Path.relative dir s))) + | Macro (Dep, s) -> Some (path_exp (Path.relative dir s)) + | Macro (Bin, s) -> begin + let sctx = host sctx in + match Artifacts.binary (artifacts sctx) s with + | Ok path -> Some (path_exp path) + | Error e -> + Resolved_forms.add_fail acc + ({ fail = fun () -> Action.Prog.Not_found.raise e }) + end + | Macro (Lib, s) -> begin + let lib_dep, file = parse_lib_file ~loc s in + Resolved_forms.add_lib_dep acc lib_dep dep_kind; + match + Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file + with + | Ok path -> Some (path_exp path) + | Error fail -> Resolved_forms.add_fail acc fail + end + | Macro (Libexec, s) -> begin + let sctx = host sctx in + let lib_dep, file = parse_lib_file ~loc s in + Resolved_forms.add_lib_dep acc lib_dep dep_kind; + match + Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file + with + | Error fail -> Resolved_forms.add_fail acc fail + | Ok path -> + if not Sys.win32 || Filename.extension s = ".exe" then begin + Some (path_exp path) + end else begin + let path_exe = Path.extend_basename path ~suffix:".exe" in + let dep = + Build.if_file_exists path_exe + ~then_:(Build.path path_exe >>^ fun _ -> + path_exp path_exe) + ~else_:(Build.path path >>^ fun _ -> + path_exp path) + in + Resolved_forms.add_ddep acc ~key dep + end + end + | Macro (Lib_available, s) -> begin + let lib = s in + Resolved_forms.add_lib_dep acc lib Optional; + Some (str_exp (string_of_bool ( + Lib.DB.available (Scope.libs scope) lib))) + end + | Macro (Version, s) -> begin + match Package.Name.Map.find (Scope.project scope).packages + (Package.Name.of_string s) with + | Some p -> + let x = + Pkg_version.read sctx p >>^ function + | None -> [Value.String ""] + | Some s -> [String s] + in + Resolved_forms.add_ddep acc ~key x + | None -> + Resolved_forms.add_fail acc { fail = fun () -> + Loc.fail loc + "Package %S doesn't exist in the current project." s + } + end + | Macro (Read, s) -> begin + let path = Path.relative dir s in + let data = + Build.contents path + >>^ fun s -> [Value.String s] + in + Resolved_forms.add_ddep acc ~key data + end + | Macro (Read_lines, s) -> begin + let path = Path.relative dir s in + let data = + Build.lines_of path + >>^ Value.L.strings + in + Resolved_forms.add_ddep acc ~key data + end + | Macro (Read_strings, s) -> begin + let path = Path.relative dir s in + let data = + Build.strings path + >>^ Value.L.strings + in + Resolved_forms.add_ddep acc ~key data + end + | Macro (Path_no_dep, s) -> Some [Value.Dir (Path.relative dir s)]) + in + Option.iter res ~f:(fun v -> + acc.sdeps <- Path.Set.union + (Path.Set.of_list (Value.L.deps_only v)) acc.sdeps + ); + res + + let with_expander sctx ~dir ~dep_kind ~scope ~targets_written_by_user + ~map_exe ~bindings ~f = + let acc = Resolved_forms.empty () in + ( f (expander ~acc sctx ~dir ~dep_kind ~scope ~targets_written_by_user ~map_exe ~bindings) + , acc + ) +end + module Action = struct open Build.O module U = Action.Unexpanded - type targets = + type nonrec targets = targets = | Static of Path.t list | Infer | Alias - type resolved_forms = - { (* Failed resolutions *) - mutable failures : fail list - ; (* All "name" for %{lib:name:...}/%{lib-available:name} forms *) - mutable lib_deps : Build.lib_deps - ; (* Static deps from %{...} variables. For instance %{exe:...} *) - mutable sdeps : Path.Set.t - ; (* Dynamic deps from %{...} variables. For instance %{read:...} *) - mutable ddeps : (unit, Value.t list) Build.t String.Map.t - } - - let add_lib_dep acc lib kind = - acc.lib_deps <- String.Map.add acc.lib_deps lib kind - - let add_fail acc fail = - acc.failures <- fail :: acc.failures; - None - - let add_ddep acc ~key dep = - acc.ddeps <- String.Map.add acc.ddeps key dep; - None - - let path_exp path = [Value.Path path] - let str_exp str = [Value.String str] let map_exe sctx = match sctx.host with @@ -604,140 +789,10 @@ module Action = struct Path.append host.context.build_dir exe | _ -> exe - let parse_lib_file ~loc s = - match String.lsplit2 s ~on:':' with - | None -> - Loc.fail loc "invalid %%{lib:...} form: %s" s - | Some x -> x - let expand_step1 sctx ~dir ~dep_kind ~scope ~targets_written_by_user ~map_exe ~bindings t = - let acc = - { failures = [] - ; lib_deps = String.Map.empty - ; sdeps = Path.Set.empty - ; ddeps = String.Map.empty - } - in - let expand pform syntax_version = - let loc = String_with_vars.Var.loc pform in - let key = String_with_vars.Var.full_name pform in - let res = - Pform.Map.expand bindings ~syntax_version ~pform - |> Option.bind ~f:(function - | Pform.Expansion.Var (Values l) -> Some l - | Macro (Ocaml_config, s) -> Some (expand_ocaml_config sctx pform s) - | Var Project_root -> Some [Value.Dir (Scope.root scope)] - | Var (First_dep | Deps | Named_local) -> None - | Var Targets -> - begin match targets_written_by_user with - | Infer -> - Loc.fail loc "You cannot use %s with inferred rules." - (String_with_vars.Var.describe pform) - | Alias -> - Loc.fail loc "You cannot use %s in aliases." - (String_with_vars.Var.describe pform) - | Static l -> - Some (Value.L.dirs l) (* XXX hack to signal no dep *) - end - | Macro (Exe, s) -> Some (path_exp (map_exe (Path.relative dir s))) - | Macro (Dep, s) -> Some (path_exp (Path.relative dir s)) - | Macro (Bin, s) -> begin - let sctx = host sctx in - match Artifacts.binary (artifacts sctx) s with - | Ok path -> Some (path_exp path) - | Error e -> - add_fail acc - ({ fail = fun () -> Action.Prog.Not_found.raise e }) - end - | Macro (Lib, s) -> begin - let lib_dep, file = parse_lib_file ~loc s in - add_lib_dep acc lib_dep dep_kind; - match - Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file - with - | Ok path -> Some (path_exp path) - | Error fail -> add_fail acc fail - end - | Macro (Libexec, s) -> begin - let sctx = host sctx in - let lib_dep, file = parse_lib_file ~loc s in - add_lib_dep acc lib_dep dep_kind; - match - Artifacts.file_of_lib (artifacts sctx) ~loc ~lib:lib_dep ~file - with - | Error fail -> add_fail acc fail - | Ok path -> - if not Sys.win32 || Filename.extension s = ".exe" then begin - Some (path_exp path) - end else begin - let path_exe = Path.extend_basename path ~suffix:".exe" in - let dep = - Build.if_file_exists path_exe - ~then_:(Build.path path_exe >>^ fun _ -> - path_exp path_exe) - ~else_:(Build.path path >>^ fun _ -> - path_exp path) - in - add_ddep acc ~key dep - end - end - | Macro (Lib_available, s) -> begin - let lib = s in - add_lib_dep acc lib Optional; - Some (str_exp (string_of_bool ( - Lib.DB.available (Scope.libs scope) lib))) - end - | Macro (Version, s) -> begin - match Package.Name.Map.find (Scope.project scope).packages - (Package.Name.of_string s) with - | Some p -> - let x = - Pkg_version.read sctx p >>^ function - | None -> [Value.String ""] - | Some s -> [String s] - in - add_ddep acc ~key x - | None -> - add_fail acc { fail = fun () -> - Loc.fail loc - "Package %S doesn't exist in the current project." s - } - end - | Macro (Read, s) -> begin - let path = Path.relative dir s in - let data = - Build.contents path - >>^ fun s -> [Value.String s] - in - add_ddep acc ~key data - end - | Macro (Read_lines, s) -> begin - let path = Path.relative dir s in - let data = - Build.lines_of path - >>^ Value.L.strings - in - add_ddep acc ~key data - end - | Macro (Read_strings, s) -> begin - let path = Path.relative dir s in - let data = - Build.strings path - >>^ Value.L.strings - in - add_ddep acc ~key data - end - | Macro (Path_no_dep, s) -> Some [Value.Dir (Path.relative dir s)]) - in - Option.iter res ~f:(fun v -> - acc.sdeps <- Path.Set.union - (Path.Set.of_list (Value.L.deps_only v)) acc.sdeps - ); - res - in - let t = U.partial_expand t ~dir ~map_exe ~f:expand in - (t, acc) + Expander.with_expander sctx ~dir ~dep_kind ~scope ~targets_written_by_user ~map_exe ~bindings + ~f:(fun f -> U.partial_expand t ~dir ~map_exe ~f) let expand_step2 ~dir ~dynamic_expansions ~bindings ~(deps_written_by_user : Path.t Jbuild.Bindings.t) @@ -748,7 +803,7 @@ module Action = struct match String.Map.find dynamic_expansions key with | Some _ as opt -> opt | None -> - Option.map (Pform.Map.expand bindings ~syntax_version ~pform) ~f:(function + Option.map (Pform.Map.expand bindings pform syntax_version) ~f:(function | Var Named_local -> begin match Jbuild.Bindings.find deps_written_by_user key with | None -> @@ -823,13 +878,13 @@ module Action = struct sprintf "- %s" (Utils.describe_target target)) |> String.concat ~sep:"\n")); let build = - Build.record_lib_deps_simple forms.lib_deps + Build.record_lib_deps_simple (Expander.Resolved_forms.lib_deps forms) >>> - Build.path_set (Path.Set.union deps forms.sdeps) + Build.path_set (Path.Set.union deps (Expander.Resolved_forms.sdeps forms)) >>> Build.arr (fun paths -> ((), paths)) >>> - let ddeps = String.Map.to_list forms.ddeps in + let ddeps = String.Map.to_list (Expander.Resolved_forms.ddeps forms) in Build.first (Build.all (List.map ddeps ~f:snd)) >>^ (fun (vals, deps_written_by_user) -> let dynamic_expansions = @@ -854,7 +909,7 @@ module Action = struct >>> Build.action_dyn () ~dir ~targets in - match forms.failures with + match Expander.Resolved_forms.failures forms with | [] -> build | fail :: _ -> Build.fail fail >>> build end