Skip to content

fix: allow rename to overwrite read-only destination on Windows when deduplicating Dune cache#13713

Merged
nojb merged 7 commits intoocaml:mainfrom
Nevor:fix_dune_cache_deduplication_rename_on_windows
Mar 2, 2026
Merged

fix: allow rename to overwrite read-only destination on Windows when deduplicating Dune cache#13713
nojb merged 7 commits intoocaml:mainfrom
Nevor:fix_dune_cache_deduplication_rename_on_windows

Conversation

@Nevor
Copy link
Contributor

@Nevor Nevor commented Mar 2, 2026

In the Dune cache, when a temp artifact already exists in the cache, Dune attempts deduplication by deleting the temp artifact, linking it to the file already in the cache, and then moving the temp artifact to the build directory.

The last step fails on Windows because Dune sets a read-only attribute on the destination file, causing Unix.rename to fail with EACCES in this case. Since the operation fails, Dune does not consider the file cached. Combined with the fact that this seems to happen quite often [1] on Windows, this effectively nullifies the cache speedup.

This PR creates a helper function that removes the read-only attribute on the destination file before trying to overwrite it (similar to the existing win32_unlink) and use it in the deduplication logic of the cache, fixing the issue.

Note: This issue does not exist on Unix. This discrepancy is also being addressed directly on OCaml's side: ocaml/ocaml#14602.

The test dedup.t already exhibits the issue on Windows. The dune_cmd stat hardlinks _build/default/target command returns 1 instead of the expected 3. This PR bumps the result to 2. To make the test completely pass, another issue around Io.portable_hardlink on Windows still needs to be addressed [1].

[1] It seems that the fact that on windows dune always copies files instead of trying to create a hardlink is linked to the fact that this deduplication happen more often on windows. See #13714.

@rgrinberg rgrinberg requested a review from nojb March 2, 2026 14:01
@Nevor Nevor force-pushed the fix_dune_cache_deduplication_rename_on_windows branch from 39f0925 to 8c334c1 Compare March 2, 2026 14:06
Copy link
Collaborator

@nojb nojb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

A changes entry (see doc/changes) is in order, since this is an (important!) bug fix on Windows.

@Nevor Nevor force-pushed the fix_dune_cache_deduplication_rename_on_windows branch from 8c334c1 to 8e9edaf Compare March 2, 2026 14:08
…deduplicating Dune cache

In the Dune cache, when a temp artifact already exists in the cache, Dune attempts deduplication by deleting the temp artifact, linking it to the file already in the cache, and then moving the temp artifact to the build directory.

The last step fails on Windows because Dune sets a read-only attribute on the destination file, causing Unix.rename to fail with EACCES in this case. Since the operation fails, Dune does not consider the file cached. Combined with the fact that this seems to happen quite often [1] on Windows, this effectively nullifies the cache speedup.

This PR creates a helper function that removes the read-only attribute on the destination file before trying to overwrite it (similar to the existing `win32_unlink`) and use it in the deduplication logic of the cache, fixing the issue.

Note: This issue does not exist on Unix. This discrepancy is also being addressed directly on OCaml's side: ocaml/ocaml#14602.

The test dedup.t already exhibits the issue on Windows. The `dune_cmd stat hardlinks _build/default/target` command returns 1 instead of the expected 3. This PR bumps the result to 2. To make the test completely pass, another issue around `Io.portable_hardlink` on Windows still needs to be addressed [1].

[1] It seems that the fact that on windows dune always copies files instead of trying to create a hardlink is linked to the fact that this deduplication happen more often on windows.

Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
@Nevor Nevor force-pushed the fix_dune_cache_deduplication_rename_on_windows branch from a1e109c to b913ccc Compare March 2, 2026 14:41
Nevor added 2 commits March 2, 2026 14:44
Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
@Nevor Nevor force-pushed the fix_dune_cache_deduplication_rename_on_windows branch from b913ccc to 6361b99 Compare March 2, 2026 14:46
@nojb
Copy link
Collaborator

nojb commented Mar 2, 2026

There is an OxCaml error in the CI. @Alizter: any insight?

Co-authored-by: Ali Caglayan <alizter@gmail.com>
Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
@Nevor Nevor force-pushed the fix_dune_cache_deduplication_rename_on_windows branch from 91ddbb4 to 6d36ba6 Compare March 2, 2026 18:47
nojb pushed a commit that referenced this pull request Mar 2, 2026
The `Io.portable_hardlink` function was systematically copying files on
Windows instead of trying to create hard links. Hard links have been
available for a while on NTFS and have also been available for ReFS for
a coupe of years. This availability is not tied to developer mode
capabilities (unlike symlinks), which means we can generally expect a
Windows environment to be able to create hard links.

This PR removes the systematic copy and adds the `EINVAL` error as a
fallback signal in case Dune tries to create a hard link on a filesystem
that does not support it. The later reduces the risk of a breaking
change. Note that a copy fallback could be used when a cross-filesystem
link is attempted (resulting in an `EXDEV` error), but this hasn't been
added since the same error can happen on Unix and is already unhandled
there.

This change completely fixes the `dedup.t` test on Windows. 

This change also seems to address excessive cache duplication
encountered on windows (see #13713).

---------

Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
nojb and others added 2 commits March 2, 2026 19:56
Signed-off-by: Nicolás Ojeda Bär <n.oje.bar@gmail.com>
@Nevor Nevor force-pushed the fix_dune_cache_deduplication_rename_on_windows branch from 6f4658f to 2242ded Compare March 2, 2026 19:58
Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
@nojb
Copy link
Collaborator

nojb commented Mar 2, 2026

CI failure is unrelated. Merging!

@nojb nojb merged commit cc1a16c into ocaml:main Mar 2, 2026
28 of 29 checks passed
Nevor added a commit to Nevor/dune that referenced this pull request Mar 3, 2026
The `Io.portable_hardlink` function was systematically copying files on
Windows instead of trying to create hard links. Hard links have been
available for a while on NTFS and have also been available for ReFS for
a coupe of years. This availability is not tied to developer mode
capabilities (unlike symlinks), which means we can generally expect a
Windows environment to be able to create hard links.

This PR removes the systematic copy and adds the `EINVAL` error as a
fallback signal in case Dune tries to create a hard link on a filesystem
that does not support it. The later reduces the risk of a breaking
change. Note that a copy fallback could be used when a cross-filesystem
link is attempted (resulting in an `EXDEV` error), but this hasn't been
added since the same error can happen on Unix and is already unhandled
there.

This change completely fixes the `dedup.t` test on Windows.

This change also seems to address excessive cache duplication
encountered on windows (see ocaml#13713).

---------

Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
Nevor added a commit to Nevor/dune that referenced this pull request Mar 3, 2026
…deduplicating Dune cache (ocaml#13713)

In the Dune cache, when a temp artifact already exists in the cache,
Dune attempts deduplication by deleting the temp artifact, linking it to
the file already in the cache, and then moving the temp artifact to the
build directory.

The last step fails on Windows because Dune sets a read-only attribute
on the destination file, causing `Unix.rename` to fail with `EACCES` in
this case. Since the operation fails, Dune does not consider the file
cached. Combined with the fact that this seems to happen quite often [1]
on Windows, this effectively nullifies the cache speedup.

This PR creates a helper function that removes the read-only attribute
on the destination file before trying to overwrite it (similar to the
existing `win32_unlink`) and use it in the deduplication logic of the
cache, fixing the issue.

_Note: This issue does not exist on Unix. This discrepancy is also being
addressed directly on OCaml's side:
ocaml/ocaml#14602

The test dedup.t already exhibits the issue on Windows. The `dune_cmd
stat hardlinks _build/default/target` command returns 1 instead of the
expected 3. This PR bumps the result to 2. To make the test completely
pass, another issue around `Io.portable_hardlink` on Windows still needs
to be addressed [1].

[1] It seems that the fact that on windows dune always copies files
instead of trying to create a hardlink is linked to the fact that this
deduplication happen more often on windows. See ocaml#13714.

---------

Signed-off-by: Roven Lamar Gabriel <nevor@nevor.net>
shonfeder added a commit to shonfeder/opam-repository that referenced this pull request Mar 11, 2026
CHANGES:

### Fixed

- `Dyn.to_string` now uses a smarter way to convert floats. This ensures that
  floats are printed with enough precision to round-trip and are valid OCaml
  lexemes. (ocaml/dune#12982, fixes ocaml/dune#12980, @Alizter)

- Fix `dune install --prefix` failing with relative paths outside the workspace
  like `../foo` (ocaml/dune#12993, fixes ocaml/dune#12241, @benodiwal)

- Place the default trace file inside the build directory at the
  workspace root, rather than relative to the current directory.
  (ocaml/dune#13735, @vouillon)

- Fixed interpreting relative paths in `%{bin:..}` and `%{bin-available:..}`.
  These are now interpreted correctly, relative to the dune file they're in.
  (ocaml/dune#13712, fixes ocaml/dune#9564, @anmonteiro)

- Delete sandboxes with broken permissions (ocaml/dune#13511, @rgrinberg)

- Fix compiling Menhir parsers that refer to sibling modules within a
  subdirectory of `(include_subdirs qualified)`. (ocaml/dune#13118, fixes ocaml/dune#11119,
  @anmonteiro)

- Fixed the dependency specification of C stubs, which could result in C
  stubs not getting rebuilt when needed (which could in turn lead to
  segmentation faults and other hard-to-track bugs).
  (ocaml/dune#13652, fixes ocaml/dune#13651, @nojb)

- Fix the Dune cache on Windows by correctly handling renames onto read-only
  files. Before this change, the Dune cache would be filled but the stored
  artifacts would not generally be usable by Dune. (ocaml/dune#13713, @Nevor)

- Fix rpc not transferring promotion warnings to the client
  (ocaml/dune#12604, fixes ocaml/dune#12578, @ElectreAAS)

- Fix issue where `dune exec -w` was unable to kill running programs on
  rebuild. (ocaml/dune#12360, fixes ocaml/dune#12323, @Alizter)

- Fix package extraction on systems with tar implementations that don't
  auto-detect compression (e.g., OpenBSD). Dune now passes explicit
  decompression flags (-z for gzip, -j for bzip2) when needed, and provides
  clear error messages for unsupported formats like XZ and LZMA. (ocaml/dune#13688,
  fixes ocaml/dune#10123, @Alizter)

- Resolve context and workspace binaries introduced by the respective `(env
  (binaries ..))` stanzas. (ocaml/dune#12952, fixes ocaml/dune#6220, @anmonteiro)

- Fix `diff` promotions originating from sandboxed rules. Previously, they
  would be completely ignored as the sandbox with the promoted file would be
  destroyed if the promotion fired (ocaml/dune#13520, @rgrinberg)

- Fix failure to digest installed directory targets, allowing them to be used
  as dependencies to other rules. (ocaml/dune#13045, @anmonteiro)

- Fix handling of `(select ..)` field when used with `(include_subdirs ..)`.
  `(select <path> from ..)` modules now parse `path` as a relative path
  starting from the module group root (ocaml/dune#13175, fixes ocaml/dune#4383, ocaml/dune#12450,
  @anmonteiro)

- Fix dune trying to kill processes that were already reaped due to race
  conditions (ocaml/dune#13245, @rgrinberg)

- Add `O_CLOEXEC` to all files used for stdin/stdout/stderr (ocaml/dune#13385, @rgrinberg)

- Fix `$ dune promote dir/foo` when `dir` does not exist (ocaml/dune#13493, @rgrinberg)

- Fix `(select ..)` field evaluation when a transitive library has optional
  dependencies (fixes ocaml/dune#13299, ocaml/dune#13389, @anmonteiro)

- Fix sandboxed builds of `library` stanzas that set
  `(stdlib (modules_before_stdlib ..))` (ocaml/dune#13624, @anmonteiro)

- Dune cache: use of hard links under Windows. (ocaml/dune#13714, @Nevor)

- Fixed non-build caches not following `$DUNE_CACHE_ROOT` and instead only
  relying on `$XDG_CACHE_HOME`.
  This means the normal build cache moves:
  `$DUNE_CACHE_ROOT -> $DUNE_CACHE_ROOT/db` (no changes if that variable was
  unset). Affected users can prevent a full cache invalidation by moving
  previous contents:
  `cd $DUNE_CACHE_ROOT; mkdir db; mv <contents of directory> db`.
  (ocaml/dune#11612, fixes ocaml/dune#11584, @ElectreAAS)

- `$ dune promotion list` writes output to stdout rather than stderr (ocaml/dune#13462)

- Improve handling of empty files in the `diff` action. These are now correctly
  distinguished from *empty* files. (ocaml/dune#13696, @rgrinberg)
- Pass `/dev/null` to `--diff-command` instead of non-existent files (ocaml/dune#13696,
  @rgrinberg)

- Fix failure when multiple `rocq.extraction` stanzas existing in a directory
  (ocaml/dune#13531, fixes ocaml/dune#8042, @rlepigre-skylabs-ai)

- Print `$ dune promotion show` output to stdout rather than stderr (ocaml/dune#13481,
  @rgrinberg)

- Fix deadlock in the `memo` library in the presence of dependency cycles
  (ocaml/dune#13625, @anmonteiro)

- Fix promotions that modify a directory into a file (ocaml/dune#13516, fixes ocaml/dune#4067,
  @rgrinberg)

- Fix installation of implementations of virtual libraries. This failed when
  the implementation had no private modules, but the virtual library did
  (ocaml/dune#10635, @rgrinberg)

- Respect the `(dir ..)` field on packages when setting up cram tests (ocaml/dune#13581,
  @rgrinberg)

### Added

- Add support for generating `.cms` files using oxcaml and adding `.cms` or
  `.cmt` files as compilation dependencies (ocaml/dune#13397, @spiessimon)

- Add trace events for custom actions (ocaml/dune#13265, @rgrinberg)

- Allow enabling extensions with `(using ..)` in `dune-workspace` files
  (ocaml/dune#13395, @spiessimon)

- Add sandbox extraction trace event (ocaml/dune#13544, @rgrinberg)

- Add the initial cwd to the first config event (ocaml/dune#13026, @rgrinberg)

- Dune dune produces trace events in `DUNE_ACTION_TRACE_DIR` if this variable
  is set. (ocaml/dune#13302, @rgrinberg)

- Add file watching events to the trace file (ocaml/dune#13038, @rgrinberg)

- Introduce the `$ dune trace cat` subcommand to view the trace file. (ocaml/dune#13055,
  @rgrinberg)

- Add diagnostic events to the trace. (ocaml/dune#13041, @rgrinberg)

- Add `DUNE_JOBS` environment variable for controlling concurrency of Dune from
  environment. The `INSIDE_DUNE` variable also now no longer controls
  concurrency (ocaml/dune#12800, @Alizter)

- Support for Rocq expected output tests (ocaml/dune#13632, @rlepigre-skylabs-ai)

- Add `rusage` information to completed processes in the trace (@rgrinberg,
  ocaml/dune#13241)

- Add process start events to the trace (ocaml/dune#13261, rgrinberg)

- Generate odoc documentation in markdown using the `@doc-markdown` alias
  (ocaml/dune#12581, @davesnx)

- Add timing information for every command executed by cram (ocaml/dune#13092,
  @rgrinberg)

- Add the workspace root to the config trace event (ocaml/dune#12922, @rgrinberg)

- Introduce the `dune-action-trace` library. This public library is to be used
  by custom actions to emit trace events while executed as part of a dune
  build. The trace events emitted through this library will be incorporated
  into dune's own trace (ocaml/dune#13348, @rgrinberg)

- Add `dune-find-dominating` to `dune.el`, a command to find the
  dominating dune file. (ocaml/dune#12696, @arvidj)

- Add a `--no-recursive` flag to `$ dune describe workspace` (ocaml/dune#13590, @rgrinberg)

- Trace events for files written directly by dune (ocaml/dune#13618, @rgrinberg)

- Allow expansion of special forms like `(:include ..)` and `%{read-lines:..}`
  in the `modules` specification for the `ocamllex`, `ocamlyacc` and `menhir`
  stanzas. (ocaml/dune#13105, ocaml/dune#13135, ocaml/dune#13157, @anmonteiro)

- Add a trace event for snapshotting the asndbox (ocaml/dune#13541, @rgrinberg)

- Add signal send and receive events to the trace (ocaml/dune#13193, @rgrinberg)

- Emit final trace event before exiting. (ocaml/dune#13018, @rgrinberg)

- `dune runtest` can now run individual test executables from `(tests)` stanzas
  and inline tests from `(library (inline_tests))` stanzas by providing their
  source files as arguments. (ocaml/dune#13064, fixes ocaml/dune#870, @Alizter)

- Add a `shell` field to the cram stanza. This field allows customizing the
  shell to be `bash` rather than `sh` (ocaml/dune#13083, @haochenx)

### Changed

- Start sandboxing the execution of tests defined with the `test` and `tests`
  stanzas (ocaml/dune#13510, ocaml/dune#13617, @rgrinberg)

- Disabled cram tests can now be run explicitly with `dune runtest disabled.t`.
  The `enabled_if` field now only controls whether a test is included in
  the `@runtest` alias. (ocaml/dune#13081, @Alizter)

- Process categories in trace events are moved to their own field in `args`
  (ocaml/dune#13024, @rgrinberg)

- Sandbox running `ocamllex` and `ocamlyacc` actions. (ocaml/dune#13098, @anmonteiro)

- Sandboxing mdx test actions is now the default starting from `0.5` (ocaml/dune#13504,
  @rgrinberg)

- Start sandboxing Melange rules by default in the `(library ..)` and
  `(melange.emit ..)` stanzas (ocaml/dune#13619, @anmonteiro)

- Introduce a promotion trace event and remove the corresponding verbose log
  message. (ocaml/dune#12949, ocaml/dune#13444, @rgrinberg)

- Change dune's trace format to emit canonical s-expressions. This improves
  performance and is better aligned with dune's usage of the format
  elsewhere. `$ dune trace cat` can also emit the trace in `--chrome-trace`
  for perfetto, or `--sexp` for regular s-expressions for interactive usage.
  (ocaml/dune#13059, @rgrinberg)

- Move all logging statements to the trace file. All log statements now contain
  structured payloads (ocaml/dune#13015, fixes ocaml/dune#12904, @rgrinberg)

- Add a target resolution event to replace the equivalent log message (ocaml/dune#12955,
  @rgrinberg)
shonfeder added a commit to shonfeder/opam-repository that referenced this pull request Mar 16, 2026
CHANGES:

### Fixed

- `Dyn.to_string` now uses a smarter way to convert floats. This ensures that
  floats are printed with enough precision to round-trip and are valid OCaml
  lexemes. (ocaml/dune#12982, fixes ocaml/dune#12980, @Alizter)

- Fix `dune install --prefix` failing with relative paths outside the workspace
  like `../foo` (ocaml/dune#12993, fixes ocaml/dune#12241, @benodiwal)

- Place the default trace file inside the build directory at the
  workspace root, rather than relative to the current directory.
  (ocaml/dune#13735, @vouillon)

- Fixed interpreting relative paths in `%{bin:..}` and `%{bin-available:..}`.
  These are now interpreted correctly, relative to the dune file they're in.
  (ocaml/dune#13712, fixes ocaml/dune#9564, @anmonteiro)

- Delete sandboxes with broken permissions (ocaml/dune#13511, @rgrinberg)

- Fix compiling Menhir parsers that refer to sibling modules within a
  subdirectory of `(include_subdirs qualified)`. (ocaml/dune#13118, fixes ocaml/dune#11119,
  @anmonteiro)

- Fixed the dependency specification of C stubs, which could result in C
  stubs not getting rebuilt when needed (which could in turn lead to
  segmentation faults and other hard-to-track bugs).
  (ocaml/dune#13652, fixes ocaml/dune#13651, @nojb)

- Fix the Dune cache on Windows by correctly handling renames onto read-only
  files. Before this change, the Dune cache would be filled but the stored
  artifacts would not generally be usable by Dune. (ocaml/dune#13713, @Nevor)

- Fix rpc not transferring promotion warnings to the client
  (ocaml/dune#12604, fixes ocaml/dune#12578, @ElectreAAS)

- Fix issue where `dune exec -w` was unable to kill running programs on
  rebuild. (ocaml/dune#12360, fixes ocaml/dune#12323, @Alizter)

- Fix package extraction on systems with tar implementations that don't
  auto-detect compression (e.g., OpenBSD). Dune now passes explicit
  decompression flags (-z for gzip, -j for bzip2) when needed, and provides
  clear error messages for unsupported formats like XZ and LZMA. (ocaml/dune#13688,
  fixes ocaml/dune#10123, @Alizter)

- Resolve context and workspace binaries introduced by the respective `(env
  (binaries ..))` stanzas. (ocaml/dune#12952, fixes ocaml/dune#6220, @anmonteiro)

- Fix `diff` promotions originating from sandboxed rules. Previously, they
  would be completely ignored as the sandbox with the promoted file would be
  destroyed if the promotion fired (ocaml/dune#13520, @rgrinberg)

- Fix failure to digest installed directory targets, allowing them to be used
  as dependencies to other rules. (ocaml/dune#13045, @anmonteiro)

- Fix handling of `(select ..)` field when used with `(include_subdirs ..)`.
  `(select <path> from ..)` modules now parse `path` as a relative path
  starting from the module group root (ocaml/dune#13175, fixes ocaml/dune#4383, ocaml/dune#12450,
  @anmonteiro)

- Fix dune trying to kill processes that were already reaped due to race
  conditions (ocaml/dune#13245, @rgrinberg)

- Add `O_CLOEXEC` to all files used for stdin/stdout/stderr (ocaml/dune#13385, @rgrinberg)

- Fix `$ dune promote dir/foo` when `dir` does not exist (ocaml/dune#13493, @rgrinberg)

- Fix `(select ..)` field evaluation when a transitive library has optional
  dependencies (fixes ocaml/dune#13299, ocaml/dune#13389, @anmonteiro)

- Fix sandboxed builds of `library` stanzas that set
  `(stdlib (modules_before_stdlib ..))` (ocaml/dune#13624, @anmonteiro)

- Dune cache: use of hard links under Windows. (ocaml/dune#13714, @Nevor)

- Fixed non-build caches not following `$DUNE_CACHE_ROOT` and instead only
  relying on `$XDG_CACHE_HOME`.
  This means the normal build cache moves:
  `$DUNE_CACHE_ROOT -> $DUNE_CACHE_ROOT/db` (no changes if that variable was
  unset). Affected users can prevent a full cache invalidation by moving
  previous contents:
  `cd $DUNE_CACHE_ROOT; mkdir db; mv <contents of directory> db`.
  (ocaml/dune#11612, fixes ocaml/dune#11584, @ElectreAAS)

- `$ dune promotion list` writes output to stdout rather than stderr (ocaml/dune#13462)

- Improve handling of empty files in the `diff` action. These are now correctly
  distinguished from *empty* files. (ocaml/dune#13696, @rgrinberg)
- Pass `/dev/null` to `--diff-command` instead of non-existent files (ocaml/dune#13696,
  @rgrinberg)

- Fix failure when multiple `rocq.extraction` stanzas existing in a directory
  (ocaml/dune#13531, fixes ocaml/dune#8042, @rlepigre-skylabs-ai)

- Print `$ dune promotion show` output to stdout rather than stderr (ocaml/dune#13481,
  @rgrinberg)

- Fix deadlock in the `memo` library in the presence of dependency cycles
  (ocaml/dune#13625, @anmonteiro)

- Fix promotions that modify a directory into a file (ocaml/dune#13516, fixes ocaml/dune#4067,
  @rgrinberg)

- Fix installation of implementations of virtual libraries. This failed when
  the implementation had no private modules, but the virtual library did
  (ocaml/dune#10635, @rgrinberg)

- Respect the `(dir ..)` field on packages when setting up cram tests (ocaml/dune#13581,
  @rgrinberg)

### Added

- Add support for generating `.cms` files using oxcaml and adding `.cms` or
  `.cmt` files as compilation dependencies (ocaml/dune#13397, @spiessimon)

- Add trace events for custom actions (ocaml/dune#13265, @rgrinberg)

- Allow enabling extensions with `(using ..)` in `dune-workspace` files
  (ocaml/dune#13395, @spiessimon)

- Add sandbox extraction trace event (ocaml/dune#13544, @rgrinberg)

- Add the initial cwd to the first config event (ocaml/dune#13026, @rgrinberg)

- Dune dune produces trace events in `DUNE_ACTION_TRACE_DIR` if this variable
  is set. (ocaml/dune#13302, @rgrinberg)

- Add file watching events to the trace file (ocaml/dune#13038, @rgrinberg)

- Introduce the `$ dune trace cat` subcommand to view the trace file. (ocaml/dune#13055,
  @rgrinberg)

- Add diagnostic events to the trace. (ocaml/dune#13041, @rgrinberg)

- Add `DUNE_JOBS` environment variable for controlling concurrency of Dune from
  environment. The `INSIDE_DUNE` variable also now no longer controls
  concurrency (ocaml/dune#12800, @Alizter)

- Support for Rocq expected output tests (ocaml/dune#13632, @rlepigre-skylabs-ai)

- Add `rusage` information to completed processes in the trace (@rgrinberg,
  ocaml/dune#13241)

- Add process start events to the trace (ocaml/dune#13261, rgrinberg)

- Generate odoc documentation in markdown using the `@doc-markdown` alias
  (ocaml/dune#12581, @davesnx)

- Add timing information for every command executed by cram (ocaml/dune#13092,
  @rgrinberg)

- Add the workspace root to the config trace event (ocaml/dune#12922, @rgrinberg)

- Introduce the `dune-action-trace` library. This public library is to be used
  by custom actions to emit trace events while executed as part of a dune
  build. The trace events emitted through this library will be incorporated
  into dune's own trace (ocaml/dune#13348, @rgrinberg)

- Add `dune-find-dominating` to `dune.el`, a command to find the
  dominating dune file. (ocaml/dune#12696, @arvidj)

- Add a `--no-recursive` flag to `$ dune describe workspace` (ocaml/dune#13590, @rgrinberg)

- Trace events for files written directly by dune (ocaml/dune#13618, @rgrinberg)

- Allow expansion of special forms like `(:include ..)` and `%{read-lines:..}`
  in the `modules` specification for the `ocamllex`, `ocamlyacc` and `menhir`
  stanzas. (ocaml/dune#13105, ocaml/dune#13135, ocaml/dune#13157, @anmonteiro)

- Add a trace event for snapshotting the asndbox (ocaml/dune#13541, @rgrinberg)

- Add signal send and receive events to the trace (ocaml/dune#13193, @rgrinberg)

- Emit final trace event before exiting. (ocaml/dune#13018, @rgrinberg)

- `dune runtest` can now run individual test executables from `(tests)` stanzas
  and inline tests from `(library (inline_tests))` stanzas by providing their
  source files as arguments. (ocaml/dune#13064, fixes ocaml/dune#870, @Alizter)

- Add a `shell` field to the cram stanza. This field allows customizing the
  shell to be `bash` rather than `sh` (ocaml/dune#13083, @haochenx)

### Changed

- Start sandboxing the execution of tests defined with the `test` and `tests`
  stanzas (ocaml/dune#13510, ocaml/dune#13617, @rgrinberg)

- Disabled cram tests can now be run explicitly with `dune runtest disabled.t`.
  The `enabled_if` field now only controls whether a test is included in
  the `@runtest` alias. (ocaml/dune#13081, @Alizter)

- Process categories in trace events are moved to their own field in `args`
  (ocaml/dune#13024, @rgrinberg)

- Sandbox running `ocamllex` and `ocamlyacc` actions. (ocaml/dune#13098, @anmonteiro)

- Sandboxing mdx test actions is now the default starting from `0.5` (ocaml/dune#13504,
  @rgrinberg)

- Start sandboxing Melange rules by default in the `(library ..)` and
  `(melange.emit ..)` stanzas (ocaml/dune#13619, @anmonteiro)

- Introduce a promotion trace event and remove the corresponding verbose log
  message. (ocaml/dune#12949, ocaml/dune#13444, @rgrinberg)

- Change dune's trace format to emit canonical s-expressions. This improves
  performance and is better aligned with dune's usage of the format
  elsewhere. `$ dune trace cat` can also emit the trace in `--chrome-trace`
  for perfetto, or `--sexp` for regular s-expressions for interactive usage.
  (ocaml/dune#13059, @rgrinberg)

- Move all logging statements to the trace file. All log statements now contain
  structured payloads (ocaml/dune#13015, fixes ocaml/dune#12904, @rgrinberg)

- Add a target resolution event to replace the equivalent log message (ocaml/dune#12955,
  @rgrinberg)
shonfeder added a commit to shonfeder/opam-repository that referenced this pull request Mar 19, 2026
CHANGES:

### Fixed

- `Dyn.to_string` now uses a smarter way to convert floats. This ensures that
  floats are printed with enough precision to round-trip and are valid OCaml
  lexemes. (ocaml/dune#12982, fixes ocaml/dune#12980, @Alizter)

- Fix `dune install --prefix` failing with relative paths outside the workspace
  like `../foo` (ocaml/dune#12993, fixes ocaml/dune#12241, @benodiwal)

- Place the default trace file inside the build directory at the
  workspace root, rather than relative to the current directory.
  (ocaml/dune#13735, @vouillon)

- Fixed interpreting relative paths in `%{bin:..}` and `%{bin-available:..}`.
  These are now interpreted correctly, relative to the dune file they're in.
  (ocaml/dune#13712, fixes ocaml/dune#9564, @anmonteiro)

- Delete sandboxes with broken permissions (ocaml/dune#13511, @rgrinberg)

- Fix compiling Menhir parsers that refer to sibling modules within a
  subdirectory of `(include_subdirs qualified)`. (ocaml/dune#13118, fixes ocaml/dune#11119,
  @anmonteiro)

- Fixed the dependency specification of C stubs, which could result in C
  stubs not getting rebuilt when needed (which could in turn lead to
  segmentation faults and other hard-to-track bugs).
  (ocaml/dune#13652, fixes ocaml/dune#13651, @nojb)

- Fix the Dune cache on Windows by correctly handling renames onto read-only
  files. Before this change, the Dune cache would be filled but the stored
  artifacts would not generally be usable by Dune. (ocaml/dune#13713, @Nevor)

- Fix rpc not transferring promotion warnings to the client
  (ocaml/dune#12604, fixes ocaml/dune#12578, @ElectreAAS)

- Fix issue where `dune exec -w` was unable to kill running programs on
  rebuild. (ocaml/dune#12360, fixes ocaml/dune#12323, @Alizter)

- Resolve context and workspace binaries introduced by the respective `(env
  (binaries ..))` stanzas. (ocaml/dune#12952, fixes ocaml/dune#6220, @anmonteiro)

- Fix `diff` promotions originating from sandboxed rules. Previously, they
  would be completely ignored as the sandbox with the promoted file would be
  destroyed if the promotion fired (ocaml/dune#13520, @rgrinberg)

- Fix failure to digest installed directory targets, allowing them to be used
  as dependencies to other rules. (ocaml/dune#13045, @anmonteiro)

- Fix handling of `(select ..)` field when used with `(include_subdirs ..)`.
  `(select <path> from ..)` modules now parse `path` as a relative path
  starting from the module group root (ocaml/dune#13175, fixes ocaml/dune#4383, ocaml/dune#12450,
  @anmonteiro)

- Fix dune trying to kill processes that were already reaped due to race
  conditions (ocaml/dune#13245, @rgrinberg)

- Add `O_CLOEXEC` to all files used for stdin/stdout/stderr (ocaml/dune#13385, @rgrinberg)

- Fix `$ dune promote dir/foo` when `dir` does not exist (ocaml/dune#13493, @rgrinberg)

- Fix `(select ..)` field evaluation when a transitive library has optional
  dependencies (fixes ocaml/dune#13299, ocaml/dune#13389, @anmonteiro)

- Fix sandboxed builds of `library` stanzas that set
  `(stdlib (modules_before_stdlib ..))` (ocaml/dune#13624, @anmonteiro)

- Dune cache: use of hard links under Windows. (ocaml/dune#13714, @Nevor)

- Fixed non-build caches not following `$DUNE_CACHE_ROOT` and instead only
  relying on `$XDG_CACHE_HOME`.
  This means the normal build cache moves:
  `$DUNE_CACHE_ROOT -> $DUNE_CACHE_ROOT/db` (no changes if that variable was
  unset). Affected users can prevent a full cache invalidation by moving
  previous contents:
  `cd $DUNE_CACHE_ROOT; mkdir db; mv <contents of directory> db`.
  (ocaml/dune#11612, fixes ocaml/dune#11584, @ElectreAAS)

- `$ dune promotion list` writes output to stdout rather than stderr (ocaml/dune#13462)

- Improve handling of empty files in the `diff` action. These are now correctly
  distinguished from *empty* files. (ocaml/dune#13696, @rgrinberg)
- Pass `/dev/null` to `--diff-command` instead of non-existent files (ocaml/dune#13696,
  @rgrinberg)

- Fix failure when multiple `rocq.extraction` stanzas existing in a directory
  (ocaml/dune#13531, fixes ocaml/dune#8042, @rlepigre-skylabs-ai)

- Print `$ dune promotion show` output to stdout rather than stderr (ocaml/dune#13481,
  @rgrinberg)

- Fix deadlock in the `memo` library in the presence of dependency cycles
  (ocaml/dune#13625, @anmonteiro)

- Fix promotions that modify a directory into a file (ocaml/dune#13516, fixes ocaml/dune#4067,
  @rgrinberg)

- Fix installation of implementations of virtual libraries. This failed when
  the implementation had no private modules, but the virtual library did
  (ocaml/dune#10635, @rgrinberg)

- Respect the `(dir ..)` field on packages when setting up cram tests (ocaml/dune#13581,
  @rgrinberg)

### Added

- Add support for generating `.cms` files using oxcaml and adding `.cms` or
  `.cmt` files as compilation dependencies (ocaml/dune#13397, @spiessimon)

- Add trace events for custom actions (ocaml/dune#13265, @rgrinberg)

- Allow enabling extensions with `(using ..)` in `dune-workspace` files
  (ocaml/dune#13395, @spiessimon)

- Add sandbox extraction trace event (ocaml/dune#13544, @rgrinberg)

- Add the initial cwd to the first config event (ocaml/dune#13026, @rgrinberg)

- Dune dune produces trace events in `DUNE_ACTION_TRACE_DIR` if this variable
  is set. (ocaml/dune#13302, @rgrinberg)

- Add file watching events to the trace file (ocaml/dune#13038, @rgrinberg)

- Introduce the `$ dune trace cat` subcommand to view the trace file. (ocaml/dune#13055,
  @rgrinberg)

- Add diagnostic events to the trace. (ocaml/dune#13041, @rgrinberg)

- Add `DUNE_JOBS` environment variable for controlling concurrency of Dune from
  environment. The `INSIDE_DUNE` variable also now no longer controls
  concurrency (ocaml/dune#12800, @Alizter)

- Support for Rocq expected output tests (ocaml/dune#13632, @rlepigre-skylabs-ai)

- Add `rusage` information to completed processes in the trace (@rgrinberg,
  ocaml/dune#13241)

- Add process start events to the trace (ocaml/dune#13261, rgrinberg)

- Generate odoc documentation in markdown using the `@doc-markdown` alias
  (ocaml/dune#12581, @davesnx)

- Add timing information for every command executed by cram (ocaml/dune#13092,
  @rgrinberg)

- Add the workspace root to the config trace event (ocaml/dune#12922, @rgrinberg)

- Introduce the `dune-action-trace` library. This public library is to be used
  by custom actions to emit trace events while executed as part of a dune
  build. The trace events emitted through this library will be incorporated
  into dune's own trace (ocaml/dune#13348, @rgrinberg)

- Add `dune-find-dominating` to `dune.el`, a command to find the
  dominating dune file. (ocaml/dune#12696, @arvidj)

- Add a `--no-recursive` flag to `$ dune describe workspace` (ocaml/dune#13590, @rgrinberg)

- Trace events for files written directly by dune (ocaml/dune#13618, @rgrinberg)

- Allow expansion of special forms like `(:include ..)` and `%{read-lines:..}`
  in the `modules` specification for the `ocamllex`, `ocamlyacc` and `menhir`
  stanzas. (ocaml/dune#13105, ocaml/dune#13135, ocaml/dune#13157, @anmonteiro)

- Add a trace event for snapshotting the asndbox (ocaml/dune#13541, @rgrinberg)

- Add signal send and receive events to the trace (ocaml/dune#13193, @rgrinberg)

- Emit final trace event before exiting. (ocaml/dune#13018, @rgrinberg)

- `dune runtest` can now run individual test executables from `(tests)` stanzas
  and inline tests from `(library (inline_tests))` stanzas by providing their
  source files as arguments. (ocaml/dune#13064, fixes ocaml/dune#870, @Alizter)

- Add a `shell` field to the cram stanza. This field allows customizing the
  shell to be `bash` rather than `sh` (ocaml/dune#13083, @haochenx)

### Changed

- Start sandboxing the execution of tests defined with the `test` and `tests`
  stanzas (ocaml/dune#13510, ocaml/dune#13617, @rgrinberg)

- Disabled cram tests can now be run explicitly with `dune runtest disabled.t`.
  The `enabled_if` field now only controls whether a test is included in
  the `@runtest` alias. (ocaml/dune#13081, @Alizter)

- Process categories in trace events are moved to their own field in `args`
  (ocaml/dune#13024, @rgrinberg)

- Sandbox running `ocamllex` and `ocamlyacc` actions. (ocaml/dune#13098, @anmonteiro)

- Sandboxing mdx test actions is now the default starting from `0.5` (ocaml/dune#13504,
  @rgrinberg)

- Start sandboxing Melange rules by default in the `(library ..)` and
  `(melange.emit ..)` stanzas (ocaml/dune#13619, @anmonteiro)

- Introduce a promotion trace event and remove the corresponding verbose log
  message. (ocaml/dune#12949, ocaml/dune#13444, @rgrinberg)

- Change dune's trace format to emit canonical s-expressions. This improves
  performance and is better aligned with dune's usage of the format
  elsewhere. `$ dune trace cat` can also emit the trace in `--chrome-trace`
  for perfetto, or `--sexp` for regular s-expressions for interactive usage.
  (ocaml/dune#13059, @rgrinberg)

- Move all logging statements to the trace file. All log statements now contain
  structured payloads (ocaml/dune#13015, fixes ocaml/dune#12904, @rgrinberg)

- Add a target resolution event to replace the equivalent log message (ocaml/dune#12955,
  @rgrinberg)
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.

3 participants