[ANN] dune 3.13

We’re happy to announce that Dune 3.13.0 is now available.
This feature is packed with fixes and new features that you can find in the changelog.

There are a few new features that we would like to specially highlight.

Generate Conflicts File for Menhir Grammars (#9512, @nojb)

When menhir is used to generate code from .mly files, there are sometimes issues with the grammar itself, such as shift-reduce conflicts.

Menhir has an option to generate a “conflicts” file using its --explain flag, but until now this was not exposed by Dune. Starting from this version, this file will be generated automatically to help developers debug their grammars.

Cached Directory Targets (#9535, @rleshchinskiy)

Dune’s global cache is a way to save the result of intermediate build results, even across projects. Previously, it would only work with file targets. With this change, it now supports Dune’s experimental directory targets.

Dynamic Module List (#9578, @nojb)

In several places in the Dune language, it is possible to pass a list of modules. For example in a (library) stanza, if for some reason the default of picking all the source files in the current directory is not the right thing to do, it is possible to pass (module A B C) to only attach these modules to the library.

An important limitation has been that the list of modules needed to be static: written as is in the dune file. This limitation has now been lifted and it is possible to use (:include) or %{read-lines:file} in this field and similar ones.

LexiFi’s use case is a system of static plug-ins: a program is extended by selecting which modules are linked to the application core. This list of modules can now be emitted by a generator that reads a configuration file.

Previously, this required using OCaml syntax for the dune file, which has several issues, including incompatibility with features like (include_subdirs) and poor performance because Dune does not know the dependencies of the generator and needs to re-run the build more times than necessary.

Here is the full changelog:


  • Add command dune cache clear to completely delete all traces of the Dune
    cache. (#8975, @nojb)

  • Allow to disable Coq 0.8 deprecation warning (#9439, @ejgallego)

  • Allow OCAMLFIND_TOOLCHAIN to be set per context in the workspace file
    through the env stanza. (#9449, @rgrinberg)

  • Menhir: generate .conflicts file by default. Add new field to the
    (menhir) stanza to control the generation of this file: (explain <blang expression>). Introduce (menhir (flags ...) (explain ...)) field in the
    (env) stanza, delete (menhir_flags) field. All changes are guarded under
    a new version of the Menhir extension, 3.0. (#9512, @nojb)

  • Directory targets can now be cached. (#9535, @rleshchinskiy)

  • It is now possible to use special forms such as (:include) and variables
    %{read-lines:} in (modules) and similar fields. Note that the
    dependencies introduced in this way (ie the files being read) must live in a
    different directory than the stanza making use of them. (#9578, @nojb)

  • Remove warning 30 from default set for projects where dune lang is at least
    3.13 (#9568, @gasche)

  • Add coqdoc_flags field to coq field of env stanza allowing the setting
    of workspace-wide defaults for coqdoc_flags. (#9280, fixes #9139, @Alizter)

  • ctypes: fix an error where (ctypes) with no (function_description) would
    cause an error trying refer to a nonexistent _stubs.a dependency (#9302,
    fix #9300, @emillon)


  • Check that package names in (depends) and related fields in dune-project
    are well-formed. (#9472, fixes #9270, @ElectreAAS)


  • Do not ignore (formatting ..) settings in context or workspace files
    (#8447, @rgrinberg)

  • Fixed a bug where Dune was incorrectly parsing the output of coqdep when it
    was escaped, as is the case on Windows. (#9231, fixes #9218, @Alizter)

  • Copying mode for sandboxes will now follow symbolic links (#9282, @rgrinberg)

  • Forbid the empty (binaries ..) field in the env stanza in the workspace
    file unless language version is at least 3.2. (#9309, @rgrinberg)

  • [coq] Fix bug in computation of flags when composed with boot theories.
    (#9347, fixes #7909, @ejgallego)

  • Fixed a bug where the (select) field of the (libraries) field of the
    (test) stanza wasn’t working properly. (#9387, fixes #9365, @Alizter)

  • Fix handling of the PATH argument to dune init proj NAME PATH. An
    intermediate directory called NAME is no longer created if PATH is
    supplied, so dune init proj my_project . will now initialize a project in
    the current working directory. (#9447, fixes #9209, @shonfeder)

  • Experimental doc rules: Correctly handle the case when a package depends upon
    its own sublibraries (#9461, fixes #9456, @jonludlam)

  • Resolve various public binaries to their build location, rather than to where
    they’re copied in the _build/install directory (#9496, fixes #7908,

  • Correctly ignore warning flags in vendored projects (#9515, @rgrinberg)

  • Use watch exclusions in watch mode on MacOS (#9643, fixes #9517,

  • Fix merlin configuration for (include_subdirs qualified) modules (#9659,
    fixes #8297, @rgrinberg)

  • Fix handling of enabled_if in binary install stanzas. Previously, we’d
    ignore the result of enabled_if when evaluating %{bin:..} (#9707,


And dune 3.13.1 is available with the following fixes:

  • Fix performance regression for incremental builds (#9769, fixes #9738, @rgrinberg)

  • Fix dune ocaml top-module to correctly handle absolute paths. (#8249, fixes #7370, @Alizter)

  • subst: ignore broken symlinks when looking at source files (#9810, fixes #9593, @emillon)

  • subst: do not fail on 32-bit systems when large files are encountered. Just log a warning in this case. (#9811, fixes #9538, @emillon)

  • boot: sort directory entries in readdir. This makes the dune binary reproducible in terms of filesystem order. (#9861, fixes #9794, @emillon)