# Dune for OCaml: composable builds, monorepos, and opam workflows

> Dune turns static `dune` files into OCaml compilation rules, installation metadata, and development-tool configuration. It is a strong fit for multi-package OCaml repositories, though its declarative S-expression model requires teams to accept a project-specific build vocabulary.

**ocaml/dune** — A composable build system for OCaml.

- Repository: https://github.com/ocaml/dune
- Website: https://dune.build/
- Stars: 1,934 · Forks: 508
- Language: OCaml
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/ocaml-dune

## Why Dune sits inside an OCaml repository

Dune addresses the gap between source files and the low-level mechanics of compiling OCaml. A project supplies static metadata, and Dune derives build rules from it. The target audience is developers who want a consistent command-line workflow across libraries, executables, tests, installed packages, and development tools rather than a hand-maintained compilation script.

The repository's composition model is its main architectural distinction. Multiple Dune projects can be arranged so that one build recognizes their combined dependency graph. That makes Dune relevant to monorepos and repositories containing several opam packages, where each package still needs its own installation boundary even though development happens in one tree. The README also addresses simultaneous development across those packages rather than treating a repository as a single indivisible build target.

Dune extends beyond compilation. It reads project metadata for development-tool configuration, including Merlin configuration, and uses the same project description to support installation. This shared source of metadata reduces the number of independent descriptions, but it also means `dune` files become part of the project's build contract rather than optional developer notes.

## From static dune files to build rules

A `dune` file is a static file written in a simple S-expression syntax. Dune reads those files and uses the declarations to set up build rules, generate configuration for tools such as Merlin, and handle installation. The README does not provide the grammar or a complete project example, so the precise meaning of each declaration belongs in Dune's linked manual and the repository's `example` directory.

This is a metadata-driven build system, not an imperative shell script. The intended data flow begins with project declarations, continues through Dune's interpretation of components and their dependencies, and ends in compilation, configuration generation, or installation work. Dune can execute parallel builds on all supported platforms because the dependency graph supplies the ordering. The README says Dune has no system dependencies and that OCaml is sufficient to build Dune and packages using it.

The composable model changes how a multi-package repository behaves. Instead of restricting a build to one package by default, Dune can coordinate several project descriptions as one known build. For opam builds, Dune is also documented as correctly distinguishing libraries previously installed through opam from libraries already present in the source tree. That distinction matters when local development depends on generated or modified libraries rather than the installed copies.

## Installing Dune and selecting one opam package

Dune requires OCaml 4.14.0 or newer to build itself, while projects built by Dune can use OCaml 4.02.3 or newer. The documented installation route is opam, which fits Dune's close relationship with package-level metadata and opam builds.

Install it with:

```bash
opam install dune
```

If the current shell does not expose opam's environment yet, the README specifically directs new opam users to run:

```bash
eval $(opam config env)
```

After that, the installation provides the `dune` binary in the shell's `PATH`. The binary is described as self-contained and relocatable. For a repository that contains several opam packages, the documented build-and-install invocation for one selected package is:

```bash
dune build --only-packages <package-name> @install
```

This is the first useful operation to try in an existing multi-package project. It selects `<package-name>`, builds its install target, and exercises package selection rather than merely producing an unspecified default target. The README does not state the exact artifact names this command creates, so verification should focus on command success and the package's installation outputs rather than a guessed filename.

A developer working on Dune itself has separate bootstrap routes. The short manual sequence first creates `dune.exe`, then builds its installed files, then installs them:

```bash
ocaml boot/bootstrap.ml
./dune.exe build -p dune --profile dune-bootstrap
./dune.exe install dune
```

The repository Makefile exposes the same work as `make release` followed by `make install`. Its `release` target builds `dune.install`, while `install` invokes `_boot/dune.exe install` with any supplied `PREFIX`, `LIBDIR`, and `DESTDIR` values.

## Configuration matrices and cross-compilation boundaries

Dune can build the same source repository against several configurations at once. The README identifies package maintenance across OCaml versions as a direct use case: instead of switching a single tree between compilers one after another, a project can hold several configurations in view at the same time. That is especially relevant when package compatibility is the concern rather than an ordinary local edit.

Cross-compilation is part of the same model, but it has an explicit dependency: the README says this feature requires opam. Dune therefore does not present every configuration mode as a self-contained operation. The package manager is part of the documented path for managing builds across distinct compiler or target environments.

There is also a practical limit on what can be claimed. The README describes simultaneous configuration builds, but it does not enumerate every supported cross target, configuration file, or invocation in the excerpt. Projects should consult the linked cross-compilation manual rather than infer syntax from the basic `dune` file mechanism. This is a case where Dune's concise overview is not a substitute for the detailed manual, especially for non-native targets and package variants.

## Where Dune adds friction or is the wrong tool

Dune's main adoption cost is conceptual rather than a system dependency. Teams must model components, dependencies, build rules, and package boundaries through Dune's S-expression syntax. The README calls the syntax simple, but it does not claim that the full build vocabulary is self-explanatory. A team whose existing process is already fully specified by another accepted mechanism may gain little from translating that model into `dune` files.

The composition model can also make scope less obvious in a large repository. Building several projects as one graph is useful for monorepos, yet selecting the intended package and install target remains important. The documented `@install` command addresses this by using `--only-packages`. Without an explicit package selection, the README does not provide enough detail to predict which install artifacts a large workspace build should produce, so release automation should not treat an unqualified command as equivalent to package-scoped installation.

Dune is not the right tool for a non-OCaml project that merely needs a generic build orchestrator. The repository states that Dune is a build system for OCaml and makes OCaml a fundamental requirement. Nor does it replace opam when package selection, installed dependency resolution, or cross-compilation configurations are being handled through opam. The documented roles overlap, but they are not identical.

## Dune releases, upgrades, and MIT implications

The repository is not archived, and its last push was on 2026-10-16. The release list includes `3.24.2` dated 2026-08-03, `3.24.1` dated 2026-07-21, and the prerelease `3.25.0_alpha0` dated 2026-10-02. Those dates distinguish the stable patch releases from the newer alpha, but they do not by themselves establish compatibility for a particular OCaml project.

An upgrade decision therefore has to account for both sides of the version boundary. Dune itself requires OCaml 4.14.0 or newer to build, while it can build projects using OCaml 4.02.3 or newer. The presence of `3.25.0_alpha0` means an upgrade target can be prerelease code even though stable `3.24.2` is also listed. The README does not document an upgrade procedure, rollback procedure, or compatibility table for these releases, so those points must be checked in release notes and project CI rather than inferred.

The repository is licensed under MIT. That permits use, modification, distribution, and sublicensing subject to the license's conditions, including preservation of its copyright and permission notice. Projects that vendor or redistribute Dune should keep the applicable license text in place. This is a licensing observation, not legal advice, and organizations with distribution policies still need to apply their own review.

## Dune versus an isolated package build

The most relevant alternative is not another named product but a separate build boundary for each package, with package commands invoked only in that package's directory. That approach can be easier to explain when a repository contains independent releases with different build settings and little shared development.

Dune takes the opposite approach. It composes multiple Dune projects into one build that Dune can execute, allowing a monorepo to retain several package descriptions while coordinating work across them. Its opam integration also handles libraries already present in the source tree when they might otherwise collide with previously installed versions. For synchronized changes across packages, this repository-wide graph removes the need to keep isolated builds synchronized manually.

The trade-off follows directly from that benefit. A repository-wide model requires consistent `dune` metadata and gives Dune more responsibility for dependency interpretation. Isolated builds give each package a narrower scope and can simplify release reasoning, but they do not provide Dune's documented ability to build all configurations together or combine projects into a single known graph. The appropriate choice depends on whether the repository is one development unit or a collection of independently versioned units.

## Conclusion

Dune suits OCaml teams with several packages, shared build rules, or opam-managed configurations, especially when repository-level composability matters. It is a poor choice when a project cannot adopt declarative `dune` files or when `dune` metadata would duplicate an external build system without adding value. Before adoption, verify that the target OCaml version is 4.02.3 or newer, inspect the generated package boundaries, and confirm that the selected release has passed the project's own integration checks.

## FAQ

### What OCaml version does Dune require?

Dune requires OCaml 4.14.0 or newer to build itself. Projects built by Dune can use OCaml 4.02.3 or newer.

### How do I install Dune and make it available in PATH?

The recommended command is `opam install dune`. For a shell that has not loaded the opam environment, the README gives `eval $(opam config env)`.

### How do I build and install one package from a Dune monorepo?

The README gives `dune build --only-packages <package-name> @install` for selecting a package and building its install target.

### Does Dune cross-compilation require opam?

Yes. The README explicitly states that Dune's cross-compilation feature requires opam.

### Can a copied Dune executable be moved to another directory?

The README describes the `dune` binary as self-contained and relocatable. It discovers its environment at runtime rather than hard-coding it at compilation time.

## Sources

- [License: MIT](https://github.com/ocaml/dune/blob/main/LICENSE)
- [ocaml/dune on GitHub](https://github.com/ocaml/dune)
- [Project website](https://dune.build/)
- [README](https://github.com/ocaml/dune/blob/main/README.md)
- [Releases](https://github.com/ocaml/dune/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ocaml-dune
