# Ocaml Dune Migration

> Migrating OCaml projects from ocamlbuild/topkg to dune. Use when discussing _tags files, .mllib files, pkg/pkg.ml, topkg, or build system migration.

- Skill: `majiayu000/ocaml-dune-migration` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/ocaml-dune-migration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/ocaml-dune-migration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: ISC
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/ocaml-dune-migration

---


# OCaml Build System Migration

## When to Use This Skill

Invoke this skill when:
- Converting a project from ocamlbuild to dune
- Discussing _tags, .mllib, or pkg.ml files
- Migrating from topkg to dune
- Understanding ocamlbuild artifacts

## Process Overview

### 1. Analyze the Existing Build

Read these files to understand the project:
- `_tags` - ocamlbuild compilation flags and package dependencies
- `pkg/pkg.ml` - topkg package description
- `pkg/META` - findlib metadata
- `*.mllib` files - module lists for libraries
- `opam` - package dependencies

### 2. Create dune-project

```dune
(lang dune 3.20)
(name <package-name>)
(generate_opam_files true)
```

### 3. Create Library dune Files

For each library (from `.mllib` files):

```dune
(library
 (name <library_name>)
 (public_name <package.subname>)
 (libraries <dependencies>))
```

For optional libraries (from `pkg/pkg.ml`):

```dune
(library
 (name <library_name>)
 (public_name <package.subname>)
 (optional)
 (libraries <dependencies>))
```

### 4. Handle Toplevel Init Files

Files like `*_top_init.ml` shouldn't be compiled as modules:

```dune
(library
 (name lib_name)
 (modules lib_module)  ; Explicitly list modules
 (libraries deps))

(install
 (package pkg)
 (section lib)
 (files lib_top_init.ml))
```

### 5. Handle Warnings

If the original code triggers warnings:

```dune
(library
 (name lib)
 (flags (:standard -w -27)))
```

Common warnings to suppress in vendored code:
- `-w -27` - unused variable

### 6. Create Test dune File

```dune
(test
 (name test_name)
 (libraries lib_name alcotest))
```

For optional tests:

```dune
(executable
 (name test_optional)
 (modules test_optional)
 (optional)
 (libraries lib some_optional_lib))
```

### 7. Update opam File

1. Rename `opam` to `<package>.opam`
2. Remove ocamlbuild/topkg dependencies
3. Add dune:

```
depends: [
  "ocaml" {>= "4.14.0"}
  "dune" {>= "3.0"}
]
```

4. Update build commands:

```
build: [
  ["dune" "subst"] {dev}
  ["dune" "build" "-p" name "-j" jobs]
  ["dune" "runtest" "-p" name "-j" jobs] {with-test}
  ["dune" "build" "@doc" "-p" name "-j" jobs] {with-doc}
]
```

### 8. Documentation dune File

If there's a `doc/` directory:

```dune
(documentation
 (package <package-name>))
```

### 9. Remove ocamlbuild Files

Files to delete:
- `_tags`
- `.merlin`
- `pkg/pkg.ml`
- `pkg/META`
- `*.mllib` files
- `*.itarget` files
- The `pkg/` directory

## Mapping Reference

| ocamlbuild | dune |
|------------|------|
| `_tags: package(foo)` | `(libraries foo)` |
| `_tags: thread` | `(libraries threads)` |
| `foo.mllib` with `Foo` | `(library (name foo) (modules foo))` |
| `pkg/pkg.ml: Pkg.mllib ~cond:x` | `(library ... (optional))` |
| `pkg/META` | Auto-generated by dune |
| `opam` | `<package>.opam` |

## Common Issues

### "Library not found" for optional deps
Use `(optional)` on the library stanza.

### Unused variable warnings
Add `(flags (:standard -w -27))`.

### Module in wrong library
Use `(modules ...)` to explicitly list modules.

### Toplevel init files
Exclude from library with `(modules ...)` and use `(install ...)`.

## Verification

After migration:

```bash
dune build @check    # Verify syntax
dune build           # Build project
dune runtest         # Run tests
dune build @doc      # Build docs
```

