diff --git a/doc/changes/8447.md b/doc/changes/8447.md new file mode 100644 index 00000000000..9d47c9d6013 --- /dev/null +++ b/doc/changes/8447.md @@ -0,0 +1,2 @@ +- Do not ignore `(formatting ..)` settings in context or workspace files + (#8447, @rgrinberg) diff --git a/src/dune_rules/compilation_context.ml b/src/dune_rules/compilation_context.ml index f8e96dc9a6b..ac1ddb43de8 100644 --- a/src/dune_rules/compilation_context.ml +++ b/src/dune_rules/compilation_context.ml @@ -180,7 +180,7 @@ let create and+ bin_annot = match bin_annot with | Some b -> Memo.return b - | None -> Super_context.bin_annot super_context ~dir:(Obj_dir.dir obj_dir) + | None -> Env_stanza_db.bin_annot ~dir:(Obj_dir.dir obj_dir) in { super_context ; scope diff --git a/src/dune_rules/env_node.ml b/src/dune_rules/env_node.ml index 845c5fcc7c5..5429d3415ef 100644 --- a/src/dune_rules/env_node.ml +++ b/src/dune_rules/env_node.ml @@ -1,13 +1,5 @@ open Import -module Odoc = struct - type warnings = Dune_env.Odoc.warnings = - | Fatal - | Nonfatal - - type t = { warnings : warnings } -end - type t = { scope : Scope.t ; local_binaries : File_binding.Expanded.t list Memo.Lazy.t @@ -16,13 +8,9 @@ type t = ; link_flags : Link_flags.t Memo.Lazy.t ; external_env : Env.t Memo.Lazy.t ; artifacts : Artifacts.t Memo.Lazy.t - ; inline_tests : Dune_env.Inline_tests.t Memo.Lazy.t ; menhir_flags : string list Action_builder.t Memo.Lazy.t - ; odoc : Odoc.t Action_builder.t Memo.Lazy.t ; js_of_ocaml : string list Action_builder.t Js_of_ocaml.Env.t Memo.Lazy.t ; coq_flags : Coq_flags.t Action_builder.t Memo.Lazy.t - ; format_config : Format_config.t Memo.Lazy.t - ; bin_annot : bool Memo.Lazy.t } let scope t = t.scope @@ -32,18 +20,9 @@ let foreign_flags t = t.foreign_flags let link_flags t = Memo.Lazy.force t.link_flags let external_env t = Memo.Lazy.force t.external_env let artifacts t = Memo.Lazy.force t.artifacts -let inline_tests t = Memo.Lazy.force t.inline_tests let js_of_ocaml t = Memo.Lazy.force t.js_of_ocaml let menhir_flags t = Memo.Lazy.force t.menhir_flags |> Action_builder.of_memo_join -let format_config t = Memo.Lazy.force t.format_config - -let set_format_config t format_config = - { t with format_config = Memo.Lazy.of_val format_config } -;; - -let odoc t = Memo.Lazy.force t.odoc |> Action_builder.of_memo_join let coq_flags t = Memo.Lazy.force t.coq_flags -let bin_annot t = Memo.Lazy.force t.bin_annot let expand_str_lazy expander sw = match String_with_vars.text_only sw with @@ -66,7 +45,6 @@ let make ~default_context_flags ~default_env ~default_artifacts - ~default_bin_annot = let open Memo.O in let config = Dune_env.find config_stanza ~profile in @@ -77,17 +55,6 @@ let make | Some t -> Memo.Lazy.force t >>= field) >>= extend) in - let inherited_if_absent ~field ~root ~f_absent = - Memo.lazy_ (fun () -> - match root with - | Some x -> Memo.return x - | None -> - (match inherit_from with - | None -> f_absent None - | Some t -> - let* field = Memo.Lazy.force t >>= field in - f_absent (Some field))) - in let config_binaries = Option.value config.binaries ~default:[] in let local_binaries = Memo.lazy_ (fun () -> @@ -128,18 +95,6 @@ let make ~default:flags ~eval:(Expander.expand_and_eval_set expander)) in - let inline_tests = - match config with - | { inline_tests = Some s; _ } -> Memo.Lazy.of_val s - | { inline_tests = None; _ } -> - inherited - ~field:inline_tests - Memo.return - ~root: - (if Profile.is_inline_test profile - then Dune_env.Inline_tests.Enabled - else Disabled) - in let js_of_ocaml = inherited ~field:(fun t -> js_of_ocaml t) @@ -195,22 +150,6 @@ let make let+ expander = Memo.Lazy.force expander in Expander.expand_and_eval_set expander menhir_flags ~standard:flags) in - let odoc = - let open Odoc in - let root = - (* DUNE4: Enable for dev profile in the future *) - Action_builder.return { warnings = Nonfatal } - in - inherited - ~field:(fun t -> Memo.return (odoc t)) - ~root - (fun warnings -> - Memo.return - @@ - let open Action_builder.O in - let+ { warnings } = warnings in - { warnings = Option.value config.odoc.warnings ~default:warnings }) - in let coq_flags : Coq_flags.t Action_builder.t Memo.Lazy.t = inherited ~field:coq_flags @@ -231,21 +170,6 @@ let make in { Coq_flags.coq_flags; coqdoc_flags }) in - let format_config = - inherited_if_absent - ~field:format_config - ~root:config.format_config - ~f_absent:(function - | Some x -> Memo.return x - | None -> - Code_error.raise - "format config should always have a default value taken from the project root" - []) - in - let bin_annot = - inherited ~field:bin_annot ~root:default_bin_annot (fun default -> - Memo.return (Option.value ~default config.bin_annot)) - in { scope ; ocaml_flags ; foreign_flags @@ -253,12 +177,8 @@ let make ; external_env ; artifacts ; local_binaries - ; inline_tests ; js_of_ocaml ; menhir_flags - ; odoc ; coq_flags - ; format_config - ; bin_annot } ;; diff --git a/src/dune_rules/env_node.mli b/src/dune_rules/env_node.mli index 940400550a0..7256d4cb36e 100644 --- a/src/dune_rules/env_node.mli +++ b/src/dune_rules/env_node.mli @@ -2,14 +2,6 @@ open Import -module Odoc : sig - type warnings = Dune_env.Odoc.warnings = - | Fatal - | Nonfatal - - type t = { warnings : warnings } -end - type t val make @@ -24,13 +16,11 @@ val make -> default_context_flags:string list Action_builder.t Foreign_language.Dict.t -> default_env:Env.t -> default_artifacts:Artifacts.t - -> default_bin_annot:bool -> t val scope : t -> Scope.t val external_env : t -> Env.t Memo.t val ocaml_flags : t -> Ocaml_flags.t Memo.t -val inline_tests : t -> Dune_env.Inline_tests.t Memo.t val js_of_ocaml : t -> string list Action_builder.t Js_of_ocaml.Env.t Memo.t val foreign_flags : t -> string list Action_builder.t Foreign_language.Dict.t val link_flags : t -> Link_flags.t Memo.t @@ -40,9 +30,5 @@ val link_flags : t -> Link_flags.t Memo.t val local_binaries : t -> File_binding.Expanded.t list Memo.t val artifacts : t -> Artifacts.t Memo.t -val odoc : t -> Odoc.t Action_builder.t val coq_flags : t -> Coq_flags.t Action_builder.t Memo.t val menhir_flags : t -> string list Action_builder.t -val format_config : t -> Format_config.t Memo.t -val set_format_config : t -> Format_config.t -> t -val bin_annot : t -> bool Memo.t diff --git a/src/dune_rules/env_stanza_db.ml b/src/dune_rules/env_stanza_db.ml new file mode 100644 index 00000000000..d5a9a8a923e --- /dev/null +++ b/src/dune_rules/env_stanza_db.ml @@ -0,0 +1,99 @@ +open Import +open Memo.O + +module Node = struct + type t = + { value : Dune_env.t + ; parent : t option Memo.t + } + + let by_context dir = + let open Memo.O in + let+ context = Context.DB.by_dir dir in + let { Context.Env_nodes.context; workspace } = Context.env_nodes context in + match context, workspace with + | None, None -> None + | Some value, None | None, Some value -> Some { value; parent = Memo.return None } + | Some context, Some workspace -> + Some + { value = context + ; parent = Memo.return (Some { value = workspace; parent = Memo.return None }) + } + ;; + + let in_dir ~dir = + Only_packages.stanzas_in_dir dir + >>| function + | None -> None + | Some stanzas -> + List.find_map stanzas.stanzas ~f:(function + | Dune_env.T config -> Some config + | _ -> None) + ;; + + let rec by_dir dir = + let parent = + let* scope = Scope.DB.find_by_dir dir in + if Path.Build.equal dir (Scope.root scope) + then by_context dir + else ( + match Path.Build.parent dir with + | None -> by_context dir + | Some parent -> by_dir parent) + in + in_dir ~dir + >>= function + | Some value -> Memo.return (Some { value; parent }) + | None -> parent + ;; +end + +let value ~default ~f = + let rec loop = function + | None -> Memo.return default + | Some { Node.value; parent } -> + let* next = + f value + >>| function + | Some x -> `Ok x + | None -> `Parent + in + (match next with + | `Ok x -> Memo.return x + | `Parent -> parent >>= loop) + in + fun ~dir -> Node.by_dir dir >>= loop +;; + +let profile ~dir = + let name, _ = Path.Build.extract_build_context_exn dir in + let context = Context_name.of_string name in + Per_context.profile context +;; + +let value ~default ~dir ~f = + let profile = lazy (profile ~dir) in + value ~default ~dir ~f:(fun stanza -> + let* profile = Lazy.force profile in + match Dune_env.find_opt stanza ~profile with + | None -> Memo.return None + | Some stanza -> f stanza) +;; + +let bin_annot ~dir = + value ~default:true ~dir ~f:(fun (t : Dune_env.config) -> Memo.return t.bin_annot) +;; + +let inline_tests ~dir = + value ~default:None ~dir ~f:(fun (t : Dune_env.config) -> + Memo.return + @@ + match t.inline_tests with + | None -> None + | Some s -> Some (Some s)) + >>= function + | Some s -> Memo.return s + | None -> + let+ profile = profile ~dir in + if Profile.is_inline_test profile then Dune_env.Inline_tests.Enabled else Disabled +;; diff --git a/src/dune_rules/env_stanza_db.mli b/src/dune_rules/env_stanza_db.mli new file mode 100644 index 00000000000..7c508e04093 --- /dev/null +++ b/src/dune_rules/env_stanza_db.mli @@ -0,0 +1,10 @@ +open Import + +val value + : default:'a + -> dir:Path.Build.t + -> f:(Dune_env.config -> 'a option Memo.t) + -> 'a Memo.t + +val bin_annot : dir:Path.Build.t -> bool Memo.t +val inline_tests : dir:Path.Build.t -> Dune_env.Inline_tests.t Memo.t diff --git a/src/dune_rules/format_rules.ml b/src/dune_rules/format_rules.ml index befc6bae7e3..fd614669f20 100644 --- a/src/dune_rules/format_rules.ml +++ b/src/dune_rules/format_rules.ml @@ -154,29 +154,53 @@ let gen_rules_output Rules.Produce.Alias.add_deps alias_formatted (Action_builder.return ()) ;; +let format_config ~dir = + let open Memo.O in + let+ value = + Env_stanza_db.value ~default:None ~dir ~f:(fun (t : Dune_env.config) -> + Memo.return + @@ + match t.format_config with + | Some x -> Some (Some x) + | None -> None) + and+ default = + (* we always force the default for error checking *) + Path.Build.drop_build_context_exn dir + |> Source_tree.nearest_dir + >>| Source_tree.Dir.project + >>| Dune_project.format_config + in + Option.value value ~default +;; + +let with_config ~dir f = + let open Memo.O in + let* config = format_config ~dir in + if Format_config.is_empty config + then + (* CR-rgrinberg: this [is_empty] check is weird. We should use [None] + to represent that no settings have been set. *) + Memo.return () + else f config +;; + let gen_rules sctx ~output_dir = let open Memo.O in let dir = Path.Build.parent_exn output_dir in - let* config = Super_context.env_node sctx ~dir >>= Env_node.format_config in - Memo.when_ - (not (Format_config.is_empty config)) - (fun () -> - let* expander = Super_context.expander sctx ~dir in - let* scope = Scope.DB.find_by_dir output_dir in - let project = Scope.project scope in - let dialects = Dune_project.dialects project in - let version = Dune_project.dune_version project in - gen_rules_output sctx config ~version ~dialects ~expander ~output_dir) + with_config ~dir (fun config -> + let* expander = Super_context.expander sctx ~dir in + (* CR-rgrinberg: initializing the library database seems unnecessary here *) + let* scope = Scope.DB.find_by_dir output_dir in + let project = Scope.project scope in + let dialects = Dune_project.dialects project in + let version = Dune_project.dune_version project in + gen_rules_output sctx config ~version ~dialects ~expander ~output_dir) ;; -let setup_alias sctx ~dir = - let open Memo.O in - let* config = Super_context.env_node sctx ~dir >>= Env_node.format_config in - Memo.when_ - (not (Format_config.is_empty config)) - (fun () -> - let output_dir = Path.Build.relative dir formatted_dir_basename in - let alias = Alias.fmt ~dir in - let alias_formatted = Alias.fmt ~dir:output_dir in - Rules.Produce.Alias.add_deps alias (Action_builder.dep (Dep.alias alias_formatted))) +let setup_alias ~dir = + with_config ~dir (fun (_ : Format_config.t) -> + let output_dir = Path.Build.relative dir formatted_dir_basename in + let alias = Alias.fmt ~dir in + let alias_formatted = Alias.fmt ~dir:output_dir in + Rules.Produce.Alias.add_deps alias (Action_builder.dep (Dep.alias alias_formatted))) ;; diff --git a/src/dune_rules/format_rules.mli b/src/dune_rules/format_rules.mli index fefaacc5c09..84508393b2b 100644 --- a/src/dune_rules/format_rules.mli +++ b/src/dune_rules/format_rules.mli @@ -9,6 +9,6 @@ val gen_rules : Super_context.t -> output_dir:Path.Build.t -> unit Memo.t (** This must be called from the main directory, i.e. the ones containing the source files and the the [formatted_dir_basename] sub-directory. *) -val setup_alias : Super_context.t -> dir:Path.Build.t -> unit Memo.t +val setup_alias : dir:Path.Build.t -> unit Memo.t val formatted_dir_basename : Filename.t diff --git a/src/dune_rules/gen_rules.ml b/src/dune_rules/gen_rules.ml index f939b462449..a19426c27a2 100644 --- a/src/dune_rules/gen_rules.ml +++ b/src/dune_rules/gen_rules.ml @@ -300,7 +300,7 @@ let gen_rules_for_stanzas ;; let gen_format_and_cram_rules sctx ~expander ~dir source_dir = - let+ () = Format_rules.setup_alias sctx ~dir + let+ () = Format_rules.setup_alias ~dir and+ () = Source_tree.Dir.cram_tests source_dir >>= Cram_rules.rules ~sctx ~expander ~dir in diff --git a/src/dune_rules/install_rules.ml b/src/dune_rules/install_rules.ml index d8502b8f18c..98ba1302297 100644 --- a/src/dune_rules/install_rules.ml +++ b/src/dune_rules/install_rules.ml @@ -279,7 +279,7 @@ end = struct in let set_dir m = List.map ~f:(fun (cm_kind, p) -> cm_dir m cm_kind, p) in let+ modules_impl = - let+ bin_annot = Super_context.bin_annot sctx ~dir in + let+ bin_annot = Env_stanza_db.bin_annot ~dir in List.concat_map installable_modules.impl ~f:(fun m -> let cmt_files = match bin_annot with diff --git a/src/dune_rules/odoc.ml b/src/dune_rules/odoc.ml index c385ca6c443..454f5c1887e 100644 --- a/src/dune_rules/odoc.ml +++ b/src/dune_rules/odoc.ml @@ -217,14 +217,27 @@ end = struct let odoc_input t = t end -let odoc_base_flags sctx quiet build_dir = +module Flags = struct + type warnings = Dune_env.Odoc.warnings = + | Fatal + | Nonfatal + + type t = { warnings : warnings } + + let default = { warnings = Nonfatal } + + let get ~dir = + Env_stanza_db.value ~default ~dir ~f:(fun config -> + match config.odoc.warnings with + | None -> Memo.return None + | Some warnings -> Memo.return (Some { warnings })) + |> Action_builder.of_memo + ;; +end + +let odoc_base_flags quiet build_dir = let open Action_builder.O in - let+ conf = - let* env_node = - Action_builder.of_memo @@ Super_context.env_node sctx ~dir:build_dir - in - Env_node.odoc env_node - in + let+ conf = Flags.get ~dir:build_dir in match conf.warnings with | Fatal -> (* if quiet has been passed, we're running odoc on an external @@ -245,7 +258,7 @@ let run_odoc sctx ~dir command ~quiet ~flags_for args = let* () = Action_builder.return () in match flags_for with | None -> Action_builder.return Command.Args.empty - | Some path -> odoc_base_flags sctx quiet path + | Some path -> odoc_base_flags quiet path in let deps = Action_builder.env_var "ODOC_SYNTAX" in let open Action_builder.With_targets.O in diff --git a/src/dune_rules/super_context.ml b/src/dune_rules/super_context.ml index c379a28a576..7b88a1d3618 100644 --- a/src/dune_rules/super_context.ml +++ b/src/dune_rules/super_context.ml @@ -102,7 +102,7 @@ end = struct let extend_expander t ~dir ~expander_for_artifacts = let+ artifacts_host = artifacts_host t ~dir and+ bindings = - let+ inline_tests = get_node t ~dir >>= Env_node.inline_tests in + let+ inline_tests = Env_stanza_db.inline_tests ~dir in let str = Dune_env.Inline_tests.to_string inline_tests in Pform.Map.singleton (Var Inline_tests) [ Value.String str ] in @@ -139,11 +139,7 @@ end = struct let project = Scope.project scope in let inherit_from = if Path.Build.equal dir (Scope.root scope) - then ( - let format_config = Dune_project.format_config project in - Memo.lazy_ (fun () -> - let+ default_env = Memo.Lazy.force t.default_env in - Env_node.set_format_config default_env format_config)) + then Memo.lazy_ (fun () -> Memo.Lazy.force t.default_env) else ( match Path.Build.parent dir with | None -> @@ -181,7 +177,6 @@ end = struct ~default_context_flags ~default_env:t.context_env ~default_artifacts:t.artifacts - ~default_bin_annot:true ;; (* Here we jump through some hoops to construct [t] as well as create a @@ -278,7 +273,6 @@ let add_alias_action t alias ~dir ~loc action = ;; let env_node = Env_tree.get_node -let bin_annot t ~dir = Env_tree.get_node t ~dir >>= Env_node.bin_annot let resolve_program_memo t ~dir ?hint ~loc bin = let* artifacts = Env_tree.artifacts_host t ~dir in @@ -403,7 +397,6 @@ let make_default_env_node ~default_context_flags ~default_env:root_env ~default_artifacts:artifacts - ~default_bin_annot:true in make ~config_stanza:env_nodes.context diff --git a/src/dune_rules/super_context.mli b/src/dune_rules/super_context.mli index 2980d392f2f..c5685164590 100644 --- a/src/dune_rules/super_context.mli +++ b/src/dune_rules/super_context.mli @@ -27,7 +27,6 @@ val context : t -> Context.t val context_env : t -> Env.t val env_node : t -> dir:Path.Build.t -> Env_node.t Memo.t -val bin_annot : t -> dir:Path.Build.t -> bool Memo.t val add_rule : t diff --git a/test/blackbox-tests/test-cases/formatting/disable-dune-file.t b/test/blackbox-tests/test-cases/formatting/disable-dune-file.t index 0df7d25110a..7d7e08ab3ff 100644 --- a/test/blackbox-tests/test-cases/formatting/disable-dune-file.t +++ b/test/blackbox-tests/test-cases/formatting/disable-dune-file.t @@ -36,6 +36,3 @@ Disable foramtting in the root directory using context settings > EOF $ dune build @fmt - File "dune", line 1, characters 0-0: - Error: Files _build/default/dune and _build/default/.formatted/dune differ. - [1]