Skip to content

feat: per-module inter-library dependency filtering (#4572)#14116

Draft
robinbb wants to merge 4 commits intoocaml:mainfrom
robinbb:robinbb-issue-4572-combined-tests
Draft

feat: per-module inter-library dependency filtering (#4572)#14116
robinbb wants to merge 4 commits intoocaml:mainfrom
robinbb:robinbb-issue-4572-combined-tests

Conversation

@robinbb
Copy link
Copy Markdown
Contributor

@robinbb robinbb commented Apr 10, 2026

Summary

Use the already-computed ocamldep output to filter inter-library
dependencies on a per-module basis, resolving #4572.

Previously, when libA depends on libB, every module of libA got a
glob dependency on all .cmi files in libB. Now each module only
depends on .cmi/.cmx files from libraries it actually imports,
eliminating unnecessary recompilation.

  • Modules that don't reference a changed library: 0 recompilations
    (was 2)
  • Unwrapped library consumers referencing only specific modules: 0
    recompilations
    (was 2), via per-file deps on individual .cmi files
  • Transparent aliases (module M = Mylib): correctly propagated
  • Sandboxed builds: unaffected
  • Singleton stanzas, Melange, virtual library implementations: fall back
    to conservative glob deps

Known limitations

  • 4 pre-existing tests show changed cycle-detection behavior due to
    dyn_deps exploring dependency paths differently. These need
    investigation.
  • Single-module stanzas do not benefit (ocamldep is skipped for them);
    this can be addressed in a follow-up.

Test plan

  • dune build @check passes
  • All per-module-lib-deps/ tests pass (13 tests)
  • Safety tests pass: lib-deps-preserved.t, transparent-alias.t,
    sandbox-lib-deps.t, single-module-lib.t
  • Full test suite: no regressions beyond 4 known cycle-detection
    edge cases

Ref: #4572

robinbb added 3 commits April 9, 2026 14:56
…lds (ocaml#4572)

Add baseline tests documenting existing behavior:

- lib-deps-preserved: every non-alias module declares glob deps on its
  library dependencies' .cmi files
- sandbox-lib-deps: sandboxed package builds have dependency libraries'
  .cmi files available when a library depends on another library

Signed-off-by: Robin Bate Boerop <me@robinbb.com>
Add baseline test verifying that incremental builds succeed when a module
re-exports a library via a transparent alias (module M = Mylib) and the
library's interface changes. Regression reported by @Alizter.

Signed-off-by: Robin Bate Boerop <me@robinbb.com>
Add baseline test showing that single-module library consumers are
recompiled when an unused module in a dependency changes. This happens
because dune skips ocamldep for singleton stanzas, preventing future
per-module filtering from determining which libraries the module
actually references.

Signed-off-by: Robin Bate Boerop <me@robinbb.com>
@robinbb robinbb force-pushed the robinbb-issue-4572-combined-tests branch 3 times, most recently from 15c3919 to 2b4ab03 Compare April 10, 2026 07:20
@robinbb robinbb force-pushed the robinbb-issue-4572-combined-tests branch from 2b4ab03 to e273290 Compare April 10, 2026 14:59
…caml#4572)

Use the already-computed ocamldep output to filter inter-library
dependencies on a per-module basis. Each module now only depends on
.cmi/.cmx files from libraries it actually imports, rather than glob
deps on all files from all dependent libraries. This eliminates
unnecessary recompilation when a module in a dependency changes but the
current module doesn't reference that library.

The implementation:

- Add read_immediate_deps_raw_of to ocamldep, returning raw module names
  without filtering against the stanza's module set
- Move Hidden_deps from Includes (library-wide) to per-module in build_cm
- Add Lib_index mapping module names to libraries, computed from
  requires_compile and requires_hidden
- In build_cm, use ocamldep output + Lib_index to determine which
  libraries each module actually needs; fall back to all-library glob
  deps when filtering is not possible (Melange, virtual library
  implementations, singleton stanzas, alias/root modules)
- For local unwrapped libraries, use per-file deps on specific .cmi/.cmx
  files rather than directory-wide globs

Signed-off-by: Robin Bate Boerop <me@robinbb.com>
@robinbb robinbb force-pushed the robinbb-issue-4572-combined-tests branch from e273290 to 31ab29b Compare April 10, 2026 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant