Project Description
Configuration files used by drom
are in TOML syntax. See also Learn TOML in Y minutes for a very quick
introduction.
A project is composed of the project itself, and a set of packages
(libraries and executables), among which the main package shares the
same name as the project. An opam
package is generated for
each package in the project.
The drom.toml
Project File
To get a feeling of what is in this file, we can look at the one used for
drom
itself:
[project]
drom-version = "0.1.0"
[project]
drom-version = "0.1.0"
[project]
authors = ["Fabrice Le Fessant <fabrice.le_fessant@origin-labs.com>", "Léo Andrès <leo.andres@ocamlpro.com>"]
copyright = "OCamlPro SAS & Origin Labs SAS"
edition = "4.10.0"
github-organization = "ocamlpro"
license = "LGPL2"
min-edition = "4.07.0"
mode = "binary"
name = "drom"
synopsis = "The drom tool is a wrapper over opam/dune in an attempt to provide a cargo-like user experience"
version = "0.2.0"
windows-ci = true
# keys that you could also define:
# build-profile = "...build-profile..."
# odoc-target = "...odoc-target..."
# sphinx-target = "...sphinx-target..."
# archive = "...archive..."
# dev-repo = "...dev-repo..."
# bug-reports = "...bug-reports..."
# doc-api = "...doc-api..."
# doc-gen = "...doc-gen..."
# homepage = "...homepage..."
[project]
description = """
The drom tool is a wrapper over opam/dune in an attempt to provide a cargo-like
user experience. It can be used to create full OCaml projects with
sphinx and odoc documentation. It has specific knowledge of Github and
will generate files for Github Actions CI and Github pages.
"""
[project]
skip = "sphinx/about.rst src/drom_lib/main.ml sphinx/index.rst CHANGES.md test/expect-tests/test.ml ocamlformat"
[dependencies]
[tools.ocamlformat]
for-test = true
[tools.odoc]
for-doc = true
[tools.ppx_expect]
for-test = true
[tools.ppx_inline_test]
for-test = true
[profile.dev]
ocaml-flags = "-w +a-4-40-41-42-44"
[profile.release]
ocaml-flags = "-w -a"
[project]
generators = ["ocamllex", "menhir"]
pack-modules = true
skip-dirs = ["drom-test"]
[[package]]
dir = "src/drom"
[[package]]
dir = "src/drom_lib"
Notice that every package contains only the directory where the
sources are located, in which drom
expects to find a file package.toml
describing the package itself.
The [project]
table
This table describes the main project. For multi-package projects, these fields are used as default if the corresponding fields are not specified in sub-packages.
Here is a short description of the fields:
name
: the name of the project and of its main package.version
: the current version of the projectauthors
: the list of authors of the project, to display in opam files and in the documentationcopyright
: the name of the copyright holder for the projectedition
: the version of OCaml to be used by default, when building locally or on the CIgithub-organization
: the organization owning the project on Github. This field is used to compute the URLs for the documentation.kind
: specify whether packages should be programs ("program"
) or libraries ("library"
) by default.license
: the identifier of the license. See the section about licenses.drom
knows a few license and may automatically generate the corresponding files.min-edition
: the minimal version of OCaml with which the project can be built. The CI will start at least one job with this version.mode
: the target of the compilation. It is either"binary"
for an executable, orjavascript
for a file generated byjs_of_ocaml
.synopsis
: a very short description of the project.opam
requires this field to start with an uppercase letter and not end with a dot.description
: a long description of the project.pack-modules
: a bool indicating whether modules should be packed.true
by default. It corresponds to thewrapped
field ofdune
.
Some fields are computed automatically if github-organization
is specified, but can be overriden:
archive
: the URL from where the sources can be downloaded. Can contain${version}
instead of the version.dev-repo
: the location of the VCS for the project. They are often specified withgit+https://
.bug-reports
: the URL where issues can be created.doc-api
: the URL where the documentation of the API can be found.doc-gen
: the URL where the general documentation can be found.homepage
: the URL of the project main homepage
Another important field is the skip
field:
skip
contains a space-separated list of files, that should not be modified anymore bydrom
. By default,drom
will generate any missing file, and upgrade any file that was previously generated bydrom
and not modified since then.drom
will print a warning everytime it finds a modified file. This option can be used to avoid this warning, or to preventdrom
from recreating an unwanted file.drom
generates a file_drom/maximum-skip-field.txt
showing all the values that can appear in this field.There is an exception for
drom.toml
andpackage.toml
files, that are only modified when the user configuration has been changed, a changing option passed todrom project
, or the--upgrade
option to benefit from a more recent version ofdrom
.skip
can also contains tags: such tags can be used to reference several files, related to the tag itself. For example, current skeletons use the following tags:code
(source files),docs
(documentation),sphinx
(sphinx documentation),test
(test files),github
(github pages and workflows). More tags may be defined in the future.To detect modifications of its files,
drom
generates a file .drom in the project. This file should be committed in the repository with the files, so thatdrom
can always use it to detect changes.Every time
drom
skips a file because it has been modified, it saves the new version in the_drom/skipped/
directory.For example, if
drom
outputs:[...] Skipping modified file dune-project [...]
You can use the command:
$ diff dune-project _drom/skipped/dune-project
to see the differences. if the differences are meaningless, you may then decide to promote the new file by removing your file and restarting
drom
.
The [dependencies]
table
This section contains dependencies with their versions. These
dependencies are for libraries only, as they will be added in the
generated dune
files.
For example:
ez_config = "0.1.0"
means that the project should be linked with ez_config
with a
version compatible with 0.1.0
. drom
uses semantic
versioning, so it means version >= 0.1.0
and version <
1.0.0
. If the version is not formatted as X.Y.Z
, drom
will only generate a constraint version >= V
.
Versions can also be specified with some other formats:
Following
opam
conventions :">0.1.0"
for exampleNo constraint specified, with the empty string
""
Using the string
"version"
meaning that the version of the dependency should be the same one as the package
It is possible to specify more information than the version, in which case the dependency object should be seen as a record containing the fields:
version
for the version of the dependencylibname
for the name of the dependency that should be used as a dependency indune
filesfor-test
for a boolean specifying if the dependency is only needed for tests (with-test
inopam
files)for-doc
for a boolean specifying if the dependency is only needed for tests (with-doc
inopam
files)
For example:
[dependencies]
ez-config = { version = "0.1.0", libname = "ez_config" }
or equivalently:
[dependencies.ez-config]
version = "0.1.0"
libanem = "ez_config"
meaning that the project depends on the opam
package
ez-config
, and that it should be linked with the corresponding
library ez_config
.
The [tools]
table
This section contains dependencies that will appear in the
opam
files, but not as libraries in the dune
files.
The [package]
table
The package
table has one entry per package (library or
program) included in the project. One of the packages must have the
same name as the project.
The most important field of the package description in the
drom.toml
file is the dir
field. drom
expects
to find a package.toml
file in that directory with more
information on the packages.
Yet, it is possible to inline these fields also in the
drom.toml
file, but drom.toml
will move them to their
package.toml
file if you ask it to upgrade the file (using
drom project --upgrade
). You can check the list of available
fields in the documentation of package.toml
.
The [fields]
table
The fields
table contains fields that will be added to the
the dune-project
file. There is two fields may be used :
dune-project-header
dune-project-trailer
The first one add verbatim content to the dune-project
file, right
after the (lang dune X.Y)
line. The second one add verbatim content
at the end of file.
Using those fields may be required when using very specific dune
build feature that are not handled by drom
. For example, using
the parser generator menhir
for non trivial cases will likely need
such tuning.
The package.toml
Files
Every package source directory (as specified by the dir
field
of each [[package]]
entry in the drom.toml
file) can
contain a package.toml
file.
For example:
$ less src/drom_lib/package.toml
gen-version = "version.ml"
kind = "library"
name = "drom_lib"
pack-modules = true
[dependencies]
directories = "0.2"
ez_cmdliner = "0.1.0"
ez_config = "0.1.0"
ez_file = "0.2.0"
opam-file-format = "2.1.1"
toml = "5.0.0"
[fields]
dune-libraries = "bigarray"
The following fields are allowed in a package definition:
dir
: the directory of the package sources (defaults tosrc/${name}/
dependencies
: theopam
library dependencies of this packagegenerators
: the list of program for which specificdune
targets should be generated. Defaults to an empty list, but the project can define its own list ([ "ocamllex" ; "ocamlyacc" ]
by default). The generatormenhir
is also available.gen-version
: whether aversion.ml
file should be createdkind
: the kind of the package (library
orprogram
)name
: the name of the package (under which it will be published inopam
pack
: if modules should be wrapped, the name of the wrapper module (defaults to the capitalized name of the library otherwise)skeleton
: the skeleton to be used to generate the files of this project (defaults to"program"
). See the section on skeletons for more info.tools
: theopam
tools dependencies of this package
The following fields are also allowed, and default to the project ones if not specified:
authors
: the authors of the packagedescription
: the full description of the packagemode
: the mode of the package (binary
orjavascript
)pack-modules
: whether modules should be wrapped or notsynopsis
: the one-line description of the packageversion
: the version of this package
For menhir
usage, you will find an optional [menhir]
talbe,
with the following fields:
* version
: the version of the menhir language configuration
* parser
: a table with the following fields:
modules
: an array of string with all your menhir modules
merge-into
: an optional string for the name of the merged module, by default the last value in themodules
array if not provided
tokens
: an optional to add the--external-tokens
flag
flags
: an optional string array with menhir flags
infer
: an optional boolean which adds the(infer <bool>)
rule to thedune
file
tokens
: an optional table that will add the –only-tokens flag to themenhir
rule with the following fiels: *modules
: a string array with all the modules to add to the rule *flags
: an optional string array with all the flags to add to menhir
Finally, there is a table [fields]
within a
package. Currently, the following fields are used by skeletons:
dune-libraries
: extra libraries that can be added in thelibraries
field ofdune
. Typically for internal libraries.dune-stanzas
: extradune
stanzas in the descriptiondune-trailer
: a string that is added at the end of thedune
file.opam-trailer
: a string that is added at the end of theopam
file for the package.
In skeletons, fields are referenced using parens (for example
!(dune-stanzas)
).
Skeletons
drom
generates most of the files using template files stored
in skeletons on which substitutions are applied.
There are two kinds of skeletons:
Project skeletons are used to create and update most of the files of the project, excluding package specific files.
Package skeletons are used to create and update package specific files, mostly
dune
and sources files
When drom
is called in a project, it generates a file
_drom/known-skeletons.txt
listing all the skeletons it knows
about. Beware that, if you create a new skeleton, you will have to
share it for other users to be able to use drom
on the project
to update generated files.
Project Skeletons
Default project skeletons are defined in the source tree in: https://github.com/OCamlPro/drom/tree/master/src/drom_lib/skeletons/projects
The following project skeletons are available by default:
The
virtual
skeleton is for a “meta” project, i.e. a project containing other packages, but whose main package (with the name of the project) does not define a program or library. This skeleton can be seen as the root of the inheritance tree between project skeletons.Files:
$ drom new VIRTUAL --skeleton virtual └── VIRTUAL/ ├── .drom (drom state, do not edit) ├── .github/ │ └── workflows/ │ ├── doc-deploy.yml │ └── workflow.yml ├── .gitignore ├── .ocamlformat ├── .ocamlformat-ignore ├── .ocp-indent ├── CHANGES.md ├── LICENSE.md ├── Makefile ├── README.md ├── docs/ │ ├── README.txt │ ├── doc/ │ │ └── index.html │ ├── favicon.png │ ├── index.html │ ├── sphinx/ │ │ └── index.html │ └── style.css ├── drom.toml <────────── project config EDIT ! ├── dune ├── dune-project ├── sphinx/ │ ├── _static/ │ │ └── css/ │ │ └── fixes.css │ ├── about.rst │ ├── conf.py │ ├── index.rst │ ├── install.rst │ └── license.rst ├── src/ │ └── VIRTUAL/ │ └── package.toml <────────── package config EDIT ! └── test/ ├── expect-tests/ │ ├── dune │ └── test.ml ├── inline-tests/ │ ├── dune │ └── test.ml └── output-tests/ ├── dune ├── test1.expected ├── test2.expected └── test2.ml
Notice that there are no
.opam
file generated by default in thevirtual
skeleton, until you add other packages usingdrom package XXX --new SKELETON
The
library
skeleton contains only a library package. It inherits from thevirtual
skeleton.Files:
$ drom new LIBRARY --skeleton library └── LIBRARY/ │ . (same as virtual ) . ├── LIBRARY.opam ├── src/ │ └── LIBRARY/ │ ├── dune │ ├── index.mld │ ├── main.ml │ ├── package.toml <────────── package config EDIT ! │ └── version.mlt └── test/ . . (same as virtual )
The
program
skeleton contains both a library and a driver packages. It inherits from thevirtual
skeleton. It is the default project skeleton used when nothing is specified.Files:
$ drom new PROGRAM --skeleton program └── PROGRAM/ │ . (same as virtual ) . ├── PROGRAM.opam ├── PROGRAM_lib.opam ├── src/ │ ├── PROGRAM/ │ │ ├── dune │ │ ├── index.mld │ │ ├── main.ml │ │ └── package.toml <────────── package config EDIT ! │ └── PROGRAM_lib/ │ ├── dune │ ├── index.mld │ ├── main.ml │ ├── package.toml <────────── package config EDIT ! │ └── version.mlt └── test/ . . (same as virtual )
The
mini-lib
skeleton contains a library package, with a minimal set of files (no test, no docs, etc.) (since version 0.2.2)Files:
$ drom new MINI-LIB --skeleton mini-lib └── MINI-LIB/ ├── .drom (drom state, do not edit) ├── .gitignore ├── CHANGES.md ├── LICENSE.md ├── MINI-LIB.opam ├── Makefile ├── README.md ├── drom.toml <────────── project config EDIT ! ├── dune ├── dune-project └── src/ └── MINI-LIB/ ├── dune ├── package.toml <────────── package config EDIT ! └── version.mlt
The
mini-prg
skeleton contains a program package, with a minimal set of files (no test, no docs, etc.) (since version 0.2.2)Files:
$ drom new MINI-PRG --skeleton mini-prg └── MINI-PRG/ ├── .drom (drom state, do not edit) ├── .gitignore ├── CHANGES.md ├── LICENSE.md ├── MINI-PRG.opam ├── MINI-PRG_lib.opam ├── Makefile ├── README.md ├── drom.toml <────────── project config EDIT ! ├── dune ├── dune-project └── src/ ├── MINI-PRG/ │ ├── dune │ └── package.toml <────────── package config EDIT ! └── MINI-PRG_lib/ ├── dune ├── package.toml <────────── package config EDIT ! └── version.mlt
The
ppx_deriver
skeleton contains a library package that defines a ppx_deriver, with a minimal example of code. (since version 0.2.2)Files:
$ drom new PPX_DERIVER --skeleton ppx_deriver └── PPX_DERIVER/ │ . (same as virtual ) . ├── PPX_DERIVER.opam ├── src/ │ └── PPX_DERIVER/ │ ├── dune │ ├── index.mld │ ├── main.ml │ ├── package.toml <────────── package config EDIT ! │ └── version.mlt └── test/ . . (same as virtual )
Package Skeletons
Default package skeletons are defined in the source tree in: https://github.com/OCamlPro/drom/tree/master/src/drom_lib/skeletons/packages
The following package skeletons are available by default:
The
virtual
skeleton is an empty skeleton.The
library
skeleton contains a simple library.The
program
skeleton contains a simple program.The
driver
skeleton contains a simple program that only calls the main entry point of an associated library.The
ppx_deriver
skeleton contains a simple library that defines a ppx_deriver.
Note that the project program
skeleton combines a
library
package skeleton with a driver
package
skeleton.
User-specified skeletons
Users can create their own skeletons. Check the documentation on Contributing Your Own Skeletons