From aa3e8f7aa5ac5b5c56597befa610db102d622880 Mon Sep 17 00:00:00 2001 From: Antonio Nuno Monteiro Date: Sun, 5 Jul 2026 19:38:27 -0700 Subject: [PATCH] fix(jsoo): keep archive dirs for interface-only libraries Keep the generated JSOO archive directory when the library has no implementation modules. Fixes repeated rebuilds for interface-only libraries. Signed-off-by: Antonio Nuno Monteiro --- src/dune_rules/gen_rules.ml | 11 +++- src/dune_rules/jsoo/jsoo_archive_rules.ml | 56 +++++++++++++++++++ src/dune_rules/jsoo/jsoo_archive_rules.mli | 6 ++ .../test-cases/jsoo/without_implem.t/run.t | 2 - 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/dune_rules/gen_rules.ml b/src/dune_rules/gen_rules.ml index 340d5bad350..f114f797653 100644 --- a/src/dune_rules/gen_rules.ml +++ b/src/dune_rules/gen_rules.ml @@ -578,6 +578,8 @@ let gen_rules_regular_directory (sctx : Super_context.t Memo.t) ~src_dir ~compon dir_status ~jsoo_enabled:Jsoo_rules.jsoo_enabled ~dir + and+ jsoo_archive_build_only_sub_dirs = + Jsoo_archive_rules.build_only_sub_dirs_for_dir_status sctx dir_status ~dir in let allowed_subdirs = let automatic = Automatic_subdir.subdirs components in @@ -599,6 +601,13 @@ let gen_rules_regular_directory (sctx : Super_context.t Memo.t) ~src_dir ~compon in Filename.Set.union automatic toplevel in + let build_dir_only_sub_dirs = + Gen_rules.Build_only_sub_dirs.union + (Gen_rules.Build_only_sub_dirs.singleton + ~dir + (Subdir_set.of_set allowed_subdirs)) + jsoo_archive_build_only_sub_dirs + in fun rules -> let rules = let+ automatic_subdir_rules = @@ -624,7 +633,7 @@ let gen_rules_regular_directory (sctx : Super_context.t Memo.t) ~src_dir ~compon compile_commands_rules) rules in - Gen_rules.rules_for ~dir ~directory_targets ~allowed_subdirs rules + Gen_rules.Rules.create ~build_dir_only_sub_dirs ~directory_targets rules in match dir_status with | Lock_dir _ -> Gen_rules.rules_here Gen_rules.Rules.empty diff --git a/src/dune_rules/jsoo/jsoo_archive_rules.ml b/src/dune_rules/jsoo/jsoo_archive_rules.ml index b182364eb64..7c5333776bb 100644 --- a/src/dune_rules/jsoo/jsoo_archive_rules.ml +++ b/src/dune_rules/jsoo/jsoo_archive_rules.ml @@ -1,5 +1,6 @@ open Import open Memo.O +module Gen_rules = Build_config.Gen_rules module Library_key = struct type t = Path.Build.t * string @@ -29,6 +30,61 @@ let find_library ~expander ~dir ~lib_name = | _ -> Memo.return None) ;; +let archive_dir_for_library (lib : Library.t) ~sctx ~dir = + let+ ocaml = Context.ocaml (Super_context.context sctx) in + let modes = Mode_conf.Lib.Set.eval lib.modes ~has_native:ocaml.lib_config.has_native in + let has_byte_archive = + modes.ocaml.byte + && + match lib.kind with + | Lib_kind.Virtual | Lib_kind.Parameter -> false + | Lib_kind.Dune_file _ -> true + in + Option.some_if has_byte_archive (Obj_dir.jsoo_dir (Library.obj_dir ~dir lib)) +;; + +let archive_dir_to_build_only_sub_dirs = function + | None -> Gen_rules.Build_only_sub_dirs.empty + | Some dir -> + Gen_rules.Build_only_sub_dirs.singleton + ~dir:(Path.Build.parent_exn dir) + (Subdir_set.of_list [ Path.Build.basename dir ]) +;; + +let build_only_sub_dirs_for_stanzas sctx ~dir stanzas = + let* sctx = sctx in + Memo.List.fold_left + stanzas + ~init:Gen_rules.Build_only_sub_dirs.empty + ~f:(fun build_dir_only_sub_dirs stanza -> + match Stanza.repr stanza with + | Library.T lib -> + let+ archive_dir = archive_dir_for_library lib ~sctx ~dir in + Gen_rules.Build_only_sub_dirs.union + build_dir_only_sub_dirs + (archive_dir_to_build_only_sub_dirs archive_dir) + | _ -> Memo.return build_dir_only_sub_dirs) +;; + +let build_only_sub_dirs_for_dir_status sctx (dir_status : Dir_status.t) ~dir = + match dir_status with + | Lock_dir _ | Generated | Source_only _ | Is_component_of_a_group_but_not_the_root _ -> + Memo.return Gen_rules.Build_only_sub_dirs.empty + | Standalone (_, dune_file) -> + Dune_file.stanzas dune_file >>= build_only_sub_dirs_for_stanzas sctx ~dir + | Group_root { components; dune_file; _ } -> + let* stanzas = Dune_file.stanzas dune_file in + let* init = build_only_sub_dirs_for_stanzas sctx ~dir stanzas in + components + >>= Memo.List.fold_left + ~init + ~f:(fun acc { Dir_status.Group_component.dir; stanzas; _ } -> + let+ build_dir_only_sub_dirs = + build_only_sub_dirs_for_stanzas sctx ~dir stanzas + in + Gen_rules.Build_only_sub_dirs.union acc build_dir_only_sub_dirs) +;; + let library_cctx_memo = Memo.create "jsoo-library-cctx" diff --git a/src/dune_rules/jsoo/jsoo_archive_rules.mli b/src/dune_rules/jsoo/jsoo_archive_rules.mli index 0e48929940e..e89bdd33142 100644 --- a/src/dune_rules/jsoo/jsoo_archive_rules.mli +++ b/src/dune_rules/jsoo/jsoo_archive_rules.mli @@ -5,4 +5,10 @@ type lib_archive_rules = | Root | Rules of Rules.t +val build_only_sub_dirs_for_dir_status + : Super_context.t Memo.t + -> Dir_status.t + -> dir:Path.Build.t + -> Build_config.Gen_rules.Build_only_sub_dirs.t Memo.t + val lib_archive_rules_for_dir : dir:Path.Build.t -> lib_archive_rules Memo.t diff --git a/test/blackbox-tests/test-cases/jsoo/without_implem.t/run.t b/test/blackbox-tests/test-cases/jsoo/without_implem.t/run.t index 0c67f8d0b0c..d178c3eb00a 100644 --- a/test/blackbox-tests/test-cases/jsoo/without_implem.t/run.t +++ b/test/blackbox-tests/test-cases/jsoo/without_implem.t/run.t @@ -43,8 +43,6 @@ JSOO archive rules for interface-only libraries are not spuriously invalidated main.bc.js should not rebuild $ dune build --display=short main.bc.js - js_of_ocaml .interface.objs/jsoo/effects=disabled/interface.cma.js $ dune build --display=short main.bc.js - js_of_ocaml .interface.objs/jsoo/effects=disabled/interface.cma.js