How to Organize Multiple Executables in Different Directories¶
A common question when a project grows beyond a single program is: “I want to build several executables, each living in its own directory. How do I set that up?”
Dune does not impose a particular layout on your project. You are free to place
your executables in whatever directories make sense to you. The key idea is
that you describe each directory with a dune file, and Dune assembles the
whole project from those descriptions.
The Mental Model¶
Three rules are enough to organize almost any project:
A project has a single
dune-projectfile at its root. It records project-wide information, most importantly the version of the Dune language in use.Every directory that contains something to build has its own
dunefile describing what is in that directory.An executable is defined by an executable stanza in the
dunefile of the directory where its sources live.
So to have executables in several directories, you simply put a dune file
with an executable stanza in each of those directories. Nothing forces them
to sit together, and there is no central list of executables to maintain.
Consider a project with a server and a client, each in its own
directory:
myproject/
├── dune-project
├── client/
│ ├── dune
│ └── client.ml
└── server/
├── dune
└── server.ml
The dune-project File¶
There is exactly one dune-project file, and it lives at the root of the
project. The directories below it do not need their own. At a minimum it
declares the language version:
(lang dune 3.25)
Executables in Multiple Subdirectories¶
Each executable is described where its sources are. The client/dune file
declares the client:
(executable
(name client))
And server/dune declares the server in the same way:
(executable
(name server))
With the source files in place, for example client/client.ml:
let () = print_endline "client starting"
Dune builds both executables from the root of the project:
$ dune build
You run each one by giving its path relative to the project root, using the
.exe extension regardless of platform:
$ dune exec client/client.exe
client starting
$ dune exec server/server.exe
server starting
The directory names (client and server) are entirely your choice, and
the directories can be nested as deeply as you like. Dune discovers them by
reading the dune files it finds while traversing the tree.
A Note on dune init¶
The dune init command can scaffold projects, executables, and libraries for
you, which is handy when you are starting out. It is only a convenience,
though: it writes the same dune-project and dune files shown above.
Once you understand the layout, you can create and arrange these files by hand
in whatever structure suits your project.