The OCaml Ecosystem¶
The OCaml ecosystem is not monolithic: the compiler and tools are not maintained by the same entities. As such, it can be difficult to understand the history and roles of the various pieces of this ecosystem. The goal of this page is to give a quick overview of the situation and the role that Dune plays in it.
The OCaml Compiler Distribution: Compiling and Linking¶
The OCaml compiler distribution contains
“core” tools including the compilers (ocamlc
and ocamlopt
). They turn
source files (with extensions .ml
and .mli
) into executables and
libraries. Dependencies between compiled objects only exist at the module
level, so this is a low-level tool.
Findlib: Metadata for Libraries¶
Findlib is a tool that defines the concept of library, so that libraries can
depend on other libraries on top of the notion of module. Definitions of
libraries, and other pieces of metadata, are stored in META
files.
Findlib ships an executable named ocamlfind
that can be used as a wrapper
on top of the compilers to perform tasks such as producing an executable from
compiled object files and external libraries.
Opam: a Collection of Software Projects¶
Opam is a package manager. It is used to determine which packages are necessary, and how to fetch and build them. Packages can contain libraries, executables, and other kinds of files.
The notion of version is specific to opam. If your project uses a function
named Png.read_file
but this function has been added only in version
1.2.0
of that package, opam needs to know about it.
Opam manages collections of installed packages, called switches. Using your project’s dependencies (names and version constraints), it is able to create a switch that you’ll be using to develop your project.
Public definitions of packages are available in a database called
opam-repository
which is maintained as a public Git repository. Publishing a
package on opam (to make sure that external users can use your project)
consists in adding its definition to opam-repository
.
Dune: Giving Structure to Your Source Tree¶
Dune is a build system. It is used to orchestrate the compilation of source files into executables and libraries.
Assuming you have a development switch set up, you communicate to Dune about how your project is organized in terms of executables, libraries, and tests. It is then able to assemble the source files of your projects, with the dependencies installed in an opam switch, to create compiled assets for your project.
How Dune Integrates With the Ecosystem¶
Dune is designed to integrate with the tools mentioned above:
By knowing how the OCaml compilers operate, it knows which build commands should be re-executed if some source files change.
It outputs metadata like dependency information into
META
files that Findlib is able to make use of. This ensures that even if a project does not use Dune, it can use a library that has been produced by Dune. Conversely, it can read these files to determine dependency information for dependencies that have not been produced by Dune.It is able to generate opam files with filenames consistent with how opam looks for them. The generated files use build commands that make use of the
@install
and@runtest
aliases so that the Dune abstractions map to the opam ones.
Dune is Opinionated¶
As described above, the OCaml ecosystem does not have a centralized toolchain. Units such as modules, libraries, and packages operate at different levels, and the relation between these can be confusing to users.
Dune tries to simplify the picture by reducing the difference between these objects:
By default, a library will only expose a single top-level module named after the library (this is called a wrapped library).
A library can only be installed in the package of the same name. This means that the names found in
dune-project
andopam
files (package names) are consistent with the names found indune
files (library names). More precisely, librariesfoo
,foo.bar
andfoo.baz
are part of thefoo
package.