Dune 3.20.0_alpha4 was released, with no user-facing changes.
Backstage OCaml
RSSGet updates on experimental releases, work-in-progress, and opportunities to contribute to the development of the OCaml Platform and its infrastructure.
Dune 3.20.0_alpha3 was released, with no user-facing changes.
Dune 3.20.0_alpha2 was released, with no user-facing changes.
We released Dune 3.20.0_alpha1 as a minor alpha release that adds one new feature and fixes a documentation reference:
- New Feature: Added timeout support for cram tests - you can now specify
(timeout <float>)
in cram stanzas to automatically terminate tests that run too long - Documentation Fix: Corrected a reference in the RPC warning changelog entry
This unstable alpha release builds on alpha0 with minimal changes focused on improving test reliability and documentation accuracy.
Dune 3.20.0~alpha0 is now available with several user-facing improvements and fixes.
Summary of Changes
Testing improvements: Individual tests can now be run using named aliases (@runtest-<name>
), dune runtest
accepts absolute paths and can target specific build contexts, and cram tests have better process cleanup.
New command-line features: dune exec
works concurrently with watch mode, dune promote
runs while watch mode is active, dune describe location
shows executable paths, and --alias
/--alias-rec
flags provide alternatives to @
/@@
syntax.
New variables: Added %{os}
, %{os_version}
, %{os_distribution}
, and %{os_family}
variables matching opam equivalents.
Fixes: dune subst
properly handles version fields in opam files and works when no version control is detected.
Under the hood: Switched from MD5 to BLAKE3 for better performance, improved s-expression formatting, and added smart handling of transitive dependencies based on compiler capabilities.
Installation
opam install dune.3.20.0~alpha0
This is an alpha release for testing. Report issues on GitHub.
See full backstage
Fixed
-
Stop re-running cram tests after promotion when it's not necessary (#11994,
@rgrinberg) -
fix:
$ dune subst
should not fail when adding the version field in opam
files (#11801, fixes #11045, @btjorge) -
Kill all processes in the process group after the main process has
terminated; in particular this avoids background processes in cram tests to
stick around after the test finished (#11841, fixes #11820, @Alizter,
@Leonidas-from-XIV)
Added
-
(tests)
stanzas now generate aliases with the test name. To run
(test (name a))
you can dodune build @runtest-a
. (#11558, grants part of #10239,
@Alizter) -
Inline test libraries now produce aliases
runtest-name_of_lib
allowing users to run specific inline tests asdune build @runtest-name_of_lib
. (#11109, partially fixes #10239, @Alizter) -
feature:
$ dune subst
use version fromdune-project
when no version
control repository has been detected (#11801, @btjorge) -
Allow
dune exec
to run concurrently with another instance of dune in watch
mode (#11840, @gridbugs) -
Introduce
%{os}
,%{os_version}
,%{os_distribution}
, and%{os_family}
percent forms. These have the same values as their opam counterparts.
(#11863, @rgrinberg) -
Introduce option
(implicit_transitive_deps false-if-hidden-includes-supported)
that is equivalent to(implicit_transitive_deps false)
when-H
is
supported by the compiler (OCaml >= 5.2) and equivalent to
(implicit_transitive_deps true)
otherwise. (#11866, fixes #11212, @nojb) -
Add
dune describe location
for printing the path to the executable that
would be run (#11905, @gridbugs) -
dune runtest
can now understand absolute paths as well as run tests in
specific build contexts (#11936, @Alizter). -
Added 'empty' alias which contains no targets. (#11556 #11952 #11955 #11956,
grants #4161, @Alizter and @rgrinberg) -
Allow
dune promote
to properly run while a watch mode server is running
(#12010, @ElectreAAS) -
Add
--alias
and--alias-rec
flags as an alternative to the@
and@@
syntax in the command line (#12043, fixes #5775, @rgrinberg)
Changed
-
Format long lists in s-expressions to fill the line instead of
formatting them in a vertical way (#10892, fixes #10860, @nojb) -
Switch from MD5 to BLAKE3 for digesting targets and rules. BLAKE3 is both more
performant and difficult to break than MD5 (#11735, @rgrinberg, @Alizter) -
Print a warning when
dune build
runs over RPC (#11836, @gridbugs) -
Stop emitting empty module group wrapper
.js
file inmelange.emit
(#11987, fixes #11986, @anmonteiro)
Discuss this post on discuss!
Dune lock directories record the names of any system packages needed to build projects or their dependencies. Currently this information is not portable because Dune only stores the names of system packages within the package repository on the machine where the lock directory is generated. We've recently changed how Dune stores the names of system packages in the Dune Developer Preview so that the names of packages in all known package repositories are stored. This allows a lock directory generated on one machine to be used on a different machine.
Background on depexts
in Opam
A system package, or external dependency, or depext
as I'll refer to them
from now on, is a piece of software which can't be installed by Opam directly,
but which must be installed in order for some Opam package to be built or for
code in an Opam package to be executed at runtime. These packages must be
installed by the system package manager, or by some other non-Opam means such
as manually building and installing the package from source. Common types of
depext
are build tools such as the pkg-config
command, often run to
determine linker flags while building a package, or shared libraries such as
libgtk
, which an OCaml project might link against to create GUIs.
Opam usually installs depexts
automatically. Opam knows how to invoke many
different system package managers (such as apt
or pacman
), so when
installing a package with depexts
Opam can run the commands appropriate to the
current system to install the required packages using the system's package
manager. For this to work, Opam needs to know the name of the package within the
package repository appropriate to the current system, and these names can vary
from system to system. For example the pkg-config
command is in a package
named simply pkg-config
in the apt
package manager on Ubuntu/Debian
systems, whereas in the third-party homebrew
package manager on MacOS it's in
a package named pkgconf
. In order to determine the right package name for the
current system, the package metadata for Opam packages with depexts
contains
a list of all the different known package names along with the conditions under
which that name is correct. Here is that list for the conf-pkg-config
Opam
package:
depexts: [
["pkg-config"] {os-family = "debian" | os-family = "ubuntu"}
["pkgconf"] {os-distribution = "arch"}
["pkgconf-pkg-config"] {os-family = "fedora"}
["pkgconfig"] {os-distribution = "centos" & os-version <= "7"}
["pkgconf-pkg-config"] {os-distribution = "mageia"}
["pkgconfig"] {os-distribution = "rhel" & os-version <= "7"}
["pkgconfig"] {os-distribution = "ol" & os-version <= "7"}
["pkgconf"] {os-distribution = "alpine"}
["pkg-config"] {os-distribution = "nixos"}
["pkgconf"] {os = "macos" & os-distribution = "homebrew"}
["pkgconfig"] {os = "macos" & os-distribution = "macports"}
["pkgconf"] {os = "freebsd"}
["pkgconf-pkg-config"] {os-distribution = "rhel" & os-version >= "8"}
["pkgconf-pkg-config"] {os-distribution = "centos" & os-version >= "8"}
["pkgconf-pkg-config"] {os-distribution = "ol" & os-version >= "8"}
["system:pkgconf"] {os = "win32" & os-distribution = "cygwinports"}
["pkgconf"] {os-distribution = "cygwin"}
]
depexts
in Dune
Dune doesn't install depexts
automatically as the Dune developers are a little
nervous about running commands that would modify the global system state. This
may change at some point, but for now Dune only provides support for listing the
names of depexts
, leaving it up to the user to install them as they see fit.
The dune show depexts
command can be used to list the depexts
of a project.
For that command to work the project must have a lock directory. Here's an
example of listing the depexts
of a project:
$ dune pkg lock
...
$ dune show depexts
libao
libffi
pkgconf
sdl2
I ran these commands on a Mac with homebrew installed, so the package names are
from the homebrew package repo. Each package listed there is one of the
depexts
of a package whose lockfile appears in the project's lock directory.
Let's look at how this information is stored. Using pkg-config
as an example:
$ cat dune.lock/conf-pkg-config.pkg
(version 4)
(build
(run pkgconf --version))
(depexts pkgconf)
The relevant part for us is the depexts
field. The current released version of
Dune only stores the package's depexts
for the system where dune pkg lock
was run. The command dune show depexts
simply concatenates the depexts
fields from each lockfile in the lock directory.
When thinking about portable lock directories I always like to imagine what the
experience would be using Dune for a project where the lock directory is checked
into version control. I frequently switch between using two different machines
for development - one running Linux and the other running MacOS. If I was to
check in the lock directory I just generated on my Mac, and then check it out on
Linux and continue development, dune show depexts
would show me a list of
packages for the wrong system!
Portable depexts
in Dune
To make depexts
portable, one's first instinct might be to use the same
approach as taken with the depends
field outlined in a previous
post,
listing the depexts
for each platform for which the solver was run. Indeed
such a change was added to the Dune Developer Preview when we first introduced
portable lock directories, however we quickly realized a problem.
The depends
, build
, and install
fields of a package rarely vary between OS
distribution. It's reasonably common for those fields to be different on
different OSes, but very rare for them to also be different on different OS
distributions. As such, it's expected that users will elect to solve their
projects for each common OS, but there would be little value in solving projects
for each OS distro. In fact solving for multiple distros would slow down solving
and bloat the lock directory, and users would somehow need to come up with a
definitive list of distros to solve for.
But the depexts
field is highly-dependent on the OS distro since package
names are specific to the package repository for a particular distro. Recall
that the depexts
field in Opam package metadata lists package names along with
the conditions under which that package name should be used, e.g.:
["pkg-config"] {os-family = "debian" | os-family = "ubuntu"}
["pkgconf"] {os-distribution = "arch"}
["pkgconf-pkg-config"] {os-family = "fedora"}
["pkgconfig"] {os-distribution = "centos" & os-version <= "7"}
These conditions almost always involve the name of the OS distro, and to make
matters worse they also sometimes involve the OS version, as packages can
change their names between different versions of the same OS. Evaluating these
conditions at solve time for platforms with no distro or version specified
tends to result in lockfiles with no depexts
at all, since all the
conditions evaluate to false
.
The use case we have in mind for depexts
in Dune is that a user will solve
their project coarsely, usually just for each common OS with no consideration
for distribution or version. Then when they run dune show depexts
, the
depexts
will be listed using names appropriate to the current machine. This
means Dune needs to store enough metadata about depexts
to compute
system-specific depext
names at a later time. This means storing the same
names and conditions as are currently stored in Opam files, and deferring
evaluation of the conditions until as late as possible, such as right when
dune show depexts
is run.
The latest version of the Dune Developer Preview does just this; translating the
depexts
field from each package's Opam file into a Dune-friendly S-expression.
After this change, the depexts
field of conf-pkg-config
's lockfile is:
$ cat dune.lock/conf-pkg-config.4.pkg
...
(depexts
((pkg-config)
(or_absorb_undefined_var
(= %{os_family} debian)
(= %{os_family} ubuntu)))
((pkgconf)
(= %{os_distribution} arch))
((pkgconf-pkg-config)
(= %{os_family} fedora))
((pkgconfig)
(and_absorb_undefined_var
(= %{os_distribution} centos)
(<= %{os_version} 7)))
((pkgconf-pkg-config)
(= %{os_distribution} mageia))
((pkgconfig)
(and_absorb_undefined_var
(= %{os_distribution} rhel)
(<= %{os_version} 7)))
((pkgconfig)
(and_absorb_undefined_var
(= %{os_distribution} ol)
(<= %{os_version} 7)))
((pkgconf)
(= %{os_distribution} alpine))
((pkg-config)
(= %{os_distribution} nixos))
((pkgconf)
(and_absorb_undefined_var
(= %{os} macos)
(= %{os_distribution} homebrew)))
((pkgconfig)
(and_absorb_undefined_var
(= %{os} macos)
(= %{os_distribution} macports)))
((pkgconf)
(= %{os} freebsd))
((pkgconf-pkg-config)
(and_absorb_undefined_var
(= %{os_distribution} rhel)
(>= %{os_version} 8)))
((pkgconf-pkg-config)
(and_absorb_undefined_var
(= %{os_distribution} centos)
(>= %{os_version} 8)))
((pkgconf-pkg-config)
(and_absorb_undefined_var
(= %{os_distribution} ol)
(>= %{os_version} 8)))
((system:pkgconf)
(and_absorb_undefined_var
(= %{os} win32)
(= %{os_distribution} cygwinports)))
((pkgconf)
(= %{os_distribution} cygwin)))
That's a 1:1 translation of the depexts
field from conf-pkg-config
's Opam
file. There's enough information there so that the appropriate package name can
be computed on demand rather than just at solve time.
This bring us a step closer to a world where Dune users can check their lock directories into version control with confidence that their builds are reproducible across different platforms. To try out the latest version of the Dune Developer Preview, go to preview.dune.build.
Dune 3.19.0~alpha0 is now available. This alpha release includes several bug fixes and new features for OCaml developers.
Bug Fixes
This release addresses several issues that affected build reliability and functionality:
- Cram tests: Fixed duplicate execution of cram tests attached to multiple aliases
- pkg-config integration: Resolved missing
--personality
flag in pkgconfig invocations that prevented library detection in certain contexts - Foreign libraries: Fixed evaluation of
enabled_if
conditions when computing stubs forforeign_library
stanzas - Preprocessing: Corrected
dune describe pp
behavior for libraries using(include_subdirs unqualified)
- Git integration: Fixed
dune subst
functionality in subdirectories of git repositories - Windows compatibility: Resolved crash in
Path.drop_prefix
when using Melange on Windows
New Features
- Dependency validation: Added automatic detection and warnings for common typos in package dependency constraints
- Foreign library support: Added
(extra_objects)
field to(foreign_library)
stanza with(:include)
support
Improvements
- RPC server: Enhanced RPC server to handle build messages in eager watch mode and support concurrent builds
Installation
Install via opam:
opam install dune.3.19.0~alpha0
As this is an alpha release, please test thoroughly before using in production environments. Bug reports and feedback are welcome on the Dune issue tracker.
For the complete list of changes with pull request references, see the release notes.
See full backstage
Fixed
-
Fixed a bug that was causing cram tests attached to multiple aliases to be run multiple
times. (#11547, @Alizter) -
Fix: pass pkg-config (extra) args in all pkgconfig invocations. A missing --personality
flag would result in pkgconf not finding libraries in some contexts. (#11619, @MisterDA) -
Fix: Evaluate
enabled_if
when computing the stubs for stanzas such as
foreign_library
(#11707, @Alizter, @rgrinberg) -
Fix $ dune describe pp for libraries in the presence of
(include_subdirs unqualified)
(#11729, fixes #10999, @rgrinberg) -
Fix
$ dune subst
in sub directories of a git repository (#11760, fixes
#11045, @Richard-Degenne) -
Fix a crash involving
Path.drop_prefix
when using Melange on Windows
(#11767, @nojb)
Added
-
Added detection and warning for common typos in package dependency
constraints (#11600, fixes #11575, @kemsguy7) -
Added
(extra_objects)
field to(foreign_library)
stanza with(:include)
support.
(#11683, @Alizter)
Changed
Discuss this post on Discuss!
We've recently made a change to how lock directories work in the Dune Developer Preview.
Previously when Dune would solve dependencies for a project and generate a lock directory, the lock directory would be specialized for the computer where it was generated, with no guarantee it would work on a different computer. This posed a problem for checking lock directories into version control for projects with multiple developers, since one developer might lock the project on their Mac, say, only for another developer on Linux to be unable to build it due to its MacOS-specific lock directory.
This post is to announce that Dune now supports generating portable lock directories; a lock directory generated on one computer will now contain a dependency solution for a range of different computers, making it safe to check lock directories into version control.
Technical Details
In Opam the dependencies of a package can be different depending on properties of the computer where the package is being installed. A package might have a different set of dependencies when being installed on MacOS verses Linux versus Windows, or the dependencies might vary depending on the CPU architecture. It's even possible (though quite rare in practice) for the dependencies of a package to vary between operating system distributions, or even operating system versions.
This expressive power makes Opam very flexible as it allows packages to be
specialized for the environment where they will be installed. The drawback of
this approach is that there might not be a single solution to a dependency
problem that works everywhere. Each combination of
OS/architecture/distro/version could, in theory, require a different dependency
solution. There are way too many combinations of those properties to run Dune's
dependency solver once for each combination in a reasonable amount of time.
Instead we elected to compromise and have Dune only generate a solution for
common platforms by default, while allowing users to specify a custom list of
platforms to solve for in their dune-workspace
file.
Lockfiles now look a little different to account for the fact that they now
contain multiple different platform-specific dependency solutions. For example,
formerly, the lockfile for the ocaml-compiler
package on an x86 machine running
Windows, you might have had a depends
field like:
(depends arch-x86_64 system-mingw mingw-w64-shims flexdll)
Most of these dependencies are specific to Windows; it's unlikely that you'll be able to install any of these dependencies on Linux or MacOS.
With the portable lock directories feature enabled, this field now might look like:
(depends
(choice
((((arch x86_64)
(os linux))
((arch arm64)
(os linux))
((arch x86_64)
(os macos)
(os-distribution homebrew)
(os-family homebrew))
((arch arm64)
(os macos)
(os-distribution homebrew)
(os-family homebrew)))
())
((((arch x86_64)
(os win32)
(os-distribution cygwin)
(os-family windows)))
(arch-x86_64 system-mingw mingw-w64-shims flexdll))
((((arch arm64)
(os win32)
(os-distribution cygwin)
(os-family windows)))
(system-mingw mingw-w64-shims flexdll))))
This new syntax is similar to a match-statement, listing the dependencies for
each platform for which Dune's solver ran. You can change the platforms Dune
will solve for by adding something like this to dune-workspace
:
(lock_dir
(solve_for_platforms
((arch arm64)
(os openbsd))
((arch x86_32)
(os win32))))
After running dune pkg lock
again, the lockfile for ocaml-compiler
will be
updated with these dependencies:
(depends
(choice
((((arch arm64) (os openbsd))) ())
((((arch x86_32)
(os win32)))
(system-mingw ocaml-option-bytecode-only flexdll))))
A few other fields of lockfiles now also use the new syntax. Dune lockfiles contain the commands needed to build and install each package, as well as the names of any system packages needed by the Opam package, and each of these fields can also have platform-specific values.
Lockfile names now include the version number of the package. The
ocaml-compiler
package used to have a lockfile named ocaml-compiler.pkg
but
now has a name like ocaml-compiler.5.3.0.pkg
instead. This is because it's
possible that different platforms may require different versions of the same
package in the dependency solution, so the lock directory needs to be able to
contain multiple lockfiles for the same package without them colliding on
filename.
How do I get it?
This feature is live in the latest version of the Dune Developer
Preview. Follow the instructions on that page to
install a version of Dune with this feature. With portable lock directories
enabled, Dune will temporarily remain backwards compatible with the original
lock directory format, though support will likely be dropped at some point.
Generate a new lock directory by running dune pkg lock
. You'll know your lock
directory is portable if each file inside it has a version number in its
filename.
Happy reproducible building!
Discuss this post on Discuss!
Dune can install and run developer tools in the context of a project. This feature is available in the Dune Developer Preview and in the upcoming release of Dune 3.17. As with all of Dune's package management features, consider this feature to be unstable as its UI and semantics may change without notice.
The currently supported tools are ocamllsp
and ocamlformat
. Dune has a new
command dune tools exec <TOOL> -- [ARGS]...
which downloads and installs the
given tool, and then runs it with the given arguments (note the --
which
separates arguments to dune
from arguments to the tool). Tools are installed
locally to the project, in its _build
directory, which makes it easy to use
different versions of a tool in different projects. An unfortunate consequence
of installing tools into _build
is that for the time being all tools are
uninstalled whenever dune clean
is run.
Let's see it in action:
$ dune tools exec ocamlformat -- --version
Solution for dev-tools.locks/ocamlformat:
- ocamlformat.0.26.2+binary-ocaml-5.2.0-built-2024-11-07.0-x86_64-unknown-linux-musl
Building ocamlformat.0.26.2+binary-ocaml-5.2.0-built-2024-11-07.0-x86_64-unknown-linux-musl
Running 'ocamlformat --version'
0.26.2
Precompiled Binaries
Note that in the example above, Dune's package solver chose to install version 0.26.2+binary-ocaml-5.2.0-built-2024-11-07.0-x86_64-unknown-linux-musl
of ocamlformat
. This packages comes from a new repository of binary packages
containing pre-built executables for a select few Opam packages. Dune will search this
repository in addition to the default repositories when solving packages for
tools only (if a project has ocamlformat
in its dependencies, the binary
repository won't be searched while solving the project's dependencies).
The goal of the binary repository is to reduce the time it takes to get started
working on a new project. Without it, Dune would need to build ocamlformat
from source along with all of its dependencies, which can take several minutes.
For now only a small number of package versions are contained in the binary
repository. To demonstrate, here's what happens if we run dune tools exec ocamlformat
in a project
with version=0.26.1
in its .ocamlformat
file:
$ dune tools exec ocamlformat -- --version
Solution for dev-tools.locks/ocamlformat:
- astring.0.8.5
- base.v0.17.1
- base-bytes.base
- base-unix.base
- camlp-streams.5.0.1
- cmdliner.1.3.0
...
- ocamlformat.0.26.1
...
Building base-unix.base
Building ocaml-base-compiler.5.1.1
Building ocaml-config.3
Building ocaml.5.1.1
Building seq.base
Building cmdliner.1.3.0
...
Building ocamlformat.0.26.1
Running 'ocamlformat --version'
0.26.1
Dune parses .ocamlformat
to determine which version of ocamlformat
to
install, and 0.26.1
is not in the binary repo so it needed to be built from
source.
If your project requires a version of a package not available in the binary
repository, or you're on an operating system or architecture for which no binary
version of a package exists, the package will be built from source instead.
Currently the binary repository contains binaries of ocamlformat.0.26.2
,
ocaml-lsp-server.1.18.0
and ocaml-lsp-server.1.19.0
for
x86_64-unknown-linux-musl
, x86_64-apple-darwin
and aarch64-apple-darwin
.
Note that Linux binaries are statically linked with muslc so they should work on all distros regardless of dynamic linker.
Running ocamllsp
The program ocamllsp
from the package ocaml-lsp-server
analyzes OCaml code
and sends information to text editors using the Language Server
Protocol. The tool is crucial
to OCaml's editor integration and it has a couple of quirks that are worth
mentioning here.
TL;DR: Install Dune with the install script on the Developer Preview
page and you'll get an ocamllsp
shell
script
that will install and run the correct version of ocamllsp
for your project.
Firstly the ocamllsp
executable can only analyze code that has been compiled
with the same version of the OCaml compiler as was used to compile the
ocamllsp
executable itself. Different versions of the ocaml-lsp-server
package are incompatible with some versions of the OCaml compiler (e.g.
ocaml-lsp-server.1.19.0
must be built with at least 5.2.0
of the compiler).
This means that when Dune is choosing which version of ocaml-lsp-server
to
install it needs to know which version of the compiler your project is using.
This is only known after the project has been locked (by running dune pkg lock
), so Dune will refuse to install ocamllsp
in a project that doesn't
have a lock directory or for a project that doesn't depend on the OCaml compiler.
$ dune tools exec ocamllsp
Error: Unable to load the lockdir for the default build context.
Hint: Try running 'dune pkg lock'
The ocaml-lsp-server
packages in the binary
repository contain
metadata to ensure that the ocamllsp
executable that gets installed was built
with the same version of the compiler as your project. For example the
ocaml-lsp-server
package built with ocaml.5.2.0
contains this line:
conflicts: "ocaml" {!= "5.2.0"}
This prevents it from being chosen if the project depends on any version of the
compiler other than 5.2.0
.
Another quirk is that ocamllsp
will try to invoke the binaries ocamlformat
and ocamlformat-rpc
, both found in the ocamlformat
package. The
ocaml-lsp-server
package doesn't depend on ocamlformat
as the specific
version of ocamlformat
needed by a project is implied by the project's .ocamlformat
file, which package managers don't consider when solving dependencies. This
means that in general (whether using Dune or Opam for package management) it's
up to the user to make sure that the correct version of ocamlformat
is
installed in order to use the formatting features of ocamllsp
.
Otherwise expect this error in your editor:
Unable to find 'ocamlformat-rpc' binary. Types on hover may not be well-formatted. You need to install either 'ocamlformat' of version > 0.21.0 or, otherwise, 'ocamlformat-rpc' package.
Even if ocamllsp
and ocamlformat
are both installed by Dune, if you run
dune tools exec ocamllsp
you will find that ocamllsp
still can't find the
ocamlformat
or ocamlformat-rpc
executables. This is because unlike Opam,
Dune does not install tools into your $PATH
, and for the sake of simplicity,
the dune tools exec <TOOL>
command does not modify the environment of the tool
it launches. This can be fixed by adding
_build/_private/default/.dev-tool/ocamlformat/ocamlformat/target/bin
(the
directory containing ocamlformat
and ocamlformat-rpc
when ocamlformat
is
installed by dune) to the start of your $PATH
variable before running
dune tools exec ocamllsp
. For example starting ocamllsp
with the following shell script:
OCAMLFORMAT_TARGET="_build/_private/default/.dev-tool/ocamlformat/ocamlformat/target"
if!$OCAMLFORMAT_TARGET;then # Make sure that the ocamlformat dev tool is installed as it's needed by
# ocamllsp. There's currently no command that just installs ocamlformat so
# we need to run it and ignore the result.
# Add ocamlformat to the environment in which ocamllsp runs so ocamllsp can invoke ocamlformat.
# Build and run ocamllsp.
Of course, it's rare to manually start ocamllsp
directly from your terminal.
It's normally launched by text editors. It would be impractical to configure your text
editor to modify $PATH
and run a custom command to start ocamllsp
via Dune,
and doing so would make it impossible to edit any project that doesn't use
Dune for package management. Instead, the Dune Developer Preview ships with
a shell script
which installs ocamlformat
and adds its bin
directory to $PATH
before
launching dune tools exec ocamllsp
. The script is simply named ocamllsp
, and
the Dune Developer Preview install script adds it to ~/.dune/bin
which should
already be in your $PATH
if you're using the Developer Preview. The ocamllsp
script also attempts to fall back to an Opam-managed installation of ocamllsp
if it doesn't detect a Dune lockdir so the same script should work for non-Dune
projects. Because the script is named the same as the ocamllsp
executable,
most editors don't require special configuration to run it. See the "Editor
Configuration" section of the Dune Developer
Preview page for more information about setting up
your editor.
Some parts of the ocamllsp
shell script may eventually make their way into
Dune itself, but for the time being the shell script is the recommended way to
launch ocamllsp
for users of the Dune Developer Preview. The net result is
that as long as your project has a lockfile, the first time you edit some OCaml
code in the project Dune will download and run the appropriate version of
ocamllsp
.
Discuss this post on Discuss!
Support for dune shell completions for bash and zsh has just landed in the Dune Developer Preview!
Running the installer adds a snippet to
your shell config (e.g. ~/.bashrc) that installs a completion handler for dune
.
The completion script was taken from
here, and that page has
some information about how the script was generated. Once it's installed the
completions will work any time dune
is typed at the start of a command, so
you can still use the completions when running a version of Dune installed with
Opam or your system package manager after installing the Dune Developer Preview.
Currently only command completions are supported. So you can run:
$ dune c<TAB>
cache clean coq
...or:
$ dune build -<TAB>
--action-stderr-on-success
--action-stdout-on-success
--always-show-command-line
--auto-promote
--build-dir
--build-info
--cache
...
But if you run dune build <TAB>
then it will still suggest
local files rather than build targets.
Try it out!
Getting started is easy:
$ curl -fsSL https://get.dune.build/install | sh
$ source ~/.bashrc # or: source ~/.zshrc
$ dune <TAB>
build
cache
clean
coq
describe
diagnostics
exec
...
Hello folks! π
We'd like to welcome everyone to try and play with the Dune Developer Preview! π
This experimental nightly release of dune includes a lot of improvements, including the much expected package management features, and it can be installed from that website or by using the new installation script:
$ curl -fsSL https://get.dune.build/install | bash
In a few seconds you should be ready to OCaml by calling dune
:
You can also watch and share this demo on X and Mastodon.
Please try it out and let us know what you think π
π You can book a feedback call with us here
π You can submit feedback using this form
π You can submit issues to Github on ocaml/dune
Changes since last update
The Dune shared cache has been enabled by default. We're starting off by caching all downloads and dependencies.
We have improved support for dev tools. We're working to streamline this but in the latest binary you can:
-
Configure your LSP (in Neovim, Vim, Emacs, etc) to call
dune tools exec ocamllsp
to get LSP support for your projects out of the box β this may take a little bit the first time it builds the LSP for a compiler version, but it's pretty much instant afterwards. -
Call
dune fmt
to get your project formatted β remember to add an.ocamlformat
file if you don't have one yet. An empty one is enough. -
Call
dune ocaml doc
to get documentation built
What's next?
We're looking forward to streamlining the DX, working on better dependency locks, and looking into supporting Windows.
In particular, we're considering work on a few things:
dune create <repo>
β to let the community create templates that can be easily used from within dunedune pkg fetch
β to prefetch packages and prepare a repository for working in offline modedune build @deps
- to build all dependencies, useful for staged builds in Dockerfilesdune pkg add <name>
- to make adding packages straightforward- a short-hand syntax for pins on github
- and more!
If you've got any ideas, we'd love to hear them, so please open a feature request on Github π
Other updates
FunOCaml Presentation
At FunOCaml we had a last-minute opportunity to present the work being done on Dune and we used it to introduce the Developer Preview to the community, and even tested Package Management live with suggestions from the audience (thanks @anmonteiro and Paul-Elliot for participating!) β you can watch it on Twitch.
New design
We're working with @Claire_Vandenberghe on redesigning the Developer Preview website so that it'd feel like a seamless extension of OCaml.org β in this current iteration we've made it easier to get started and we're putting the FAQ front and center.
We'll be iterating on this design in the coming weeks until it fits perfectly within the OCaml.org design system π¨
You can check the new website here: https://preview.dune.build
Upcoming Blog posts
In the near future we'll be publishing blog posts about the Developer Preview and Package Management, which we're working on with @professor.rose π
As we prepare for the public beta, we're ramping up the DX interviews and ensuring the first few users will have a fun, productive experience with the Developer Preview.
π₯ If you signed up for the Dev Preview back in May, check your inbox for a link and instructions to schedule your DX interview with us.
Here's a sample video on (Mastodon or X) where you can see us building the Riot project on a machine that does not have OCaml installed. It is pretty neat!
Seriously, big shoutout to the Dune team at Tarides[0] and Jane Street[1] who have been doing a phenomenal job π β¨ π«
So here's what getting started with OCaml looks like using the Dune Developer Preview as of today (August 19 2024):
- get
dune
from our binary distribution β we'll soon make this public! - run
dune pkg lock
in your favorite project - run
dune build
That's it. No need to install anything else! Dune will see that lock file, fetch, and build all necessary dependencies.
πΊοΈ These are some strong steps towards the OCaml Platform vision for 2026 that we are actively working towards. If you have any thoughts or feedback please let us know!
There are more improvements coming that will help remove friction to get started and create a delightful experience. Both of these things we strongly believe will help onboard new users to the OCaml world.
Here's a few in the works:
-
Various DX improvements β from new outputs to simplified workflows, we want to make using Dune just delightful.
-
Bundled support for dev tools (OCamlFormat,
odoc
, LSP) β the default toolset will be available without any extra steps! Just calldune fmt
and it works. No need to manually install anything else. -
Automatic dependency locking β when building, and even in watch mode, Dune will lock your dependencies by default and keep the lock up to date.
-
Cross-project caching β by default we'll enable a local Dune cache across the system, so you never rebuild the same dependency, even across projects.
-
Signed binaries with certificates of origin β we care deeply about security and want to make sure that any binary we ship can be easily verified and tracked back to its sources.
Stay tuned! π
PS: here's a longer video on (Mastodon or X) showing you the setup for OCaml from zero, creating a new project, and adding a dependency, all within ~5 minutes
[0] @emillon @Leonidas @gridbugs @tmattio @maiste . Ambre Suhamy, Alpha Diallo [1] @rgrinberg