dune/doc/project-layout-specificatio...

236 lines
8.0 KiB
ReStructuredText
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

*****************************************
Project Layout and Metadata Specification
*****************************************
A typical jbuilder project will have a ```dune-project`` and one or
more ``<package>.opam`` file at toplevel as well as ``jbuild`` files
wherever interesting things are: libraries, executables, tests,
documents to install, etc...
It is recommended to organize your project so that you have exactly one
library per directory. You can have several executables in the same
directory, as long as they share the same build configuration. If you'd
like to have multiple executables with different configurations in the
same directory, you will have to make an explicit module list for every
executable using ``modules``.
The next sections describe the format of Jbuilder metadata files.
Note that the Jbuilder metadata format is versioned in order to ensure
forward compatibility. There is currently only one version available,
but to be future proof, you should still specify it in your ``jbuild``
files. If no version is specified, the latest one will be used.
.. _metadata-format:
Metadata format
===============
Most configuration files read by Jbuilder are using the S-expression
syntax, which is very simple. It is described below.
Note that the format is completely static. However you can do
meta-programming on jbuilds files by writing them in :ref:`ocaml-syntax`.
Lexical conventions of s-expressions
------------------------------------
Whitespace, which consists of space, newline, horizontal tab, and form
feed, is ignored unless within an OCaml-string, where it is treated
according to OCaml-conventions. The left parenthesis opens a new
list, the right one closes it. Lists can be empty.
The double quote denotes the beginning and end of a string using
similar lexing conventions to the ones of OCaml (see the OCaml-manual
for details). Differences are:
- octal escape sequences (``\o123``) are not supported;
- backslash that's not a part of any escape sequence is kept as it is
instead of resulting in parse error;
- a backslash followed by a space does not form an escape sequence, so
its interpreted as is, while it is interpreted as just a space by
OCaml.
All characters other than double quotes, left- and right parentheses,
whitespace, carriage return, and comment-introducing characters or
sequences (see next paragraph) are considered part of a contiguous
string.
Comments
--------
There are three kinds of comments:
- line comments are introduced with ``;``, and end at the newline;
- sexp comments are introduced with ``#;``, and end at the end of the
following s-expression;
- block comments are introduced with ``#|`` and end with ``|#``.
These can be nested, and double-quotes within them must be balanced
and be lexically correct OCaml strings.
Grammar of s-expressions
------------------------
S-expressions are either sequences of non-whitespace characters
(= atoms), doubly quoted strings or lists. The lists can recursively
contain further s-expressions or be empty, and must be balanced,
i.e. parentheses must match.
Examples
--------
::
this_is_an_atom_123'&^%! ; this is a comment
"another atom in an OCaml-string \"string in a string\" \123"
; empty list follows below
()
; a more complex example
(
(
list in a list ; comment within a list
(list in a list in a list)
42 is the answer to all questions
#; (this S-expression
(has been commented out)
)
#| Block comments #| can be "nested" |# |#
)
)
.. _opam-files:
dune-project files
==================
These files are used to mark the root of projects as well as define
project-wide parameters. These files are required to have a ``lang``
which controls the names and contents of all configuration files read
by Dune. The ``lang`` stanza looks like:
.. code:: scheme
(lang dune 0.1)
The 0.1 version of the language is exactly the same as the Jbuilder
language. So to convert a Jbuilder project to Dune, simply write this
file at the root of your project.
Additionally, they can contains the following stanzas.
name
----
Sets the name of the project:
.. code:: scheme
(name <name>)
<package>.opam files
====================
When a ``<package>.opam`` file is present, Jbuilder will know that the
package named ``<package>`` exists. It will know how to construct a
``<package>.install`` file in the same directory to handle installation
via `opam <https://opam.ocaml.org/>`__. Jbuilder also defines the
recursive ``install`` alias, which depends on all the buildable
``<package>.install`` files in the workspace. So for instance to build
everything that is installable in a workspace, run at the root:
::
$ jbuilder build @install
Declaring a package this way will allow you to add elements such as
libraries, executables, documentation, ... to your package by declaring
them in ``jbuild`` files.
Such elements can only be declared in the scope defined by the
corresponding ``<package>.opam`` file. Typically, your
``<package>.opam`` files should be at the root of your project, since
this is where ``opam pin ...`` will look for them.
Note that ``<package>`` must be non-empty, so in particular ``.opam``
files are ignored.
.. _scopes:
Scopes
------
Any directory containing at least one ``<package>.opam`` file defines
a scope. This scope is the sub-tree starting from this directory,
excluding any other scopes rooted in sub-direcotries.
Typically, any given project will define a single scope. Libraries and
executables that are not meant to be installed will be visible inside
this scope only.
Because scopes are exclusive, if you whish to include the dependencies
of the project you are currently working on into your workspace, you
may copy them in a ``vendor`` directory, or any other name of your
choice. Jbuilder will look for them there rather than in the installed
world and there will be no overlap between the various scopes.
Package version
---------------
Note that Jbuilder will try to determine the version number of packages
defined in the workspace. While Jbuilder itself makes no use of version
numbers, it can be use by external tools such as
`ocamlfind <http://projects.camlcity.org/projects/findlib.html>`__.
Jbuilder determines the version of a package by first looking in the
``<package>.opam`` for a ``version`` variable. If not found, it will try
to read the first line of a version file in the same directory as the
``<package>.opam`` file. The version file is any file whose name is, in
order in which they are looked for:
- ``<package>.version``
- ``version``
- ``VERSION``
The version file can be generated by a user rule.
If the version can't be determined, Jbuilder just won't assign one.
Note that if you are using `Topkg <https://github.com/dbuenzli/topkg>`__
as well in your project, you shouldn't manually set a version in your
``<package>.opam`` file or write/generate on of the file listed above.
See the section about :ref:`using-topkg` for more details.
Odig conventions
----------------
Jbuilder follows the `odig <http://erratique.ch/software/odig>`__
conventions and automatically installs any README\*, CHANGE\*, HISTORY\*
and LICENSE\* files in the same directory as the ``<package>.opam`` file
to a location where odig will find them.
Note that this includes files present in the source tree as well as
generated files. So for instance a changelog generated by a user rule
will be automatically installed as well.
jbuild-ignore
=============
By default Jbuilder traverses the whole source tree, ignoring the
following files and directories:
- any file that start with ``.#``
- any directory that start with either ``.`` or ``_``
To ignore a subtree, simply write a ``jbuild-ignore`` file in the
parent directory containing the name of the sub-directories to ignore.
So for instance, if you write ``foo`` in ``src/jbuild-ignore``, then
``src/foo`` won't be traversed and any ``jbuild`` file it contains will
be ignored.
``jbuild-ignore`` files contain a list of directory names, one per line.