Projects with Dune & opam

By default a library mylib with files a.ml, b.ml exposes Mylib.A, Mylib.B.

23.1 dune-project

(lang dune 3.16)
(name myapp)
(generate_opam_files true)
(source (github user/myapp))
(authors "You <you@example.com>")
(license MIT)
(package
 (name myapp)
 (synopsis "A short description")
 (depends
  (ocaml (>= 5.1))
  dune
  cmdliner
  (alcotest :with-test)))

23.2 dune files

; lib/dune
(library
 (name mylib)
 (public_name myapp.mylib)
 (libraries str unix re)
 (preprocess (pps ppx_deriving.show ppx_yojson_conv)))

; bin/dune
(executable
 (public_name myapp)
 (name main)
 (libraries mylib cmdliner))

; test/dune
(test
 (name test_mylib)
 (libraries mylib alcotest))

23.3 Common dune commands

dune build                 # build everything (@default)
dune build @all
dune exec myapp -- --arg   # build & run
dune test                  # run tests (alias @runtest)
dune utop lib              # REPL with your library loaded
dune build @fmt --auto-promote   # format with ocamlformat
dune build @doc            # generate docs
dune clean
dune build --watch         # rebuild on change (-w)
dune promote               # accept expect-test output
dune pkg lock              # (dune package management, newer dune)

23.4 Library wrapping

By default a library mylib with files a.ml, b.ml exposes Mylib.A, Mylib.B. Write mylib.ml manually to control the public API.

23.5 Build profiles & flags

In dev profile, many warnings are errors — this is intentional.

(env
 (dev (flags (:standard -w +a-4-40-41-42-44-70)))
 (release (ocamlopt_flags (:standard -O3))))   ; -O3 requires a flambda switch
dune build --profile release

23.6 opam workflows

Lock files: opam lock → myapp.opam.locked.

opam install . --deps-only --with-test    # install project dependencies
opam search json
opam show yojson
opam update && opam upgrade
opam pin add mylib git+https://github.com/user/mylib.git
opam list
opam remove pkg
opam exec -- dune build